How I Replaced OpenClaw with Claude Code Channels and a Discord Watchdog

Per-channel Claude Code sessions via tmux — with workdir mapping, session resume, idle suspension, Telegram support, and a self-healing watchdog

March 23, 2026

6 min read·
agent-osclaude-codediscordtelegrambuild-loginfrastructureopen-source

Discord sessions architecture — each channel maps to an isolated Claude Code session via tmux

The agent-on-mobile dream was real. Having your AI agent accessible through Discord and Telegram — from your phone, while walking, between meetings — turned out to be one of the highest-leverage features I built. OpenClaw proved that. But 331K GitHub stars and a TypeScript dependency tree aren't what you need when Claude Code ships native channels.

The mobile agent problem

Here's what I wanted: send a message on Discord from my phone, have my AI agent — with full access to my codebase, tools, and context — respond. Not a chatbot. My actual development agent, the one that knows my project structure, runs tests, and commits code.

OpenClaw made this work. It was a framework that bridged messaging platforms to agent runtimes. You'd wire up a Telegram bot or a Discord bot, connect it to your agent, and suddenly your agent was on your phone. It was successful — the concept proved itself daily.

But the overhead was real:

  • A separate TypeScript framework with its own dependency tree
  • Custom message routing between Discord and the agent runtime
  • Separate authentication and state management
  • Context fragmentation — the Discord agent wasn't quite the same as my terminal agent

Every layer between "message received" and "agent processes it" was a layer that could break, drift, or need maintenance.

Claude Code Channels changes everything

In March 2026, Anthropic shipped channels as a research preview for Claude Code. One flag:

claude --channels plugin:discord@claude-plugins-official

That's it. Your Claude Code session — the same one with your MCP tools, skills, CLAUDE.md context, conversation history — now listens on Discord. Messages arrive, Claude processes them with full workspace access, replies go back to Discord.

No middleware. No framework. No extra runtime. The same Claude Code that runs in your terminal, now reachable from your phone.

But there was one limitation: a single session handles all channels. If you have five Discord channels, they all share one Claude context. No isolation. A conversation in #general bleeds into #health-os.

Claude Remote Sessions

The fix is per-channel isolation through tmux. Each Discord channel gets its own Claude Code session running in its own tmux pane, with its own DISCORD_STATE_DIR scoped to only that channel. The same pattern works for Telegram.

The architecture:

Discord #general      →  tmux: dc-<id>  →  Claude Code (~/broomva)
Discord #health-os    →  tmux: dc-<id>  →  Claude Code (~/broomva/apps/healthOS)
Discord #life         →  tmux: dc-<id>  →  Claude Code (~/broomva/core/life)
Discord #chatos       →  tmux: dc-<id>  →  Claude Code (~/broomva/apps/chatOS)
Thread: "design"      →  tmux: dc-<id>  →  Claude Code (inherits parent workdir)
Telegram chat         →  tmux: tg-<id>  →  Claude Code (configured workdir)
                         dc-watchdog     →  Respawns + discovers + suspends idle

Workdir mapping

A workdir-map.json file maps channel names to project directories. When the watchdog discovers a new channel, it looks up the name and assigns the right workdir automatically:

{
  "general": "~/broomva",
  "health-os": "~/broomva/apps/healthOS",
  "life": "~/broomva/core/life",
  "chatos": "~/broomva/apps/chatOS",
  "symphony": "~/broomva/core/symphony",
  "stimulus": "~/broomva/work/stimulus/stimulus"
}

The --workdir flag means that session loads the project-specific CLAUDE.md, giving the agent project context automatically through Claude Code's built-in CLAUDE.md chain. I have 25 channels, each scoped to its own project.

Threads inherit context

Threads get two things from their parent channel: the workdir (so the thread agent has the same project context) and the last 20 messages (fetched via Discord REST API and injected as a system prompt). The thread session knows what was discussed before it existed.

Session resume

Each channel gets a deterministic UUID v5 session ID. When the watchdog respawns a dead session, it uses --session-id to resume the previous conversation. Use --fresh to start clean.

The watchdog daemon

Manual session management doesn't scale. The watchdog daemon handles everything:

