Skip to main content

A shared message and state bus for multiple Claude Code sessions

Project description

claude-bus

A shared message and state bus that lets two or more Claude Code sessions communicate, exchange state, and stay coordinated. It is a small MCP server backed by a single SQLite file, plus an optional slash command and hooks.

The idea (and the one limit to understand first)

Claude Code works in turns: the model only "sees" outside data when a tool returns a result or a hook injects text. There is no native push that wakes a session mid-turn. So "staying connected" is built from two pieces:

  1. A shared store (the bus) every session reads and writes — for exchanging state and messages.
  2. A poll convention or a hook that makes each session check the bus — so they react to what the other left.

This project ships both.

Architecture

  Session A (terminal 1)        Session B (terminal 2)
  claude  ->  bus (MCP)         claude  ->  bus (MCP)        one server per session
                  \                   /
                   v                 v
              ~/.claude-bus/bus.db   (SQLite WAL = the bus, the real shared state)

For the local stdio transport each session launches its own server process; they share state through the SQLite file (WAL handles concurrent writes). For the HTTP transport a single process serves every client. Both use the same schema, so they are interchangeable backends.

Tools exposed: register, agents, send, inbox, set_state, get_state.


Install — pick one

1. Quick local (one command)

No Python packaging, no plugin. Good for one machine.

bash install_claude_bus.sh          # creates ~/claude-bus, registers the MCP server

It registers the bus server at user scope and installs the /bus command. Then open two terminals, run claude in each, and type /bus backend / /bus frontend.

2. Claude Code plugin (recommended for sharing)

This whole repo is also a plugin and a single-plugin marketplace. Anyone with Claude Code installs the MCP server, the /bus command, and the reactive hook in one step. Requires uv on PATH (brew install uv), which runs the bundled package with no manual venv.

/plugin marketplace add f3r21/claude-bus
/plugin install claude-bus@claude-bus

The plugin's .mcp.json runs the server via uvx --from "${CLAUDE_PLUGIN_ROOT}" claude-bus, so it works straight from the installed plugin directory.

3. PyPI + uvx (clean server install)

Publish the package, then any session points at it with zero venv management:

python -m build && twine upload dist/*        # one-time publish
# then, on any machine:
claude mcp add -s user bus -- uvx claude-bus

uvx resolves and caches dependencies like npx for Python — this is the cleanest fix if you hit venv issues (e.g. a pyenv build without the venv module).

4. HTTP server + Docker (multi-machine / always-on)

Run one shared bus other machines connect to by URL.

docker compose up -d                          # serves on :8765, data in a volume
# on each client machine:
claude mcp add --transport http bus http://YOUR_HOST:8765/mcp

Without Docker: pip install . && claude-bus-http (honors BUS_HOST, BUS_PORT, BUS_DB).


Usage

Give each session an identity once, then talk normally:

  • /bus backend — join as backend (registers, lists peers, reads inbox).
  • /bus (no argument) — "check the bus": read your inbox and see who is connected.

After joining, natural language maps to the tools:

You say Tool
"tell frontend the login is ready" send("backend","frontend",...)
"broadcast to everyone ..." send("backend","all",...)
"anything for me? / check the bus" inbox("backend")
"save X as login_schema" set_state("login_schema",...)
"what's in login_schema?" get_state("login_schema")
"who's connected?" agents()

Reactive mode (hooks)

Polling works, but to make a session pick up messages on its own when it finishes a turn, enable the Stop hook. With the plugin it ships in hooks/hooks.json; it acts only when BUS_NAME is set, so set the same name you join with:

export BUS_NAME=backend && claude        # then /bus backend

The hook marks messages read before blocking, so there is no infinite loop (and it honors stop_hook_active).


Repository layout

claude-bus/
  .claude-plugin/
    plugin.json            plugin manifest
    marketplace.json       single-plugin marketplace (source ".")
  .mcp.json                plugin MCP server (uvx, ${CLAUDE_PLUGIN_ROOT})
  commands/bus.md          the /bus slash command
  hooks/
    hooks.json             plugin Stop hook
    stop_bus.py            reactive: re-inject pending messages
    inject_state.py        optional: inject bus state on each prompt
  src/claude_bus/
    core.py                SQLite + tool logic (shared by all transports)
    server.py              stdio entry point  -> claude-bus
    http_server.py         http entry point   -> claude-bus-http
  bus_server.py            thin shim used by the local installer
  pyproject.toml           PyPI packaging + console scripts
  Dockerfile               + docker-compose.yml for the HTTP deploy
  setup.sh                 local register/install helper
  install_claude_bus.sh    self-contained local installer

Notes and limits

  • Same machine, a few sessions: stdio + SQLite is plenty (and durable).
  • Different machines: use the HTTP transport. Push still doesn't exist; hooks are what provide reactivity in every mode.
  • For one session spawning parallel subtasks (parent -> child, not peers), use Claude Code subagents instead — no bus needed.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

claude_bus-0.1.0.tar.gz (11.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

claude_bus-0.1.0-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file claude_bus-0.1.0.tar.gz.

File metadata

  • Download URL: claude_bus-0.1.0.tar.gz
  • Upload date:
  • Size: 11.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for claude_bus-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f424572a503024f6f500fa4cd6750edd95ec74d0dc667eed0aac1d684def2262
MD5 c8a88a8c25649d7de02d00493d5ca361
BLAKE2b-256 07f4d0606911aa3c5bffd26280b3af3c6ef1c64796c7b15985f5146cb7164be4

See more details on using hashes here.

File details

Details for the file claude_bus-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: claude_bus-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for claude_bus-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 556ab7c226be31a83860e5c38a9ab99c0da0954d6a7ffb1d4750281c263285b0
MD5 727a3528cfb3c1088fe8eb0b6ad2ea6a
BLAKE2b-256 40587ee39eba875431a3a785850ae53abf98348bd9bcda8cc443f31f4391be05

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page