A persistent local server that lets AI coding agents talk to each other —
across repos and sessions, without a human relaying messages between terminals.
One always-on daemon owns the conversation state (SQLite). Agents talk to it through a uniform surface exposed both as MCP tools and a CLI, so the same actions work whether an agent reaches them over MCP or a human runs them by hand.
Status: work in progress — not operational yet. chatbotchat is under active development and isn't ready for real use. See the v1 design and the issue tracker for what's planned.
I'm trying to thread the needle between proper hands-on development and fully agentic, hands-off "vibe coding." I'm a firm believer in quality-of-life automation — but I'm also keenly aware of how it can breed laziness and costly problems down the line.
chatbotchat is meant to bridge the gap between the developer manually shuttling
messages between their repos and agents, and the hyped, over-the-top "agent
swarms" that are just a black box. The idea is for chatbotchats to be invoked
intentionally, when needed, so you always understand where and what is
happening. It also caps how many messages agents can exchange, and requires a
human in the loop when they disagree or the path forward isn't clear.
Future features include a proper GUI, "more-than-two" agent chats, and a shared chat with the user and multiple agents — directing questions at specific agents, vetoing messages, and semantic vector-DB lookups over repo-specific data and previous conversations.
flowchart LR
cli["cbc (CLI)"] --> server
mcp["cbc mcp<br/>(MCP stdio)"] --> server
server["chatbotchat-server<br/>axum · 127.0.0.1:8484"] --> db[("~/.chatbotchat/state.db<br/>SQLite · WAL")]
chatbotchat-server— the daemon. Binds127.0.0.1:8484(loopback only).cbc— dual-mode client.cbc <subcommand>is the CLI;cbc mcpruns an MCP stdio server exposing the same actions as tools.- Three libraries back them:
chatbotchat-core(storage + HTTP router),chatbotchat-client(typed HTTP client),chatbotchat-protocol(shared DTOs).
Requires a recent stable Rust toolchain.
# Build everything
cargo build --release
# Or install both binaries onto your PATH
cargo install --path bins/chatbotchat-server
cargo install --path bins/cbcchatbotchat-server # binds 127.0.0.1:8484, DB at ~/.chatbotchat/state.db
chatbotchat-server --port 8485 # custom port
chatbotchat-server --db /tmp/x.db # custom DB pathTo keep it always running on macOS, edit etc/com.chatbotchat.server.plist
(set the absolute binary path), copy it to ~/Library/LaunchAgents/, and
launchctl load it. (A polished install flow comes in a later slice.)
# Terminal A — open a room
cbc open "slider labels"
# Room: slider-labels-20260528-1423
# Share: /cbc-join slider-labels-20260528-1423
# Terminal B — join the room (repo + cwd are auto-detected; you supply the model)
cbc join slider-labels-20260528-1423 --model opus47
# Handle: chatbotchat-opus47-a3f2
# Resumed: false
# State: active
# Re-joining from the same repo/cwd with the same model is idempotent —
# it returns the same handle (Resumed: true). A different cwd or model
# produces a new handle.
# Terminal A — post a message (broadcast to all; add --to <handle> to target one)
cbc send slider-labels-20260528-1423 --model opus47 "what label fits the 0-100 slider?"
# Terminal B — long-poll for the next message addressed to you (or broadcast).
# Blocks up to 10 minutes server-side; prints `paused_by_timeout` on cap.
cbc wait slider-labels-20260528-1423 --model sonnet46
# From: chatbotchat-opus47-a3f2
# To: all
# Body: what label fits the 0-100 slider?
# Check status — includes the participant roster
cbc status slider-labels-20260528-1423A handle has the form <repo>-<model>-<sess4hex>. repo is the basename of the
git toplevel (falling back to the cwd basename), model is what you pass to
--model, and sess4hex is stable for a given (room, repo, model, cwd) tuple.
Point a client at a non-default daemon with --server or the CBC_SERVER
environment variable:
CBC_SERVER=http://127.0.0.1:8485 cbc open "test"Register cbc mcp as an MCP server in your agent. For Claude Code, add to your
MCP config (global registration is automated in a later slice):
{
"mcpServers": {
"chatbotchat": {
"command": "cbc",
"args": ["mcp"],
"env": { "CBC_SERVER": "http://127.0.0.1:8484" }
}
}
}This exposes the tools cbc_open_room, cbc_join_room, cbc_send, cbc_wait,
and cbc_status. cbc_join_room(room_id, model), cbc_send(room_id, model, body, to?), and cbc_wait(room_id, model) auto-detect repo and cwd from the
MCP server's working directory; you supply the model (your identity). cbc_wait
returns { message } when one arrives, or { status: "paused_by_timeout" } when
the 10-minute server cap elapses.
cargo test --workspace # all tests
cargo clippy --workspace --all-targets
cargo fmt --allTests run against real SQLite (in-memory or temp-file) and a real loopback daemon — no mocked database. The build is developed test-first, one vertical slice at a time.
docs/v1-design-locked.md— full v1 design (source of truth)docs/v2-ideas.md— deferred ideas (web UI, multi-agent rooms, vector search)
MIT
