What happened
sp-canvas status prints a canvas's state without ever consulting the server it is
reporting on. Both lines below it are guesses, and both can be wrong in ways that
send you off debugging the wrong thing.
Two separate defects, same function (cmd_status):
1. The boards line follows the caller's cwd, not the running server
A canvas started with an explicit --canvases path reports a different boards
directory depending on where you ask from — and none of the answers is the one it
is actually serving:
$ cd ~/proj && sp-canvas start --port 5174 --canvases prototypes/mockups/canvases
boards /home/me/proj/prototypes/mockups/canvases # correct, at start
$ cd ~/proj && sp-canvas status --port 5174
boards would be /home/me/proj/mockups/canvases # wrong
$ cd /tmp && sp-canvas status --port 5174
boards would be /tmp/mockups/canvases # wrong
$ cd ~/other-repo && sp-canvas status --port 5174
boards would be /home/me/other-repo/mockups/canvases # wrong
cmd_status recomputes the path from the calling process instead of reading it
back from the server:
# sp_canvas.py, cmd_status
print(f"boards would be {_canvases_dir(a.canvases)}")
# _canvases_dir — resolves against the current process's cwd/args/env
raw = arg or os.environ.get("PROTOTYPING_CANVASES_DIR") or "mockups/canvases"
return Path(raw).expanduser().resolve()
The value is already known at start time — cmd_start holds boards and passes it
to the child as PROTOTYPING_CANVASES_DIR — but the pidfile only keeps the pid:
_pidfile(a.port).write_text(f"{proc.pid}\n")
The phrasing "boards would be" is accurate when nothing is running, and that
case is genuinely useful. The problem is that the same line prints verbatim under
port 5174: answering, where readers take it as a description of the live server.
This is not hypothetical: it cost me a real debugging detour. I had two canvases up
on different ports and used status to work out which one was serving my project's
boards. It confidently pointed at a directory that did not even exist. Reading
PROTOTYPING_CANVASES_DIR off the process (ps -E -o command -p <pid>) gave the
right answer immediately.
2. status treats any listener on the port as a canvas
cmd_status only calls _port_answers(), a bare connect_ex. Anything answering
is reported as ours, including the tmux session line — for a session that does not
exist:
$ python3 -m http.server 5999 --bind 127.0.0.1 &
$ sp-canvas status --port 5999
port 5999: answering
http://127.0.0.1:5999/
session canvas-5999 # no such tmux session
boards would be /home/me/whatever/mockups/canvases
cmd_stop gets this right — it checks the pidfile, drops stale pids, and says so
when the port belongs to someone else:
(something else is answering on {port} — left alone)
start is careful here too, refusing to reuse a port that already answers because
it may be another checkout's canvas. status is the one command that will tell you
a stranger's server is yours.
Where
- Canvas or skill:
sp-canvas CLI (tools/), cmd_status
- Hosted or local dev server: local dev server
- Browser / device / OS: n/a (CLI); macOS 15.1, Darwin 25.1.0
- Versions: plugin 1.4.1, toolkit 1.4.1 (
sp-canvas root -v)
How to reproduce
Defect 1
cd ~/proj && mkdir -p prototypes/mockups/canvases
sp-canvas start --port 5174 --canvases prototypes/mockups/canvases — note the
boards line it prints, which is correct
sp-canvas status --port 5174 from ~/proj, then from /tmp, then from any
other directory
- Each run reports a different boards path; none matches step 2
Defect 2
python3 -m http.server 5999 --bind 127.0.0.1 &
sp-canvas status --port 5999
- It reports
session canvas-5999 and a boards path for a server that has nothing
to do with sp-canvas
Suggested fix
Both come down to status reporting what it guessed rather than what is running.
- Have
cmd_start write the boards path into the pidfile next to the pid (or a
sibling file), and have cmd_status read it back when the port answers. Reading
PROTOTYPING_CANVASES_DIR from the live process works too and needs no format
change, at the cost of being platform-specific.
- Reuse the pidfile/stale-pid check
cmd_stop already has, so status can
distinguish "our canvas", "a stale pidfile", and "something else is on this port".
- Keep
boards would be ... for the not-running case — it answers a real question
("what would start pick up from here?"). Print the server's actual directory
when one is answering.
Happy to send a PR if the approach looks right.
What happened
sp-canvas statusprints a canvas's state without ever consulting the server it isreporting on. Both lines below it are guesses, and both can be wrong in ways that
send you off debugging the wrong thing.
Two separate defects, same function (
cmd_status):1. The
boardsline follows the caller's cwd, not the running serverA canvas started with an explicit
--canvasespath reports a different boardsdirectory depending on where you ask from — and none of the answers is the one it
is actually serving:
cmd_statusrecomputes the path from the calling process instead of reading itback from the server:
The value is already known at start time —
cmd_startholdsboardsand passes itto the child as
PROTOTYPING_CANVASES_DIR— but the pidfile only keeps the pid:The phrasing "boards would be" is accurate when nothing is running, and that
case is genuinely useful. The problem is that the same line prints verbatim under
port 5174: answering, where readers take it as a description of the live server.This is not hypothetical: it cost me a real debugging detour. I had two canvases up
on different ports and used
statusto work out which one was serving my project'sboards. It confidently pointed at a directory that did not even exist. Reading
PROTOTYPING_CANVASES_DIRoff the process (ps -E -o command -p <pid>) gave theright answer immediately.
2.
statustreats any listener on the port as a canvascmd_statusonly calls_port_answers(), a bareconnect_ex. Anything answeringis reported as ours, including the tmux session line — for a session that does not
exist:
cmd_stopgets this right — it checks the pidfile, drops stale pids, and says sowhen the port belongs to someone else:
startis careful here too, refusing to reuse a port that already answers becauseit may be another checkout's canvas.
statusis the one command that will tell youa stranger's server is yours.
Where
sp-canvasCLI (tools/),cmd_statussp-canvas root -v)How to reproduce
Defect 1
cd ~/proj && mkdir -p prototypes/mockups/canvasessp-canvas start --port 5174 --canvases prototypes/mockups/canvases— note theboardsline it prints, which is correctsp-canvas status --port 5174from~/proj, then from/tmp, then from anyother directory
Defect 2
python3 -m http.server 5999 --bind 127.0.0.1 &sp-canvas status --port 5999session canvas-5999and a boards path for a server that has nothingto do with sp-canvas
Suggested fix
Both come down to
statusreporting what it guessed rather than what is running.cmd_startwrite the boards path into the pidfile next to the pid (or asibling file), and have
cmd_statusread it back when the port answers. ReadingPROTOTYPING_CANVASES_DIRfrom the live process works too and needs no formatchange, at the cost of being platform-specific.
cmd_stopalready has, sostatuscandistinguish "our canvas", "a stale pidfile", and "something else is on this port".
boards would be ...for the not-running case — it answers a real question("what would
startpick up from here?"). Print the server's actual directorywhen one is answering.
Happy to send a PR if the approach looks right.