npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

switchroom-ai

v0.6.4

Published

Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys, no Docker.

Downloads

797

Readme

Switchroom

Build status Tests Trigger evals Quality evals

Your Claude Pro or Max, as a fleet of always-on agents in Telegram. Opinionated UX, done properly.

I loved OpenClaw + Telegram. I wanted my Claude subscription. And the UX done properly. So I built this.

Compliance-by-design. Switchroom leverages Claude Code natively — unmodified claude CLI, no Agent SDK, no direct API. It sets up the CLI the way you would, then gets out of the way. See the Compliance Attestation for detail.

Right, so what's this about

So you had the bright idea. Run Claude Code agents 24/7 on a cheap Linux box, talk to them from Telegram, use the Claude Pro or Max subscription you're already paying for. Sensible. Obvious, even.

Then you tried OpenClaw. Followed the docs, spun it up, got it running, only to realise halfway through that you're pinging the Anthropic API on your own key and your token bill is quietly ticking over in the background. Bit of a bait and switch, that one. You signed up for "use your subscription," not "buy API credits on top of your subscription."

So you gave Claude Code's built-in Telegram channel a crack instead. Sent a message. Waited. Something happened, maybe. Eventually a reply came back. What did the agent actually do? No idea. Which tools ran? No idea. Did it get stuck, crash, spawn a sub-agent, read half your repo? No idea. It's an MVP black box of death, and I got sick of squinting into it.

So I built this.

What Switchroom is, and isn't

Switchroom is an opinionated implementation of a Telegram plugin and agent lifecycle layer, sitting on top of the official claude CLI. No fork. No custom runtime in Docker. No API key interception. Your Claude Pro or Max subscription does the work, the same way it does on your desktop, authenticated via the same OAuth flow, fully compliant with Anthropic's terms.

It is not trying to be a general-purpose LLM orchestrator. It doesn't care about OpenAI, Gemini, Llama, or swapping model providers. It is not a multi-channel bridge for Slack, Discord, Teams. It does one thing: makes Telegram the best possible interaction surface for Claude Code. Unashamedly.

The whole thing is built around one idea. Every time an agent starts work, a progress card pops into Telegram and stays pinned while the task runs. It updates in place as tools execute, so you see each Read, Bash, Edit, Grep happen as it happens.

⚙️ Working… · ⏱ 12s
💬 refactor the auth module to use JWT
  ─ ─ ─
  … (+3 more earlier steps)
  ✅ Read src/auth/session.ts
  ✅ Grep "cookie" (in src/)
  🤖 Edit src/auth/jwt.ts · 4s

When the agent finishes, the card flips to Done and unpins. Two agents working at the same time? Each gets its own card, labelled (1/2) and (2/2), so you can follow both without losing the plot.

The UX bits that matter

  • Cards update at most once every 5 seconds. Fast enough to follow, not so fast it floods
  • Last 5 steps are always visible, older ones collapse into (+N more earlier steps)
  • Running steps show elapsed time so you can tell if something's stuck
  • Sub-agents get their own section in the card, so nested work is visible, not hidden
  • No silent gaps. No ghosts.

Architecture

One Claude Code REPL per agent, dressed up with systemd and a Telegram bot. Two systemd units per agent: the Claude process (switchroom-<agent>.service) and its Telegram gateway (switchroom-<agent>-gateway.service). See docs/architecture.md for the process model, IPC layout, and how each layer maps to the claude CLI.

You (Telegram)
    │
    ▼
