switchroom 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +26 -11
  2. package/dist/auth-broker/index.js +1 -1
  3. package/dist/cli/skill-validate-pretool.mjs +7209 -0
  4. package/dist/cli/switchroom.js +869 -430
  5. package/dist/vault/broker/server.js +31 -22
  6. package/package.json +3 -2
  7. package/profiles/_shared/agent-self-service.md.hbs +1 -1
  8. package/skills/skill-creator/SKILL.md +52 -0
  9. package/telegram-plugin/auth-snapshot-format.ts +5 -5
  10. package/telegram-plugin/dist/gateway/gateway.js +62 -8
  11. package/telegram-plugin/gateway/access-validator.test.ts +8 -8
  12. package/telegram-plugin/gateway/access-validator.ts +1 -1
  13. package/telegram-plugin/gateway/boot-probes.ts +43 -3
  14. package/telegram-plugin/gateway/gateway.ts +72 -0
  15. package/telegram-plugin/recent-outbound-dedup.ts +1 -1
  16. package/telegram-plugin/registry/turns-schema.ts +1 -1
  17. package/telegram-plugin/tests/auth-add-flow.test.ts +1 -1
  18. package/telegram-plugin/tests/auth-command-format2.test.ts +4 -4
  19. package/telegram-plugin/tests/auth-snapshot-format.test.ts +17 -17
  20. package/telegram-plugin/tests/auto-fallback-fleet.test.ts +10 -10
  21. package/telegram-plugin/tests/boot-probes.test.ts +37 -2
  22. package/telegram-plugin/tests/fixtures/service-log-current-claude-code.bin +1 -1
  23. package/telegram-plugin/tests/fleet-state.test.ts +3 -2
  24. package/telegram-plugin/tests/secret-detect-audit.test.ts +1 -1
  25. package/telegram-plugin/tests/secret-detect-pipeline.test.ts +7 -6
  26. package/telegram-plugin/tests/secret-detect-suppressor-no-silent-allow.test.ts +6 -5
  27. package/telegram-plugin/tests/secret-detect.test.ts +8 -8
  28. package/telegram-plugin/tests/vault-grant-inbound-builders.test.ts +8 -8
  29. package/telegram-plugin/tests/vault-request-access-tool.test.ts +51 -0
package/README.md CHANGED
@@ -87,9 +87,12 @@ You (Telegram)
87
87
  ├─ Progress cards ├─ Approval kernel ◄─────┤ settings.json (tools, hooks, MCP)
88
88
  ├─ Pin / unpin lifecycle │ (allow/deny broker) ├─ Hindsight plugin (memory)
89
89
  ├─ SQLite history ├─ Vault broker ◄────────┤ Drive MCP, Playwright MCP, …
90
- ├─ Card-events.jsonl audit │ (cron secrets, IPC) └─ scheduled tasks across reboots
91
- ├─ Emoji reactions │
92
- └─ Format conversion └─ Docker Compose restart (unless-stopped)
90
+ ├─ Card-events.jsonl audit ├─ Auth broker ◄─────────┤ in-agent scheduler sidecar
91
+ ├─ Emoji reactions │ (OAuth refresh, └─ (cron, fires across reboots)
92
+ └─ Format conversion │ sole creds writer)
93
+ ├─ hostd (host-control:
94
+ │ /restart, /update apply)
95
+ └─ Docker Compose restart (unless-stopped)
93
96
  ```
94
97
 
95
98
  See [`docs/architecture.md`](docs/architecture.md) for the process model, IPC layout, supervisor choice, and how each layer maps to the `claude` CLI.
@@ -157,12 +160,13 @@ Then log out and back in so the docker group takes effect, and:
157
160
 
158
161
  ```bash
159
162
  switchroom setup # interactive: Telegram + vault + first agent
160
- switchroom auth add me --via-claude # OAuth into your Claude Pro/Max account, broader scope (first-time setup)
161
- switchroom apply # write ~/.switchroom/compose/docker-compose.yml
162
- docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d
163
+ switchroom apply # regenerate ~/.switchroom/compose/docker-compose.yml
164
+ docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d # bring the fleet up
165
+ switchroom auth add default --via-claude # OAuth your Claude Pro/Max account — run AFTER the fleet is up
166
+ switchroom auth use default # make it the fleet-wide active account
163
167
  ```
164
168
 
165
- After the last command you talk to the agent from Telegram. You don't touch the server again.
169
+ Auth comes *after* the fleet is up on purpose: the `switchroom-auth-broker` is the sole writer of credentials and doesn't exist until the compose stack is running (`switchroom auth …` beforehand just prints a "fleet not up" hint). After this you talk to the agent from Telegram and don't touch the server again. To catch a running host up later — pull images, refresh scaffolds, recreate — use **`switchroom update`**, not a raw `docker compose up` (a bare compose-up on a live fleet skips the operator restart-marker, so the boot cards render as crashes).
166
170
 
167
171
  ### Already have Docker + Node ≥ 20.11
168
172
 
@@ -187,7 +191,7 @@ If you already use Claude Code, this is the shortest path. Inside any session:
187
191
 
188
192
  ### Static binary (planned, not yet shipped)
189
193
 
190
- Pre-built single-binary releases (no Node or Bun required on the host) are scaffolded in [`install.sh`](install.sh) and referenced from the GitHub Releases page, but **the release workflow that publishes those binaries does not yet exist**. Until v0.9, use the one-script or npm paths above. Tracking work: switching the release pipeline to actually upload `switchroom-linux-{amd64,arm64}` and `switchroom-macos-{amd64,arm64}` on every tag.
194
+ Pre-built single-binary releases (no Node or Bun required on the host) are scaffolded in [`install.sh`](install.sh) and referenced from the GitHub Releases page, but **the release workflow that publishes those binaries still does not exist as of v0.12.0**. Use the one-script or npm paths above. Tracking work: switching the release pipeline to actually upload `switchroom-linux-{amd64,arm64}` and `switchroom-macos-{amd64,arm64}` on every tag.
191
195
 
192
196
  ### One-shot happy path (no wizard)
193
197
 
@@ -292,7 +296,8 @@ Disable with `switchroom vault broker disable-auto-unlock`.
292
296
  ```bash
293
297
  switchroom setup # Interactive wizard
294
298
  switchroom doctor # Health check
295
- switchroom apply # Reconcile + (re)write docker-compose.yml; bring fleet up via `docker compose ... up -d`
299
+ switchroom apply # Reconcile + regenerate docker-compose.yml (self-elevates via sudo for scaffolds). Does NOT run docker prints the `up` command
300
+ switchroom update [--check|--status|--rebuild] # Operator catch-up: pull images + apply + recreate fleet + doctor
296
301
  switchroom restart [agent] [--force] # Bounce agent(s); drains in-flight turn by default
297
302
  switchroom version # Show versions + running agent health summary
298
303
 
@@ -304,15 +309,23 @@ switchroom agent bootstrap <name> --profile <p> --bot-token <t> # One-shot scaf
304
309
  switchroom agent reconcile <name|all> # Re-apply switchroom.yaml (without pulling/building)
305
310
  switchroom agent start|stop|restart <name> # Lifecycle (with preflight)
306
311
  switchroom agent interrupt <name> # Cancel in-flight turn without restarting
312
+ switchroom agent unquarantine <name> # Clear a crash-quarantine and resume supervision
307
313
  switchroom agent rename <old> <new> # Rename an agent slug (#168)
308
314
  switchroom agent destroy <name> # Remove from compose + scaffold dir
309
315
  switchroom agent attach <name> # Interactive tmux session
316
+ switchroom agent send <name> <slash-cmd> # Inject a slash command into the agent's tmux pane
310
317
  switchroom agent logs <name> [-f] # View logs
311
318
  switchroom agent grant <name> <tool> # Grant a tool permission
312
319
  switchroom agent permissions <name> # Show allow/deny list
313
320
  switchroom agent dangerous <name> [off] # Toggle full tool access
321
+
322
+ switchroom soul path|show|reset <name> # Manage the agent's user-owned SOUL.md (persona)
323
+ switchroom hostd install|status|uninstall|audit # Host-control daemon (/restart, /update apply, …)
324
+ switchroom drive connect|disconnect <agent> # Per-agent Google Drive OAuth
314
325
  ```
315
326
 
327
+ `switchroom --help` lists every verb (also `deps`, `issues`, `migrate`).
328
+
316
329
  Profiles live in `profiles/` at the repo root. Bundled ones for `--profile`: `coding`, `default`, `executive-assistant`, `health-coach` (the `_base/` dir is framework-internal render templates and is not a user-selectable profile).
317
330
 
318
331
  `switchroom agent create <name> --profile <profile>` does two things in one step:
@@ -351,7 +364,9 @@ The same surface is reachable from Telegram in any agent's chat: `/auth show` (r
351
364
 
352
365
  ### Workspace (agent bootstrap layer)
353
366
 
354
- Each agent has a workspace directory (`~/.switchroom/agents/<name>/workspace/`) with editable stable files (`AGENTS.md`, `SOUL.md`, `USER.md`, `IDENTITY.md`, `TOOLS.md`) and dynamic files (`MEMORY.md`, `memory/YYYY-MM-DD.md`, `HEARTBEAT.md`) that are injected into the model's context at turn time.
367
+ Each agent has a workspace directory (`~/.switchroom/agents/<name>/workspace/`) with editable stable files (`AGENTS.md`, `USER.md`, `IDENTITY.md`, `TOOLS.md`) and dynamic files (`MEMORY.md`, `memory/YYYY-MM-DD.md`, `HEARTBEAT.md`) injected into the model's context at turn time.
368
+
369
+ `SOUL.md` (the persona) is a special case since v0.12.0: it's **user-owned and seeded once** — switchroom writes it at first scaffold (from the setup wizard's persona prompts or the profile default) and then *never overwrites it*, the deliberate inverse of the switchroom-managed `CLAUDE.md`. Edit it freely; `switchroom update` won't touch it. Use `switchroom soul reset <agent>` to re-seed from the profile (it backs the old one up first). See [docs/configuration.md § Persona & SOUL.md ownership](docs/configuration.md#persona--soulmd-ownership).
355
370
 
356
371
  ```bash
357
372
  switchroom workspace path <agent> # Print the workspace dir
@@ -415,7 +430,7 @@ Overlay entries win on collision with built-in defaults. Unknown files that appe
415
430
  | **[Vault](docs/vault.md)** | Architecture, per-cron secrets, ACL, audit log, threat model |
416
431
  | **[Telegram Plugin](docs/telegram-plugin.md)** | Progress cards, 15 MCP tools, native checklists, sticker aliases, voice-in |
417
432
  | **[Sub-Agents](docs/sub-agents.md)** | Model routing, delegation patterns, frontmatter spec |
418
- | **[Scheduling](docs/scheduling.md)** | Cron tasks (per-agent scheduler container), model selection |
433
+ | **[Scheduling](docs/scheduling.md)** | Cron tasks (in-agent scheduler sidecar), model selection |
419
434
  | **[Session Management](docs/session-optimization.md)** | Continuity, compaction, freshness policy |
420
435
  | **[OpenClaw alternative](docs/vs-openclaw.md)** | Switchroom vs OpenClaw |
421
436
  | **[NanoClaw alternative](docs/vs-nanoclaw.md)** | Switchroom vs NanoClaw |
@@ -12142,7 +12142,7 @@ function validateAccountLabel(label) {
12142
12142
  throw new Error("Account label cannot contain path separators");
12143
12143
  }
12144
12144
  if (!LABEL_RE.test(label)) {
12145
- throw new Error("Account label must match [A-Za-z0-9._@+-]+ (letters, digits, dot, " + "underscore, dash, @, +). The @ and + chars let you label accounts " + "by Anthropic email — e.g. 'pixsoul@gmail.com', 'ken+work@example.com'.");
12145
+ throw new Error("Account label must match [A-Za-z0-9._@+-]+ (letters, digits, dot, " + "underscore, dash, @, +). The @ and + chars let you label accounts " + "by Anthropic email — e.g. 'you@example.com', 'ken+work@example.com'.");
12146
12146
  }
12147
12147
  }
12148
12148
  function listAccounts(home2 = homedir2()) {