Every 30 seconds: Respawn any dead session with the same workdir, session ID, and config.

Every 60 seconds: Discover new channels and threads via the Discord API, spawn sessions automatically with mapped workdirs.

Every 5 minutes: Clean up stale sessions (deleted channels, archived threads) and suspend idle sessions to free resources.

./scripts/discord-watchdog.sh --daemon

The flow: I create a channel on Discord from my phone → within 60 seconds, the watchdog discovers it, looks up the workdir map, spawns a Claude Code session with the right project context, and registers it. I send a message, the agent responds.

Idle suspension

With 25 channels, resource usage matters. Sessions idle beyond 30 minutes are automatically suspended — the tmux process is killed but the registration persists. When I need a channel again, wake <id> brings it back instantly with the same conversation history via session resume.

# Manual control
./scripts/discord-session-manager.sh suspend-idle    # suspend all idle sessions
./scripts/discord-session-manager.sh wake <id>       # wake a specific channel
./scripts/discord-session-manager.sh wake-all        # wake everything

In practice, I keep 3-5 core channels active and let the rest sleep until needed.

What we dropped

Here's what's no longer in the stack:

  • No external agent framework (OpenClaw or otherwise)
  • No separate runtime for the messaging layer
  • No custom message routing or webhook handlers
  • No state synchronization between agent and messaging platform
  • No separate authentication system
  • No Docker containers running middleware

The entire implementation is six bash scripts. The Discord session manager and watchdog handle channels, threads, discovery, stale cleanup, and idle suspension. The Telegram session manager and watchdog handle per-chat sessions. No compiled code, no framework, no runtime dependencies beyond bash, tmux, python3, and curl.

What we gained

The compounding advantages are significant:

Full MCP tool access — Every Discord session has the same tools as a terminal session. Read files, edit code, run tests, commit, push — from Discord on your phone.

CLAUDE.md chain — Set --workdir ~/broomva/core/life and the agent loads both the root workspace CLAUDE.md and the project-specific one. Different channels, different project contexts, automatically.

Skills and hooks — The conversation bridge hook captures session history. The control gate hook enforces safety shields. The regression gate runs before destructive operations. All of them work in Discord sessions exactly as they do in the terminal.

Thread context injection — When a thread is spawned, the parent channel's recent messages are fetched and injected as a system prompt. The thread session knows what was discussed before it existed.

Session persistence — Each session gets a deterministic UUID. When the watchdog respawns a dead session, --session-id resumes the exact conversation. Use --fresh to start clean.

Idle suspension — Sessions idle beyond 30 minutes are suspended automatically. Wake on demand. In practice, 3-5 channels stay active while 20 sleep, keeping resource usage manageable on a laptop.

Telegram support — The same pattern works for Telegram via telegram-session-manager.sh. Spawn-based (Telegram has no channel listing API), but the same tmux isolation, workdir mapping, and watchdog respawn.

The takeaway

The best infrastructure is the kind you delete. OpenClaw proved that mobile agent access is genuinely useful — it's not a gimmick. But the concept didn't need a framework. It needed a messaging protocol (Claude Code channels) and a session orchestrator (tmux + a watchdog script).

Claude Code is already a battle-tested agent runtime. It has tools, skills, hooks, MCP servers, conversation persistence, and now native messaging channels. Building on top of it instead of alongside it eliminates an entire class of integration problems.

A handful of bash scripts and a tmux watchdog replaced an entire framework. That's not a hack — that's what simplification looks like when the underlying platform does the hard work.


The skill is open source. Install it and try it yourself:

# Install the skill
npx skills add broomva/claude-remote-sessions -g -y

# Configure
./scripts/discord-session-manager.sh init

# Discover all channels and start the watchdog
./scripts/discord-session-manager.sh discover-all
./scripts/discord-watchdog.sh --daemon

Source: github.com/broomva/claude-remote-sessions

Reactions

broomva.tech

Reliability engineering for complex systems.

  • Pages
  • Home
  • Projects
  • Writing
  • Notes
  • Tools
  • Chat
  • Prompts
  • Link Hub
  • Social
  • GitHub
  • LinkedIn
  • X