@YourBot ──── switchroom-telegram MCP ──── Claude Code CLI
                  │                        │
                  ├─ Progress cards         ├─ .claude/agents/*.md (sub-agents)
                  ├─ Pin / unpin lifecycle  ├─ settings.json (tools, hooks, MCP)
                  ├─ SQLite history         ├─ Hindsight plugin (memory)
                  ├─ Emoji reactions        └─ systemd (agent + cron timers)
                  └─ Format conversion

Switchroom is not a harness. Each agent runs the unmodified claude binary, authenticated directly with Anthropic via official OAuth. No credential interception, no API key routing.

Everything else you get

| Feature | What it does | |---------|-------------| | Claude Pro/Max auth | OAuth, not API keys. No per-token billing. | | Multi-agent | Opus plans, Sonnet implements in the background. Sub-agent work surfaces in the card. | | Config cascade | Defaults, then profiles, then per-agent YAML. Change one line, every agent updates. | | Scheduled tasks | Cron-based systemd timers. Survive reboots. | | Persistent memory | Hindsight semantic memory with knowledge graphs. | | Session continuity | Resume sessions across restarts with freshness gating. | | Encrypted vault | AES-256-GCM for secrets. | | 12 Telegram MCP tools | Reply, stream replies, pin, react, history, attachments, native checklists, all of it. |

How it stacks up against the alternatives

| | Switchroom | Claude Code channels | OpenClaw | NanoClaw | |---|---|---|---|---| | Progress visibility | Live progress cards, pinned | None, black box | None | None | | Runtime | Claude Code CLI | Claude Code CLI | Custom runtime | Agents SDK | | Auth | Pro/Max OAuth | Pro/Max OAuth | API key | API key | | Sub-agent tracking | Yes, visible in card | No | No | No | | Parallel task display | Labelled cards (1/N) | No | No | No | | Config | YAML with cascade | None | JSON/TOML | Env vars | | Setup | switchroom setup | Built-in (limited) | Docker compose | Docker compose |

Install

Ubuntu 24.04 LTS, 4GB RAM. Linux only.

From inside Claude Code (the on-ramp)

If you already use Claude Code, this is the shortest path. Inside any session:

/plugin marketplace add switchroom/switchroom
/plugin install switchroom@switchroom
/switchroom:setup

/switchroom:setup walks you through deps, switchroom setup (Telegram + vault + first agent), and switchroom agent start. Once it's done you have /switchroom:start, /switchroom:stop, and /switchroom:status for day-to-day. See docs/publishing.md.

One-liner (fresh box)

curl -fsSL https://get.switchroom.ai | bash

Bootstraps bun, node 22, the claude CLI, and switchroom-ai. Idempotent. Safe to re-run. Source is install.sh in this repo.

Then:

switchroom setup                                        # interactive Telegram wiring
switchroom agent create coach --profile health-coach    # scaffold your first agent
switchroom auth login coach                             # link your Pro or Max session
switchroom agent start coach                            # go

After the last command you talk to the agent from Telegram. You don't touch the server again.

Already have node?

npm install -g @anthropic-ai/claude-code switchroom-ai
switchroom setup

Node 20.11+. switchroom setup is the interactive first-time wizard — scaffolds config, handles Telegram wiring, sets up the vault.

One-shot happy path (no wizard)

If you already have Telegram credentials in ~/.switchroom/switchroom.yaml, skip switchroom setup. agent create --profile writes a minimal entry for you, and auth is scoped per-agent:

switchroom agent create coach --profile health-coach
switchroom auth login coach
switchroom agent start coach

Example Configuration

switchroom:
  version: 1

telegram:
  bot_token: "vault:telegram-bot-token"
  forum_chat_id: "-1001234567890"

memory:
  backend: hindsight

defaults:
  model: claude-opus-4-6   # or claude-sonnet-4-6, claude-haiku-4-5
  tools: { allow: [all] }
  subagents:
    worker:
      description: "Implementation tasks"
      model: sonnet
      background: true
      isolation: worktree
  schedule:
    - cron: "0 8 * * 1-5"
      prompt: "Morning briefing"
  session:
    max_idle: 2h

agents:
  assistant:
    topic_name: "General"
    memory: { collection: general }

  coach:
    topic_name: "Coach"
    extends: advisor
    soul:
      name: Coach

See docs/configuration.md for the full reference.

Vault broker (cron secrets)

Scheduled tasks run headless via systemd --user timers, so they cannot prompt for the vault passphrase. The vault broker is a long-running user-level systemd unit that holds the vault decrypted in memory after a one-time interactive unlock. Cron tasks fetch the specific keys they declare via a unix socket; the passphrase never sits on disk.

Declare per-cron secrets in switchroom.yaml:

agents:
  scout:
    schedule:
      - cron: "0 8 * * *"
        prompt: "Morning brief."
        secrets: [openai_api_key, polygon_api_key]   # only these may be read

secrets: [] (the default) means the cron has no vault access.

Bootstrap once per host:

switchroom update                       # installs the broker systemd unit
switchroom vault broker unlock          # prompt for passphrase, primes broker

Or just run switchroom vault get <key> from a TTY — the broker offers to take the unlocked state with [Y/n] so you don't have to remember a separate unlock command.

Identity model. On Linux, the broker reads /proc/<pid>/cgroup to find the connecting cron's systemd unit (switchroom-<agent>-cron-<i>.service). Cgroup membership is set by systemd as root and is unspoofable from userspace, so a compromised agent cannot pose as another agent's cron and read its keys. macOS and other platforms degrade to UID-only via the socket file mode 0600 — fine for desktop use, not recommended for production cron.

The broker locks on SIGTERM (so a restart zeros the in-memory state) and on demand via switchroom vault broker lock. Use switchroom vault get <key> --no-broker to bypass and prompt locally.

Unit installed at ~/.config/systemd/user/switchroom-vault-broker.service.

Auto-unlock on boot (opt-in)

By default, the broker holds the unlocked state in memory only — every restart (host reboot, service crash, reconcile that re-renders the unit) wipes it and requires switchroom vault broker unlock again. For unattended hosts where this is too painful, switchroom can encrypt the passphrase with a key derived from /etc/machine-id and have the broker unlock itself at boot:

switchroom vault broker enable-auto-unlock   # one-time setup, prompts for passphrase

Done. The wizard prompts for your vault passphrase, encrypts it with AES-256-GCM keyed off /etc/machine-id, writes the result to ~/.config/switchroom/auto-unlock.bin (mode 0600), flips vault.broker.autoUnlock: true in switchroom.yaml, restarts the broker, and verifies the vault came up unlocked. Every subsequent boot the broker reads + decrypts + unlocks itself.

Disable with switchroom vault broker disable-auto-unlock.

Security tradeoff — read this before enabling. The encrypted blob lives at mode 0600 in your home directory; the encryption key is derived from /etc/machine-id plus a per-file random salt. This means disk theft is safe (the blob doesn't decrypt on any other machine) and other UNIX users on the same box can't read it — but root on the host can read both the blob and the machine-id, so once root is on the machine the passphrase is recoverable. Same blast radius as the running broker process (anything with code-exec as you can already attach to the broker socket and exfiltrate secrets), but it shifts the convenience-vs-security knob: auto-unlock means a lost laptop is a lost vault even if the vault file itself is encrypted at rest. Use only on hosts you trust. See docs/auto-unlock.md for the full threat model and recovery instructions.

CLI Reference

switchroom setup                              # Interactive wizard
switchroom doctor                             # Health check
switchroom update                             # Pull latest + rebuild + reconcile + restart
switchroom restart [agent] [--force]          # Bounce agent(s); drains in-flight turn by default
switchroom version                            # Show versions + running agent health summary

switchroom agent list                         # Status of all agents
switchroom agent status <name>                # Status of one agent
switchroom agent add [name]                   # Wizard: scaffold a new agent end-to-end (#543)
switchroom agent create <name> [--profile <p>] # Scaffold + install timers; --profile writes yaml entry
switchroom agent bootstrap <name> --profile <p> --bot-token <t>  # One-shot scaffold + auth + start
switchroom agent reconcile <name|all>         # Re-apply switchroom.yaml (without pulling/building)
switchroom agent start|stop|restart <name>    # Lifecycle (with preflight)
switchroom agent interrupt <name>             # Cancel in-flight turn without restarting
switchroom agent rename <old> <new>           # Rename an agent slug (#168)
switchroom agent destroy <name>               # Tear down systemd units + scaffold dir
switchroom agent attach <name>                # Interactive tmux session
switchroom agent logs <name> [-f]             # View logs
switchroom agent grant <name> <tool>          # Grant a tool permission
switchroom agent permissions <name>           # Show allow/deny list
switchroom agent dangerous <name> [off]       # Toggle full tool access

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).

switchroom agent create <name> --profile <profile> does two things in one step:

  1. Adds an entry to switchroom.yaml under agents: with extends: <profile> and a derived topic_name (capitalized agent name). Edit the yaml afterwards to change the topic name, emoji, tools, etc.
  2. Scaffolds the agent directory and installs the systemd unit (same as running agent create on an entry that already exists in yaml).

If the agent is already in yaml, --profile must match the existing extends: value or it errors. If the yaml entry has no extends: and you pass --profile, the flag is written in additively with a warning. Running agent create with no --profile on a missing entry keeps the old "Agent not defined in switchroom.yaml" error, now with a hint to use --profile.

Model aliases: the bare names opus, sonnet, haiku are accepted alongside the full IDs (claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5). Use whichever reads cleaner in your config.

Authentication (multi-account slot pool)

Each agent has a pool of Claude OAuth slots. The active slot is what the agent uses; other slots are automatic fallbacks when the active slot hits its quota window. Every <slot> option defaults to the active slot if omitted.

switchroom auth status                            # All agents, one table
switchroom auth login <agent>                     # First-time OAuth into the active slot
switchroom auth code <agent> <browser-code>       # Paste the code back from the browser
switchroom auth cancel <agent>                    # Abandon a pending login
switchroom auth reauth <agent> [--slot <s>]       # Fresh OAuth, replace existing token
switchroom auth refresh <agent>                   # Alias for reauth (back-compat)
switchroom auth refresh-tick [--threshold-ms N]   # Daemon: rotate tokens nearing expiry (cron/timer)

switchroom auth add <agent> [--slot <name>]       # Add another account to the fallback pool
switchroom auth use <agent> <slot>                # Switch the active slot
switchroom auth list <agent> [--json]             # Show slots: health, quota status, expiry
switchroom auth rm <agent> <slot> [--force]       # Remove a slot (refuses active/last slot)

The fallback pool also works from Telegram. The switchroom MCP plugin exposes the same verbs as /auth add|use|list|rm inside the chat.

Workspace (agent bootstrap layer)

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.

switchroom workspace path <agent>                 # Print the workspace dir
switchroom workspace show <agent> [file]          # Print one workspace file (default AGENTS.md)
switchroom workspace edit <agent> [file]          # Open in $EDITOR (default AGENTS.md)
switchroom workspace render <agent> --stable      # Dump the stable bootstrap block (for start.sh)
switchroom workspace render <agent> --dynamic     # Dump the dynamic block (for UserPromptSubmit)
switchroom workspace search <agent> <query...>    # BM25-lite search over workspace markdown
switchroom workspace commit <agent> [-m <msg>]    # Git checkpoint of workspace state
switchroom workspace status <agent>               # git status on the workspace

Observability

switchroom debug turn <agent>                     # Dump the exact prompt layering from the last turn
switchroom memory setup|search|stats|reflect      # Hindsight memory

Other

switchroom topics sync|list|cleanup               # Telegram forum topics
switchroom vault init|set|get|list|remove         # Encrypted secrets
switchroom handoff <agent>                        # Cross-session handoff summarizer
switchroom web                                    # Web dashboard

Migrating credentials from OpenClaw

scripts/import-openclaw-credentials.ts is a one-shot migration script that lifts /data/openclaw-config/credentials/ into the Switchroom vault. It ships with a small set of default mappings for filenames OpenClaw documents out of the box.

User-specific credential filenames (your custom bot tokens, SSH keys, and so on) belong in a local overlay file — not in the source repository. Create ~/.switchroom/import-openclaw.yaml:

# ~/.switchroom/import-openclaw.yaml
files:
  telegram-bot-token-mybot: telegram/mybot-bot-token
  discord-bot-token-mybot: discord/mybot-bot-token
  my-server-ssh-key: ssh/my-server
skip:
  compass-mac-cookies.json: "auto-managed by compass skill (8h TTL cache)"
secrets_env:
  X_BEARER_TOKEN: x-api/bearer-token
directories:
  garmin-tokens: garmin/tokens

Overlay entries win on collision with built-in defaults. Unknown files that appear in neither defaults nor the overlay surface as warn entries so nothing is silently dropped. Run bun scripts/import-openclaw-credentials.ts --help for flags including --mapping <path> to override the default overlay location.

Documentation

| Guide | Description | |-------|-------------| | Configuration | Full field reference, cascade semantics, profiles | | Vault | Architecture, per-cron secrets, ACL, audit log, threat model | | Telegram Plugin | Progress cards, 10 MCP tools, emoji reactions | | Sub-Agents | Model routing, delegation patterns, frontmatter spec | | Scheduling | Cron tasks, systemd timers, model selection | | Session Management | Continuity, compaction, freshness policy | | OpenClaw alternative | Switchroom vs OpenClaw | | NanoClaw alternative | Switchroom vs NanoClaw | | Compliance | Anthropic compliance analysis | | Telemetry | What Switchroom reports to PostHog and how to opt out |

Telemetry

Switchroom reports anonymous usage events and errors to PostHog so we can spot regressions and understand which commands are used. No personal data, code, or message content leaves your machine. The anonymous ID lives at ~/.switchroom/analytics-id and is a random UUID. Not tied to your username, email, IP, or machine identifier (we pass disableGeoip: true on every event).

To opt out, set this in your shell profile:

export SWITCHROOM_TELEMETRY_DISABLED=1

Full event catalogue, dashboard links, and the source module at docs/posthog.md.

FAQ

Can I use a Claude Pro or Max subscription instead of an API key? Yes. That's the whole point. Switchroom runs the unmodified claude CLI with the same OAuth flow you use on the desktop app. No API key. No per-token billing.

How is this different from Claude Code's built-in Telegram channel? The built-in channel is message in, message out, with zero visibility into what the agent is doing in between. Switchroom adds live progress cards that pin to the top of each topic and update as tools execute. You can always see what's happening, which is the bit the built-in channel gets wrong.

Does it work with multiple agents at the same time? Yes. Each agent gets its own Telegram forum topic. When multiple agents are working simultaneously, each has its own pinned progress card labelled (1/N), (2/N) and so on.

Can I see what sub-agents are doing? Yes. When an agent delegates to a sub-agent (a worker, a researcher), the sub-agent's activity shows up in its own section of the progress card. You see the full hierarchy, not just the top-level agent.

What does it cost to run? A cheap Linux VPS (around $6/mo on Hetzner, DigitalOcean, wherever), plus your existing Claude Pro ($20/mo) or Max ($100/mo) subscription. Switchroom itself is MIT-licensed, free.

Is this against Anthropic's terms of service? No. Switchroom uses the official claude binary with the official OAuth flow. See docs/compliance-attestation.md for the full analysis.

Is Switchroom an alternative to OpenClaw? Yes. Same use case, but it uses your Claude subscription via OAuth instead of an API key, and runs the native claude binary instead of a custom runtime in Docker. See vs-openclaw.

License

MIT. See CONTRIBUTING.md.