Imported from switchroom/switchroom (
skills/switchroom-cli/SKILL.md). Install upstream withnpx skills add switchroom/switchroom --skill switchroom-cli. Copyright stays with the author.
Switchroom CLI operations
This skill is the reference for running switchroom CLI commands against existing agents. Each section below is triggered by a distinct user intent — jump to the relevant one rather than walking top-to-bottom.
Four commands to know:
switchroom update— full operator path: pulls images + applies config + recreates containers + runs doctor (since v0.7.8 / #918). What you want 95% of the time.switchroom apply— host/operator-only, for structural changes: refresh per-agent scaffolds and (re)write~/.switchroom/compose/docker-compose.yml. Its full per-agent scaffold cannot run from inside an agent container (no vault at the container HOME, nodocker composev2 plugin) — that's correct by construction, not a bug. Version rolls do NOT need it: drive the hostd rollout (mcp__hostd__rollout), which runs a--compose-onlyapply plus a per-agent restart-reconcile that refreshes each agent's templates automatically. Reserve a host-sidesudo switchroom applyfor compose regeneration / new-agent scaffolding.switchroom restart [agent]— bounces a stuck or wedged agentswitchroom version— shows what's running (versions + health summary)
Prerequisite: the switchroom CLI must be on PATH. If it isn't, direct the user to the switchroom-install skill.
Logs — "show me the logs", "what happened", "why did it crash"
Fetch recent journal output when the user wants to see what an agent did or is debugging a specific crash.
Step 1 — Identify the agent
If the user didn't name one, ask: "Which agent do you want logs for?" Then list available agents:
switchroom agent list
Step 2 — Tail the logs
Default is the last 20 lines. User can specify a number. Use the CLI if available; fall back to docker compose logs when it's not:
switchroom agent logs <name> [--lines 50]
# or, when switchroom CLI isn't reachable:
docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml logs --tail 50 switchroom-<name>
Step 3 — Present output
Include the last ~20 lines verbatim, then summarise what you see (crash, stall, normal chatter). If the user asked "why did it crash" and you don't see a clear cause, say so and offer /doctor as the next step.
Update — "update", "pull latest", "get new code", "upgrade"
Use the switchroom update verb (since v0.7.8 / #918). It collapses pull + apply + recreate + doctor into one command.
switchroom update # pull images + apply + recreate + run doctor
switchroom update --check # dry-run: print the plan, exit 0
switchroom update --status # read-only: CLI version + image/container ages
switchroom update --rebuild # source-checkout users: also git pull + npm build
switchroom update is the operator path. The CLI self-elevates via sudo internally for the per-agent scaffold dirs that need root — no need for sudo HOME=… PATH=… incantations.
If you only need the config-reconcile half without restarting agents, switchroom apply (run on the host by the operator) writes ~/.switchroom/compose/docker-compose.yml and refreshes per-agent scaffolds without touching running containers. The operator runs the docker bring-up themselves. Note this full apply cannot run from inside an agent container by construction — to roll the fleet to a new version from an agent, use the hostd rollout (mcp__hostd__rollout) instead of a full apply.
From inside an agent's Telegram DM, the same flow is available as /upgradestatus (read-only) and /update apply (admin-gated).
Restart — "restart", "reboot", "bounce", "it's stuck"
Restart one agent or all. Also covers "refresh", "kick", "kill and restart", "stop and start".
Step 1 — Identify the agent
If the user didn't name one, ask which. Accept all or no argument as "all agents".
Step 2 — Run the restart
# Restart a specific agent (drains in-flight turn by default):
switchroom restart <name>
# Restart all agents:
switchroom restart
# Skip drain — SIGTERM immediately:
switchroom restart <name> --force
The switchroom restart top-level command reconciles + restarts and prints the health summary. It uses drain semantics by default (waits up to 60s for an in-flight turn to complete before cycling).
For the lower-level per-agent restart without reconcile, switchroom agent restart <name> is also available.
Step 3 — Confirm
Report the outcome. If the agent is being restarted via Telegram (/restart handler), the user will see a 🔄 Restarting <name>… ack followed by a 🎛️ Switchroom restarted — ready message. Don't double-post.
Version / health summary — "version", "what sha", "are agents up", "health check"
Show switchroom version, claude-code version, and the running status of all agents.
switchroom version
Output format:
✓ claude-code 2.1.119
✓ switchroom 0.3.0 / 7278044 (clean)
✓ klanker → up 5m, on 7278044
✓ gymbro → up 4h, on 7278044
✓ foreman → up 2d, on 7278044
No side effects. Safe to run at any time.
Config inspection — "what model is X using", "show config for "
Surface the resolved effective config for a specific agent. Use for "how is X configured", "what tools does X have", or cascade-resolution questions.
Step 1 — Pick the right inspector
For a high-level view (model, profile, topic, status, uptime):
switchroom agent list --json
For the full merged settings file (tools, hooks, MCP servers):
cat ~/.switchroom/agents/<name>/.claude/settings.json
For the exact prompt + system message an agent sends Claude on its next turn:
switchroom debug turn <name>
For the rendered workspace bootstrap block (CLAUDE.md, SOUL.md, skills wiring):
switchroom workspace render <name>
debug turn and workspace render are the authoritative answers when the user asks "why is X behaving this way" or "what is X actually being told".
Step 2 — Explain the cascade
Agent config resolves through defaults → extends profile → agent-specific, with later keys winning. If the user asks why a value is set the way it is, walk them through which layer contributed it.
Auth — "share my Pro account across agents", "auth verbs", "who's logged into what"
The Anthropic account is the unit of authentication — one OAuth flow per account, then "use this account on these agents" is fleet-wide config (not another OAuth round per agent). The switchroom-auth-broker daemon is the sole writer of every credentials.json; agents are passive readers. See docs/auth.md for the full model.
CLI verbs
# Add an account (one OAuth flow per account, ever)
switchroom auth add <label> --from-oauth # interactive OAuth
switchroom auth add <label> --from-agent <name> # seed from an existing agent's creds
switchroom auth add <label> --from-credentials <path> # import a credentials.json
switchroom auth add <label> --from-oauth --replace # re-auth an existing label (drift recovery)
# See the state of the fleet
switchroom auth list # accounts + health + which one is active
switchroom auth show # full snapshot (fleet + agents + consumers)
switchroom auth show <agent> # one agent's effective account + override
# Move the fleet to a different account
switchroom auth use <label> # fleet-wide active swap
switchroom auth rotate # cycle to next non-exhausted in fallback_order
# Manage accounts
switchroom auth rm <label> # refused if it's the only account
# Edge case: per-agent override (opts one agent out of the fleet active)
switchroom auth agent override <agent> <label>
switchroom auth agent override <agent> --clear
# Diagnostics (broker owns the refresh loop; this just forces a tick)
switchroom auth refresh # all accounts
switchroom auth refresh <label> # one account
Schema
auth:
active: me@example.com # fleet-wide active account
fallback_order: # ordered cycle list for `auth rotate`
- me@example.com
- work
- personal
agents:
ziggy: {} # inherits fleet active
clerk:
admin: true # gates /agents, /restart, /update AND admin /auth verbs
klanker:
auth:
override: work # opt-out (edge case)
Most agents need no auth: block — they inherit auth.active. The pre-RFC-H per-agent auth.accounts: [...] and auth_label: fields are gone; replace them with fleet-wide auth.active + (rarely) agents.<name>.auth.override.
Telegram surface
Three commands the gateway recognises in any agent chat:
/auth show— fleet snapshot. Open to any agent (read-only)./auth use <label>— admin agents only./auth rotate— admin agents only.
These replaced the v0.7-era /auth dashboard UI (a 1100-LOC slot-model promote UI, deleted in the broker rollout).
When auth-related questions come in
- "I want one Pro/Max subscription on multiple agents" → that's just the default.
switchroom auth add me@example.com --from-oauth, thenswitchroom auth use me@example.com. Every agent in the fleet inherits. - "An agent's auth expired" →
switchroom auth listfirst. If broker thinks the account is healthy but the agent isn't getting it, force a tick withswitchroom auth refresh(diagnostic; the broker normally handles this on its own loop). - "I hit a quota" →
switchroom auth rotatecycles to the next non-exhausted account infallback_order. Quota state is per-account and fans out in seconds across every agent on that account.
Scheduled tasks — "what cron runs", "show me the timers"
List cron jobs and scheduled tasks.
Step 1 — Show live timers
Since Phase 4 (#893) cron runs in-container as the agent-scheduler
sidecar inside each agent — the old switchroom-<agent>-scheduler /
switchroom-cron singleton container no longer exists. Inspect fired
jobs in the agent's own log; scheduler lines are prefixed
agent-scheduler::
docker logs --tail 100 switchroom-<agent> 2>&1 | grep agent-scheduler:
Step 2 — Show declared schedule entries
From switchroom.yaml, the schedule: array under each agent specifies cron + prompt. (A model: field may appear but is ignored — since the v0.8 cron-fold-in the fire runs in the agent's existing session and uses the agent's configured model, not a per-task one. Don't tell the user a per-task model is honoured.) Cron expressions are evaluated in the agent's resolved timezone (the switchroom.timezone / per-agent timezone cascade), not hard-coded UTC. Read the relevant agent block and enumerate the entries with their next-fire times in that zone.
Step 3 — A schedule change is NOT live until the agent restarts
The in-container agent-scheduler reads its entries once at boot. Editing the schedule: array in switchroom.yaml, or adding/removing an entry via the agent-config schedule add / schedule remove tools, writes the change to disk but does not register it in the running scheduler. The same is true for skill_install and .mcp.json changes — claude loads skills and MCP servers at process start.
So whenever you (or the user) change a schedule, skill, or MCP config:
- The
schedule add/skill_installtool result includesrestart_required: trueand arestart_hint. Surface it. Tell the user plainly that the change is on disk but won't take effect untilswitchroom agent restart <name>(orswitchroom restart <name>for the reconcile+restart path). - Never report a just-added schedule or skill as already active. It is staged, not live.
Step 4 — Missed runs while the agent was offline
If the user asks whether scheduled runs were missed during downtime: the scheduler replays fires missed within the last ~30 min on boot, but runs older than that window are not re-run (cron is not a queue). It is not silent about this — on boot it emits a one-time notice listing every schedule that had a skipped run, delivered as a normal turn and recorded in agent-scheduler: log lines / /state/agent/scheduler.jsonl. Check those to answer honestly; never claim a run happened if the skip notice says it was dropped.
Hindsight model change — "swap the memory model", "move retain off the subscription"
Changing which LLM runs Hindsight's retain / reflect / consolidation ops is a
config-plus-recreate operation with three known traps. Follow the runbook:
docs/operators/hindsight-model-change.md. The short version:
- Edit
hindsight.llm.{retain,reflect,consolidation}in the operator'sswitchroom.yaml— keep the outgoing block in a dated comment for rollback. - Pick a full lane: non-Claude via LiteLLM needs
provider: litellm+model+base_url+api_key; subscription Claude needsprovider: claude-code+ a Claude model name with NO base_url/api_key. A per-opmodel:alone does not reroute (docs/model-routing.md G1/G5). - Apply with
switchroom memory setup --recreateon the host — a plaindocker restartdoes not re-derive env, and running the CLI inside an agent container silently reads the staleSWITCHROOM_CONFIGsnapshot. - Verify with
docker inspect switchroom-hindsight:HINDSIGHT_API_<OP>_LLM_MODEL/_PROVIDER/_BASE_URLmatch the yaml, and health reacheshealthy. docker restart switchroom-hostdafter the yaml edit, and re-verify after any fleet rollout — the singletons bind-mount the yaml as a single file, so an atomic (rename-based) edit leaves them pinned to the stale old inode and a hostd-driven rollout can silently revert the model change.
Telegram plugin reference — "what MCP tools", "how does reply work"
The switchroom-telegram plugin is an enhanced fork of the official Telegram MCP plugin and is the default for all switchroom agents. It exposes 20+ MCP tools (all prefixed mcp__switchroom-telegram__; the authoritative list is the tool declarations in telegram-plugin/bridge/bridge.ts). The core messaging set:
| Tool | Purpose |
|---|---|
reply |
Send a text/photo message — the single final-answer tool; chunks anything over the 32768-char rich-message cap (4096 applies only to plain-text degradations). Optional reply_to for threaded quotes |
react |
Emoji reaction on an inbound or outbound message |
edit_message |
Modify an earlier bot message's text |
delete_message |
Remove an earlier bot message |
forward_message |
Forward a message from another chat |
send_typing |
Show the "typing…" indicator |
download_attachment |
Save a Telegram file attachment to the agent's inbox |
get_recent_messages |
Fetch recent history for context |
Additional features:
- Status reactions — 👀 queued → 🤔 thinking → 👨💻 tool → 🔥 streaming → 👍 done
- Progress cards — pinned, live-updating tool-step summary
- SQLite history — enables quote-reply defaults
- PI-safe envelope — inbound text wrapped in
<channel source="telegram">for prompt-injection safety - Inline approvals — tool permissions surface as ✅/❌ buttons or via
/approve/deny/pending - Slash commands —
/new,/reset,/approve,/deny,/pending,/restart,/update,/version,/logs,/doctor,/auth,/switchroomhelp(seeTELEGRAM_MENU_COMMANDSintelegram-plugin/welcome-text.ts) /auth— three chat commands:/auth show(read-only, open to any agent),/auth use <label>and/auth rotate(admin agents only). Backed by the auth-broker — see the Auth section above anddocs/auth.mdfor the full model.- Access control —
dmPolicy: pairing | allowlist | disabledper agent
Rule of thumb
If the user is asking "do X", this is your skill. If they're asking "why is X broken", switch to switchroom-health. If they're asking "how do I add/remove an agent", switch to switchroom-manage. If they're new and don't have switchroom yet, switch to switchroom-install.