diff --git a/.claude/skills/run-app/SKILL.md b/.claude/skills/run-app/SKILL.md index be3b2cf34..c7e2c480a 100644 --- a/.claude/skills/run-app/SKILL.md +++ b/.claude/skills/run-app/SKILL.md @@ -162,25 +162,37 @@ committing. `bun run dev:tauri` carries a development-only bridge, so you can inspect the WKWebView the app ships with, not Chrome. Drive it with `tauri-mcp`. -**Launching the app is not isolated by `NODESPACE_HOME`.** It installs the -sidecars into `~/.nodespace/bin`, kills a daemon on the default socket, and -registers the debug launchd label (`app.nodespace.daemon.dev`), which is per user, -not per `HOME`. A running dev daemon of the user's would be booted out. So: - -1. Pick a short scratch home (`/tmp/nsh`) and pre-seed it: copy +**Launching the app cannot be isolated from the user's service registration.** +It installs the sidecars into `~/.nodespace/bin`, kills a daemon on the default +socket, and registers the debug launchd label (`app.nodespace.daemon.dev`). That +label is per user, so neither `HOME` nor `NODESPACE_HOME` scopes it, and the app +re-registers it whenever it rebuilds or finds a changed sidecar. A scratch +`HOME` keeps the files and database out of the real home; it does **not** stop +the app replacing the user's loaded job with one pointing at the scratch install. +Pre-seeding the sidecars only avoids re-registration while they stay unchanged +and validly signed, and `dev:tauri` rebuilds them first, so do not rely on it. +Get the user's go-ahead before launching it, and restore afterwards. + +1. Note the user's job: `launchctl print gui/$(id -u)/app.nodespace.daemon.dev` + (its `path`, `program` and `pid`). +2. Pick a short scratch home (`/tmp/nsh`) and pre-seed it: copy `target/debug/binaries/nodespaced-` and `nodespace-` to `/tmp/nsh/.nodespace/bin/nodespaced` and `nodespace`. -2. Start that daemon with `HOME=/tmp/nsh`, +3. Start that daemon with `HOME=/tmp/nsh`, `NODESPACED_SOCKET=/tmp/nsh/.nodespace/daemon-dev.sock`, `NODESPACE_HOME=/tmp/nsh/.nodespace`. The log must say `/tmp/nsh/...`, never `/Users//.nodespace/`. -3. Launch with `HOME=/tmp/nsh CARGO_HOME=… RUSTUP_HOME=… bun run dev:tauri` +4. Launch with `HOME=/tmp/nsh CARGO_HOME=… RUSTUP_HOME=… bun run dev:tauri` (literal paths for the two; a scratch HOME otherwise downloads a toolchain). Do not set `NODESPACED_SOCKET` for the app: the app registers a daemon on its home socket, so the two must agree. -4. Before and after, `launchctl list | grep nodespace` must show the same pid. - -A session that cannot set `HOME` (a worktree-isolated agent) cannot do step 2 -or 3; have the user run them in their own terminal. +5. Afterwards restore the registration: `launchctl bootout + gui/$(id -u)/app.nodespace.daemon.dev`, then `launchctl bootstrap + gui/$(id -u) `, and confirm `path` and + `program` match step 1 (the `pid` will differ: the job restarts). Stop the + scratch daemon and remove `/tmp/nsh`. + +A session that cannot set `HOME` (a worktree-isolated agent) cannot do step 3 +or 4; have the user run them in their own terminal. ```bash bunx tauri-mcp driver-session start # 127.0.0.1:9223; --port N for another app