Skip to content

pablospe/claude-code-bridge

Repository files navigation

Claude Code Bridge

A TypeScript library + CLI that lets external UIs and orchestrators drive an already-running, already-authenticated Claude Code session — without restarting it, without scraping the terminal, and without talking to the model API directly.

The idea

Channels for inbound general content; MCP tools for outbound. A consumer pushes a message in via a Claude Code channel (notifications/claude/channel); Claude responds by calling one of three MCP tools (bridge_reply / bridge_progress / bridge_done); every turn is persisted as an append-only JSONL event log.

        +-------------------------------------------+
        |                 Consumer                  |
        |        ccb serve, T3 Code, agtx, ...      |
        +-------------------------------------------+
              |                          ^
              | sendMessage()            | events(sessionId)
              v                          |
        +-------------------------------------------+
        |                  Bridge                   |
        |          session state + event log        |
        +-------------------------------------------+
              ||                         ^^
              || channels (inbound)      || MCP tools (outbound)
              vv                         ||
        +-------------------------------------------+
        |                Claude Code                |
        |             claude + ccb plugin           |
        +-------------------------------------------+

This is not an ACP replacement and not a universal agent runtime. It exists for the specific case where you want an already-authenticated interactive claude to be the runtime.

See docs/ARCHITECTURE.md for the full design, process topology, and a library-usage example.

Demo

demo

Screnshot

ccb demo

Install

1. Install the CLI globally (bun ≥ 1.3 must be on PATH):

> bun add -g @pablospe/claude-code-bridge

2. Register the plugin inside a claude session:

/plugin marketplace add https://github.com/pablospe/claude-code-bridge
/plugin install ccb@claude-code-bridge

The plugin connects a normal claude session back to the bridge automatically — including the hook relay, so you get tool.event visibility out of the box.

What this installs / why order matters
  • Four bins land on your PATH: ccb (the CLI), ccb-channel-server and ccb-hook-relay (spawned by Claude Code), and ccb-launcher (a Node-side launcher; see limitations).
  • npm name: published as @pablospe/claude-code-bridge, scoped under the author's namespace; the GitHub repo name stays claude-code-bridge.
  • Global install must come first: the plugin manifest invokes ccb-channel-server / ccb-hook-relay by bare name, so without them on PATH claude reports command not found.
  • Channels is a research preview: it must be enabled / allowlisted for your account — see docs/SMOKE.md for that one-time step.

Usage: two terminals

The bridge is the consumer side; your claude session is the runtime — you drive claude from the bridge and watch the structured event stream.

1. Start the bridge (Terminal 1). It mints a session id, writes a per-session MCP config, and prints the exact claude command for terminal 2:

ccb serve
#   listening on 127.0.0.1:18484
#   bridge_uuid: 4f3b6e10-…
#
#   in a second terminal, start claude pointed at this bridge:
#     claude --dangerously-load-development-channels server:ccb \
#       --mcp-config /tmp/ccb-serve-4f3b6e10-….mcp.json \
#       --allowed-tools "mcp__ccb__bridge_reply mcp__ccb__bridge_progress mcp__ccb__bridge_done"

2. Start claude (Terminal 2). Paste the command ccb serve printed.

3. Send a prompt (back in Terminal 1) — it's pushed to claude as a channel notification:

what is 11 squared?

Terminal 1 streams the round-trip as structured events:

[message.sent]  m1 "what is 11 squared?"
[tool.event]    PreToolUse Bash "…"
[tool.event]    PostToolUse Bash (12 B)
[agent.reply final=true] "11 squared is 121."
[agent.done]
Why the pasted command matters / session-id tips
  • The dev-channels flag is what enables inbound. It loads the ccb channel from the generated --mcp-config (whose env carries the endpoint + session id); a plain plugin launch gives outbound tools + hooks only.
  • Need a session id without copy-paste? Bun is already installed: bun -e 'console.log(crypto.randomUUID())', or use uuidgen if you have it, and pass the same value to ccb serve --session-id and export CCB_SESSION_ID.

For the full verified walkthrough — including enabling the channels preview and the alternative ccb-launcher flow — see docs/SMOKE.md.

Did it install? (no claude needed)

A mock supervisor runs the whole event pipeline in-process, with no real claude and no channels — handy as a smoke check:

ccb demo --supervisor=mock "what is 11 squared?"
[session.started] d91356a6-…
[message.sent] 916c268f-… "what is 11 squared?"
[agent.progress] "thinking"
[agent.reply final=true] "echo: what is 11 squared?"
[session.ended]

Development

From a source checkout — also the way to run the bridge before the npm package is published:

git clone https://github.com/pablospe/claude-code-bridge
cd claude-code-bridge
bun install
bun test
# the CLI runs straight from source (no global install):
bun apps/ccb/src/cli.ts demo --supervisor=mock "hello world"

--channels=dev-flag exercises the real-claude channel surface without the plugin (uses claude --dangerously-load-development-channels), so you can test against your local source without publishing. To exercise the plugin path against local source, bun link @pablospe/claude-code-bridge in this checkout and bun link --global @pablospe/claude-code-bridge where you run claude; the plugin manifest references bin names, so PATH resolution finds the linked bins.

Requirements & limitations

The real-claude paths need Claude Code v2.1.80+, authenticated, with the channels research preview enabled for your account. The preview is gated server-side (the tengu_harbor flag) and isn't on for everyone yet — see docs/SMOKE.md for the availability diagnostics.

  • Inbound is dev-flag-only. The full round-trip needs the --dangerously-load-development-channels + --mcp-config path (what ccb serve prints). The plugin path gives outbound tools + hooks but not inbound on individual accounts.
  • Managed launch needs node-pty. ccb demo --supervisor=claude spawns claude via node-pty (works under both Node and Bun); if node-pty can't load on the host, use the two-terminal flow or the ccb-launcher bin instead.

Where to go next

  • docs/ARCHITECTURE.md — full design, process topology, library-usage example, and channel-direction nuance.
  • docs/CLI.mdccb CLI command reference (demo, mcp-config, serve).
  • docs/SMOKE.md — real-claude verification procedure (plugin, dev-flag, and two-terminal launcher).
  • docs/ROADMAP.md — milestones, planned work, and consumer-gated follow-ups.

License

MIT.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors