switchroom 0.8.1 → 0.10.0
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.
- package/README.md +49 -57
- package/bin/timezone-hook.sh +9 -7
- package/dist/agent-scheduler/index.js +285 -45
- package/dist/auth-broker/index.js +13932 -0
- package/dist/cli/switchroom.js +15931 -12778
- package/dist/host-control/main.js +582 -43
- package/dist/vault/approvals/kernel-server.js +276 -47
- package/dist/vault/broker/server.js +333 -69
- package/examples/minimal.yaml +63 -0
- package/examples/personal-google-workspace-mcp/.env.example +34 -0
- package/examples/personal-google-workspace-mcp/README.md +194 -0
- package/examples/personal-google-workspace-mcp/compose.yaml +66 -0
- package/examples/switchroom.yaml +220 -0
- package/package.json +6 -4
- package/profiles/_base/start.sh.hbs +3 -3
- package/profiles/_shared/agent-self-service.md.hbs +126 -0
- package/profiles/default/CLAUDE.md +10 -0
- package/profiles/default/CLAUDE.md.hbs +16 -0
- package/skills/buildkite-agent-infrastructure/SKILL.md +30 -11
- package/skills/buildkite-agent-runtime/SKILL.md +44 -11
- package/skills/buildkite-api/SKILL.md +31 -8
- package/skills/buildkite-cli/SKILL.md +27 -9
- package/skills/buildkite-migration/SKILL.md +22 -9
- package/skills/buildkite-pipelines/SKILL.md +26 -9
- package/skills/buildkite-secure-delivery/SKILL.md +23 -9
- package/skills/buildkite-test-engine/SKILL.md +25 -8
- package/skills/docx/SKILL.md +1 -1
- package/skills/file-bug/SKILL.md +34 -6
- package/skills/humanizer/SKILL.md +15 -0
- package/skills/humanizer-calibrate/SKILL.md +7 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/pdf/SKILL.md +1 -1
- package/skills/pptx/SKILL.md +1 -1
- package/skills/skill-creator/SKILL.md +21 -1
- package/skills/skill-creator/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/generate_report.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/improve_description.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_eval.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_loop.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/skills/switchroom-cli/SKILL.md +63 -64
- package/skills/switchroom-health/SKILL.md +23 -10
- package/skills/switchroom-install/SKILL.md +3 -3
- package/skills/switchroom-manage/SKILL.md +26 -19
- package/skills/switchroom-runtime/SKILL.md +67 -15
- package/skills/switchroom-status/SKILL.md +26 -1
- package/skills/telegram-test-harness/SKILL.md +3 -0
- package/skills/webapp-testing/SKILL.md +31 -1
- package/skills/xlsx/SKILL.md +1 -1
- package/telegram-plugin/admin-commands/index.ts +7 -5
- package/telegram-plugin/dist/gateway/gateway.js +13042 -12844
- package/telegram-plugin/gateway/auth-add-flow.ts +326 -0
- package/telegram-plugin/gateway/auth-broker-client.ts +75 -0
- package/telegram-plugin/gateway/auth-command.ts +794 -0
- package/telegram-plugin/gateway/auth-line.ts +123 -0
- package/telegram-plugin/gateway/boot-card.ts +22 -36
- package/telegram-plugin/gateway/boot-probes.ts +3 -3
- package/telegram-plugin/gateway/gateway.ts +313 -798
- package/telegram-plugin/gateway/hostd-dispatch.ts +117 -0
- package/telegram-plugin/hooks/tool-label-pretool.mjs +11 -0
- package/telegram-plugin/hooks/wedge-detect-posttool.mjs +303 -0
- package/telegram-plugin/permission-title.ts +56 -0
- package/telegram-plugin/quota-check.ts +19 -41
- package/telegram-plugin/scripts/build.mjs +0 -1
- package/telegram-plugin/shared/bot-runtime.ts +5 -4
- package/telegram-plugin/tests/auth-add-flow.test.ts +559 -0
- package/telegram-plugin/tests/auth-code-redact.test.ts +8 -4
- package/telegram-plugin/tests/auth-command-vernacular.test.ts +531 -0
- package/telegram-plugin/tests/boot-probes.test.ts +11 -4
- package/telegram-plugin/tests/hostd-dispatch.test.ts +129 -0
- package/telegram-plugin/tests/permission-title.test.ts +31 -0
- package/telegram-plugin/tests/quota-check.test.ts +5 -35
- package/telegram-plugin/uat/SETUP.md +31 -1
- package/telegram-plugin/uat/runners/agent-self-sufficiency.ts +457 -0
- package/telegram-plugin/uat/runners/paraphrases.ts +231 -0
- package/telegram-plugin/uat/runners/report.ts +150 -0
- package/telegram-plugin/uat/runners/run-agent-self-sufficiency.sh +50 -0
- package/telegram-plugin/uat/runners/scorer.test.ts +196 -0
- package/telegram-plugin/uat/runners/scorer.ts +106 -0
- package/telegram-plugin/uat/runners/skill-coverage.test.ts +100 -0
- package/telegram-plugin/uat/runners/skill-coverage.ts +620 -0
- package/telegram-plugin/uat/scenarios/jtbd-interrupt-marker-dm.test.ts +7 -1
- package/telegram-plugin/uat/scenarios/jtbd-rapid-followup-dm.test.ts +7 -1
- package/telegram-plugin/auth-dashboard.ts +0 -1104
- package/telegram-plugin/auth-slot-parser.ts +0 -497
- package/telegram-plugin/dist/foreman/foreman.js +0 -31358
- package/telegram-plugin/foreman/foreman-create-flow.ts +0 -202
- package/telegram-plugin/foreman/foreman-handlers.ts +0 -493
- package/telegram-plugin/foreman/foreman.ts +0 -1165
- package/telegram-plugin/foreman/setup-flow.ts +0 -345
- package/telegram-plugin/foreman/setup-state.ts +0 -239
- package/telegram-plugin/foreman/state.ts +0 -203
- package/telegram-plugin/tests/auth-account-identity-surface.test.ts +0 -118
- package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +0 -260
- package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +0 -140
- package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +0 -559
- package/telegram-plugin/tests/auth-dashboard.test.ts +0 -1045
- package/telegram-plugin/tests/auth-slot-commands.test.ts +0 -640
- package/telegram-plugin/tests/boot-card-account-quota.test.ts +0 -137
- package/telegram-plugin/tests/foreman-create-flow.test.ts +0 -359
- package/telegram-plugin/tests/foreman-handlers.test.ts +0 -347
- package/telegram-plugin/tests/foreman-state.test.ts +0 -164
- package/telegram-plugin/tests/foreman-write-ops.test.ts +0 -214
- package/telegram-plugin/tests/setup-flow.test.ts +0 -510
- package/telegram-plugin/tests/setup-state.test.ts +0 -146
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ So I built this.
|
|
|
60
60
|
| Feature | What it does |
|
|
61
61
|
|---|---|
|
|
62
62
|
| **Progress cards** | Pinned, in-place, every tool call visible. The headline UX. |
|
|
63
|
-
| **Claude Pro/Max auth** | OAuth, not API keys. No per-token billing.
|
|
63
|
+
| **Claude Pro/Max auth** | OAuth, not API keys. No per-token billing. Fleet-wide active account + fallback order; broker-owned refresh and credential fanout. |
|
|
64
64
|
| **Approval kernel** | Inline allow/deny cards in Telegram for every gated tool. TTL'd grants, full audit trail. |
|
|
65
65
|
| **Sub-agents** | Opus plans, Sonnet implements. Sub-agent work surfaces in the parent card. |
|
|
66
66
|
| **Config cascade** | Defaults, then profiles, then per-agent YAML. Change one line, every agent updates. |
|
|
@@ -119,7 +119,7 @@ Each agent is a long-running service. They survive reboots, network drops, and y
|
|
|
119
119
|
- **Auto-restart.** Agent containers come up with `restart: unless-stopped`, and each service has a healthcheck — a crashed or wedged agent is brought back automatically. No silent dropped work.
|
|
120
120
|
- **Resume protocol.** When an agent reboots mid-turn, `start.sh` exports `SWITCHROOM_PENDING_TURN=true` plus the original chat / message ids. The agent's first action on boot is to acknowledge the gap and ask the user how to proceed (start over, summarise and continue, or drop it).
|
|
121
121
|
- **Wake-audit.** On every fresh boot the agent checks for owed replies, orphan sub-agents, and stale in-progress todos. If everything's clean it stays quiet. If it owed you a reply, it tells you.
|
|
122
|
-
- **Token refresh.**
|
|
122
|
+
- **Token refresh.** The `switchroom-auth-broker` daemon owns the refresh loop and is the sole writer of every `credentials.json`. Per-account quota state fans out across the fleet in seconds; `auth.fallback_order` cycles when an account is exhausted.
|
|
123
123
|
|
|
124
124
|
## How it stacks up
|
|
125
125
|
|
|
@@ -138,75 +138,62 @@ The wedge against OpenClaw and NanoClaw isn't the substrate — it's the stock `
|
|
|
138
138
|
|
|
139
139
|
## Install
|
|
140
140
|
|
|
141
|
-
Runs on the box you already have. The supported production runtime is Linux + Docker
|
|
141
|
+
Runs on the box you already have. The supported production runtime is Linux + Docker. **Canonical target: Ubuntu 24.04 LTS with ≥4 GiB RAM** (8 GiB recommended once you run more than one agent). Other Debian-derivatives work with the same script; non-apt distros need a manual prereq install. macOS (Docker Desktop) works for development but is not yet release-validated.
|
|
142
142
|
|
|
143
|
-
> **
|
|
143
|
+
> **Full new-user walkthrough — [`docs/install.md`](docs/install.md).** Zero to first Telegram message in ~15 minutes. Includes the [BotFather walkthrough](docs/botfather-walkthrough.md). Read that first if you're installing from scratch.
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
> **Heads up on the package name.** The npm package was originally `switchroom-ai`. It's now just `switchroom`. The old name is deprecated and will stop receiving updates — `npm install -g switchroom` is the current path.
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
### Fresh Linux box — one script
|
|
148
148
|
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
/plugin install switchroom@switchroom
|
|
152
|
-
/switchroom:setup
|
|
149
|
+
```bash
|
|
150
|
+
curl -fsSL https://github.com/switchroom/switchroom/raw/main/scripts/install-deps.sh | sudo bash
|
|
153
151
|
```
|
|
154
152
|
|
|
155
|
-
|
|
153
|
+
Installs Docker Engine + Compose v2, Node.js 20.11+, Bun, and the `@anthropic-ai/claude-code` + `switchroom` CLIs. Idempotent. Adds the invoking user to the `docker` group. Tested on Ubuntu 24.04 LTS and 26.04 LTS. Warns (does not block) on hosts under 4 GiB RAM.
|
|
156
154
|
|
|
157
|
-
|
|
155
|
+
Then log out and back in so the docker group takes effect, and:
|
|
158
156
|
|
|
159
157
|
```bash
|
|
160
|
-
|
|
158
|
+
switchroom setup # interactive: Telegram + vault + first agent
|
|
159
|
+
switchroom auth add me --from-oauth # OAuth into your Claude Pro or Max account (one flow, fleet-wide)
|
|
160
|
+
switchroom apply # write ~/.switchroom/compose/docker-compose.yml
|
|
161
|
+
docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d
|
|
161
162
|
```
|
|
162
163
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
The static binary still needs the `claude` CLI to run agents: `npm i -g @anthropic-ai/claude-code` (Node 20.11+).
|
|
164
|
+
After the last command you talk to the agent from Telegram. You don't touch the server again.
|
|
166
165
|
|
|
167
|
-
|
|
166
|
+
### Already have Docker + Node ≥ 20.11
|
|
168
167
|
|
|
169
168
|
```bash
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
chmod +x switchroom
|
|
173
|
-
sudo mv switchroom /usr/local/bin/
|
|
169
|
+
sudo npm install -g bun @anthropic-ai/claude-code switchroom
|
|
170
|
+
switchroom setup
|
|
174
171
|
```
|
|
175
172
|
|
|
176
|
-
|
|
173
|
+
`bun` is a hard runtime dep — the `switchroom` CLI's entrypoint is a Bun script. A Node-only CLI build is on the roadmap but not yet shipped.
|
|
177
174
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
**Mac (Sequoia+) one-time.** macOS 15 adds a second-stage notarization check that the `xattr` strip alone does not bypass — you may still see a Gatekeeper "cannot verify the developer" dialog the first time you run `switchroom`. `install.sh` attempts `sudo spctl --add /usr/local/bin/switchroom` automatically (best-effort, ignored if sudo isn't available). If the dialog still fires, run that `spctl --add` manually, or open System Settings → Privacy & Security → "Open Anyway" once.
|
|
175
|
+
### From inside Claude Code (the on-ramp)
|
|
181
176
|
|
|
182
|
-
|
|
177
|
+
If you already use Claude Code, this is the shortest path. Inside any session:
|
|
183
178
|
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
switchroom
|
|
188
|
-
switchroom apply # write docker-compose.yml
|
|
189
|
-
docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d
|
|
179
|
+
```
|
|
180
|
+
/plugin marketplace add switchroom/switchroom
|
|
181
|
+
/plugin install switchroom@switchroom
|
|
182
|
+
/switchroom:setup
|
|
190
183
|
```
|
|
191
184
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
### Already have node?
|
|
185
|
+
`/switchroom:setup` walks you through deps, `switchroom setup` (Telegram + vault + first agent), and `switchroom agent start`. Day-to-day: `/switchroom:start`, `/switchroom:stop`, `/switchroom:status`. See [`docs/publishing.md`](docs/publishing.md).
|
|
195
186
|
|
|
196
|
-
|
|
197
|
-
npm install -g @anthropic-ai/claude-code switchroom
|
|
198
|
-
switchroom setup
|
|
199
|
-
```
|
|
187
|
+
### Static binary (planned, not yet shipped)
|
|
200
188
|
|
|
201
|
-
Node
|
|
189
|
+
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.
|
|
202
190
|
|
|
203
191
|
### One-shot happy path (no wizard)
|
|
204
192
|
|
|
205
|
-
If you already have Telegram credentials in `~/.switchroom/switchroom.yaml
|
|
193
|
+
If you already have Telegram credentials in `~/.switchroom/switchroom.yaml` and one Anthropic account already added, skip `switchroom setup`. `agent create --profile` writes a minimal entry; the new agent inherits the fleet-wide active account automatically — no per-agent OAuth flow:
|
|
206
194
|
|
|
207
195
|
```bash
|
|
208
196
|
switchroom agent create coach --profile health-coach
|
|
209
|
-
switchroom auth login coach
|
|
210
197
|
switchroom apply && docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d
|
|
211
198
|
```
|
|
212
199
|
|
|
@@ -336,26 +323,29 @@ If the agent is already in yaml, `--profile` must match the existing `extends:`
|
|
|
336
323
|
|
|
337
324
|
Model aliases: the bare names `opus`, `sonnet`, `haiku` are accepted alongside the full IDs (`claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5`). Use whichever reads cleaner in your config.
|
|
338
325
|
|
|
339
|
-
### Authentication (
|
|
326
|
+
### Authentication (one OAuth, many agents)
|
|
340
327
|
|
|
341
|
-
|
|
328
|
+
The **Anthropic account is the unit of authentication.** One OAuth flow per account, then every agent in the fleet inherits the fleet-wide active account. The `switchroom-auth-broker` daemon owns the refresh loop and is the sole writer of every `credentials.json`. Per-account quota state fans out across the fleet in seconds. See [`docs/auth.md`](docs/auth.md) for the full operator guide.
|
|
342
329
|
|
|
343
330
|
```bash
|
|
344
|
-
switchroom auth
|
|
345
|
-
switchroom auth
|
|
346
|
-
switchroom auth
|
|
347
|
-
switchroom auth
|
|
348
|
-
|
|
349
|
-
switchroom auth
|
|
350
|
-
switchroom auth
|
|
351
|
-
|
|
352
|
-
switchroom auth
|
|
353
|
-
switchroom auth
|
|
354
|
-
|
|
355
|
-
switchroom auth
|
|
331
|
+
switchroom auth add <label> --from-oauth # New account via OAuth (one flow per Anthropic account)
|
|
332
|
+
switchroom auth add <label> --from-agent <name> # Seed from an existing agent's creds
|
|
333
|
+
switchroom auth add <label> --from-credentials <path> # Import a credentials.json
|
|
334
|
+
switchroom auth add <label> --from-oauth --replace # Re-auth an existing label (drift recovery)
|
|
335
|
+
|
|
336
|
+
switchroom auth list # Accounts + health + which one is fleet-active
|
|
337
|
+
switchroom auth show [agent] # Full snapshot (fleet + agents + consumers), or one agent
|
|
338
|
+
switchroom auth use <label> # Fleet-wide active swap
|
|
339
|
+
switchroom auth rotate # Cycle to next non-exhausted in fallback_order
|
|
340
|
+
switchroom auth rm <label> # Remove an account (refused if it's the only one)
|
|
341
|
+
|
|
342
|
+
switchroom auth agent override <agent> <label> # Edge case: one agent on a different account
|
|
343
|
+
switchroom auth agent override <agent> --clear # Back to fleet active
|
|
344
|
+
|
|
345
|
+
switchroom auth refresh [label] # Diagnostic: force a refresh tick
|
|
356
346
|
```
|
|
357
347
|
|
|
358
|
-
The
|
|
348
|
+
The same surface is reachable from Telegram in any agent's chat: `/auth show` (read-only), `/auth use <label>`, `/auth rotate`. Mutating verbs are admin-gated against the per-agent `admin: true` flag (the same flag that gates `/agents`, `/restart`, `/update`, etc.). One knob to make an agent the fleet control panel.
|
|
359
349
|
|
|
360
350
|
### Workspace (agent bootstrap layer)
|
|
361
351
|
|
|
@@ -416,6 +406,8 @@ Overlay entries win on collision with built-in defaults. Unknown files that appe
|
|
|
416
406
|
|
|
417
407
|
| Guide | Description |
|
|
418
408
|
|---|---|
|
|
409
|
+
| **[Install](docs/install.md)** | Zero-to-first-message new-user walkthrough |
|
|
410
|
+
| **[BotFather walkthrough](docs/botfather-walkthrough.md)** | Step-by-step bot creation in Telegram |
|
|
419
411
|
| **[Changelog](CHANGELOG.md)** | Release notes, every version |
|
|
420
412
|
| **[Configuration](docs/configuration.md)** | Full field reference, cascade semantics, profiles |
|
|
421
413
|
| **[Vault](docs/vault.md)** | Architecture, per-cron secrets, ACL, audit log, threat model |
|
package/bin/timezone-hook.sh
CHANGED
|
@@ -10,16 +10,18 @@
|
|
|
10
10
|
# This hook fires on every UserPromptSubmit and prints a one-line hint that
|
|
11
11
|
# Claude Code prepends to the prompt as additionalContext, so the LLM sees
|
|
12
12
|
# fresh local time each turn. The resolved zone is passed in via
|
|
13
|
-
# SWITCHROOM_TIMEZONE (
|
|
14
|
-
#
|
|
15
|
-
#
|
|
13
|
+
# SWITCHROOM_TIMEZONE (set in the agent container's `environment:` block by
|
|
14
|
+
# the compose generator at `switchroom apply` time — see
|
|
15
|
+
# src/agents/compose.ts). If unset we fall back to UTC — same default as
|
|
16
|
+
# the resolver — so the hook never fails loudly.
|
|
16
17
|
#
|
|
17
18
|
# Stale-install detection: when SWITCHROOM_TIMEZONE is unset we also annotate
|
|
18
19
|
# the hint with an in-band WARNING. This makes the failure visible to the
|
|
19
20
|
# agent (and thus to the user), rather than silently emitting "UTC" while the
|
|
20
|
-
# operator's real zone is Australia/Melbourne. Typical cause:
|
|
21
|
-
#
|
|
22
|
-
#
|
|
21
|
+
# operator's real zone is Australia/Melbourne. Typical cause: the compose
|
|
22
|
+
# env block is stale because `switchroom apply` hasn't run since the
|
|
23
|
+
# operator added a `timezone:` cascade entry (or the agent container was
|
|
24
|
+
# rebuilt from an image that predates the #1198 compose-TZ wiring fix).
|
|
23
25
|
#
|
|
24
26
|
# Failure modes are silent: hooks that error block the turn in Claude Code,
|
|
25
27
|
# and a missing timezone hint is never worse than no hint at all.
|
|
@@ -46,7 +48,7 @@ ROUNDED=$(( NOW_UNIX - (NOW_UNIX % 900) ))
|
|
|
46
48
|
NOW=$(TZ="$TZ_VAL" date -d "@$ROUNDED" '+%Y-%m-%d %H:%M %Z (UTC%:z)')
|
|
47
49
|
|
|
48
50
|
if [ "$TZ_UNSET" = "1" ]; then
|
|
49
|
-
MSG="Current local time: $NOW ($TZ_VAL — WARNING: SWITCHROOM_TIMEZONE unset;
|
|
51
|
+
MSG="Current local time: $NOW ($TZ_VAL — WARNING: SWITCHROOM_TIMEZONE unset; compose env may be stale, run \`switchroom apply && switchroom agent restart <agent>\` to refresh)"
|
|
50
52
|
else
|
|
51
53
|
MSG="Current local time: $NOW ($TZ_VAL)"
|
|
52
54
|
fi
|