with one click
ws
// Manage parallel multi-repo development workspaces using the ws CLI tool. Use when the user wants to create, update, tear down, or inspect workspaces, or mentions workspaces or parallel dev environments.
// Manage parallel multi-repo development workspaces using the ws CLI tool. Use when the user wants to create, update, tear down, or inspect workspaces, or mentions workspaces or parallel dev environments.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | ws |
| description | Manage parallel multi-repo development workspaces using the ws CLI tool. Use when the user wants to create, update, tear down, or inspect workspaces, or mentions workspaces or parallel dev environments. |
| argument-hint | up <name> <repo[:branch]...> |
All workspace operations go through a single CLI — run it for full docs:
uv run {{SKILL_PATH}}/scripts/ws.py --help
See ws.py --help for the two-agent role model (Creator vs Workspace Claude) and safety rules.
ws.py. Never reach behind it — no pkill, no killing PIDs directly, no spawning serve processes by hand, no reconstructing commands from ps output, no touching route-configs or state files directly. If you think you need to, you don't; there is a ws.py command for it.ws.py nuke --delete-branches does this, and confirm with the user first.ws.py nuke without explicit user confirmation. Nuke is irreversible — it deletes all workspace files and kills the tmux session. Do not infer that nuke is the right move; the user must explicitly ask to tear down or delete the workspace. Do NOT use nuke to remove a single repo, switch branches, free memory, or resolve a stuck serve — use restart or recreate with the desired repos instead.ws.py init launches the workspace Claude, the creator is done.103830646The creator reads this section to handle user requests. The workspace Claude never sees it.
When the user invokes this skill (via /ws or natural language), route based on intent:
Creating a workspace belowAdding repos belowws.py nuke <name>. Do not run nuke just because a workspace needs different repos or a branch change — those don't require a full teardown.If repos are given in natural language, confirm your interpretation before proceeding.
/ws up <name> <repo[:branch]>...
Run ws.py plan — if ok: false, show missingRepos and stop.
uv run {{SKILL_PATH}}/scripts/ws.py plan <name> <repo1> <repo2:branch>...
Briefly state what you're doing (one line — workspace name + repos). Don't wait for approval; proceed straight to step 3. Tell the user init will take a few minutes and that the workspace Claude will report serve status from inside the tmux session.
Run ws.py init in the background:
a. Launch init in the background (Bash with run_in_background: true) — it will notify you when done:
uv run {{SKILL_PATH}}/scripts/ws.py init <name> \
--repos <repo1>:<branch1> <repo2>:<branch2> ... \
--prompt "<handoff prompt text>"
See "Building the handoff prompt" below for the prompt template.
Always run ws.py list before init to check headroomMB. See ws.py prefs --help for memory configuration.
b. When the background init task completes, parse the JSON result.
DO NOT start a Monitor to follow serve logs. The workspace Claude runs inside the tmux session and is solely responsible for monitoring serve progress and reporting ready/error status. Watching logs from the creator duplicates that work, fills your context with noise, and is the wrong agent for the job.
Tell the user how to access the new workspace (from init's JSON output) and that they should tmux attach -t <name> to see the workspace Claude's status report. The creator's job is done — do not continue monitoring, polling, or checking serve status.
/ws up <name> <new-repo>... when the workspace already exists (plan output has existing: true):
Tell the user to switch to the workspace and ask the workspace Claude to run ws.py add <name> <new-repo>.... The creator does NOT do this work.
Pass this as the --prompt string to ws.py init. Template:
You are starting in the <WORKSPACE_NAME> workspace.
REPOS (already cloned + serve already running):
- <repo1>:<branch1>
- <repo2>:<branch2>
<optional: TASK CONTEXT: <user's intent, if they provided one>>
<paste Section 3 below verbatim here>
The REPOS: block is informational only — ws.py init has already cloned them and started serve. Workspace Claude just confirms status and reports.
Everything below this line is included verbatim in the handoff prompt. The workspace Claude only sees this section (plus the header with repo details).
ws.py. Never reach behind it — no pkill, no killing PIDs directly, no spawning serve processes by hand, no reconstructing commands from ps output, no touching route-configs or state files directly. If you think you need to, you don't; there is a ws.py command for it.ws.py nuke without explicit user confirmation. Nuke is irreversible. Do not use it to remove a single repo, switch branches, free memory, or resolve a stuck serve — try restart first. Only run nuke when the user explicitly asks to tear down and discard the workspace.Setup was already done by ws.py init before you spawned. Run the post-init startup sequence from ws.py init --help, sequentially and exactly once. If the log-check returns hits, use the "Setup failed" template. Otherwise use "Workspace ready". Never skip the log check.
If the user asks to add a repo, use ws.py add <name> <repo>:<branch>. If resuming a workspace whose files exist but serve is down, use ws.py setup <name>.
Bend tools are deferred — schemas aren't loaded until you fetch them via ToolSearch with query bend. If the tool isn't in your immediate list, search first; don't conclude it's missing. Never fall back to shell tsc/jasmine. Tests take 2–5 min, TS checks up to 120s — don't restart serve because tests are slow.
See ws.py help monitor and ws.py help templates.
At milestones or exit, update ~/src/workspaces/<WORKSPACE_NAME>/CONTEXT.md with sections: Goal, Status, Next steps, Branches, Notes. Keep it to non-obvious state — not anything derivable from code or git log.