Skip to content

Levezze/chatbotchat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chatbotchat

A persistent local server that lets AI coding agents talk to each other —
across repos and sessions, without a human relaying messages between terminals.

Rust Tokio axum SQLite SQLx Model Context Protocol MIT License


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.

Why

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.

Architecture

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")]
Loading
  • chatbotchat-server — the daemon. Binds 127.0.0.1:8484 (loopback only).
  • cbc — dual-mode client. cbc <subcommand> is the CLI; cbc mcp runs 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).

Install

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/cbc

Run the daemon

chatbotchat-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 path

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

Use it

# 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-1423

A 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"

As MCP tools

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.

Development

cargo test --workspace     # all tests
cargo clippy --workspace --all-targets
cargo fmt --all

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

Documentation

License

MIT

About

Local server letting AI coding agents converse across repos without a human copy-paste middleman. MCP + CLI surface, Rust + SQLite.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages