@bike4mind/cc-bridge
v0.0.1
Published
Local daemon that surfaces your Claude Code sessions as sprites in the Bike4Mind Tavern
Readme
@bike4mind/cc-bridge
Local daemon that makes your running Claude Code sessions show up as sprites in the Bike4Mind Tavern. Distributed as a single self-contained binary users download from the tavern.
How it works
- User clicks Connect Claude Code in the tavern → server mints a one-time pairing token + wraps the bridge binary in a zip.
- User unzips, double-clicks the binary. On first run it:
- Redeems the pairing token via
POST /api/cc-bridge/redeemfor a durable, device-scoped API key. - Writes durable config to
~/.b4m/cc-bridge.json. - Merges hooks into
~/.claude/settings.json. - Opens a persistent WebSocket to the tavern's API Gateway.
- Redeems the pairing token via
- Every
claudesession on the machine fires hooks that the bridge translates tocc_agent_*WS messages → sprite appears in the tavern.
What the bridge sends to the tavern
The bridge is outbound-only and sends exactly these fields to the
configured baseUrl. Nothing else on disk, no transcripts, no tool
output — hooks are the only source:
| Event | Fields sent |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| cc_agent_register | instanceId, deviceId, workspaceName (basename of cwd), workspacePath (cwd), startedAt |
| cc_agent_event status | Status (running / idle / awaiting_input), optional short text (≤240 chars, from hook) |
| cc_agent_event message | User prompt first 240 chars only when UserPromptSubmit fires |
| cc_agent_disconnect | instanceId, optional reason |
Prompt text leaves your machine. Every /exit'd Claude session's
first 240 characters of each prompt are transmitted so the tavern can
show a compact "last request" hover preview. If you want to run the
bridge without that, disable the UserPromptSubmit entry in
~/.claude/settings.json after first launch — hooks are merged, not
locked, and the bridge will still function (it just loses the hover
text).
Claude Code tool outputs, assistant responses, and file contents are not captured by any hook the bridge installs and are never sent.
Running from source (dev loop)
No need to compile a binary during iteration:
# 1. Mint a pair.json via the tavern's "Advanced" flow.
# 2. Save it OUTSIDE the repo (or in apps/cc-bridge/pair.json — that path
# is gitignored so the token never gets committed).
# 3. Point the bridge at it and run:
CC_BRIDGE_PAIR_FILE=/tmp/my-pair.json pnpm --filter @bike4mind/cc-bridge devPairing tokens grant an API key on first redemption. Never commit one, paste one into a PR, or check
pair.jsoninto git — the file is listed in.gitignorespecifically for this reason.
The dev script runs src/index.ts directly via tsx, auto-discovers
pair.json (via CC_BRIDGE_PAIR_FILE or adjacent to the entry script),
and connects.
Building distributable binaries
Bun cross-compiles natively — no Docker, no target-specific toolchain, no env juggling. Five single-file binaries come out of one command on any host:
pnpm --filter @bike4mind/cc-bridge compile:allOr pick one:
pnpm --filter @bike4mind/cc-bridge compile:linux-x64
pnpm --filter @bike4mind/cc-bridge compile:linux-arm64
pnpm --filter @bike4mind/cc-bridge compile:darwin-x64
pnpm --filter @bike4mind/cc-bridge compile:darwin-arm64
pnpm --filter @bike4mind/cc-bridge compile:win32-x64Artifacts land in apps/cc-bridge/dist-bin/. First build for each new
target downloads that platform's Bun runtime (~30–50 MB, cached after).
Prerequisite: Bun must be installed locally (curl -fsSL https://bun.sh/install | bash).
Binaries are env-agnostic
Nothing stage-specific is baked in. The binary reads baseUrl from the
pair.json it ships with and resolves the WS endpoint at runtime via
/api/settings/serverConfig. Build once, upload to every stage's
bucket. Don't rebuild per env.
Publishing binaries
Binaries live in each stage's appFilesBucket under
cc-bridge/artifacts/<version>/cc-bridge-<os>-<arch>[.exe]. The download
endpoint pulls from the latest tag by default.
1 — Find the bucket name for the stage
Each SST stage has its own bucket; names include a random suffix, so you need to look them up once per stage:
# Staging (SST stage = "dev")
./for-env local aws s3 ls | grep -i appfiles
# Production
./for-env prod aws s3 ls | grep -i appfilesExample output:
2026-01-22 18:03:11 dev-appfilesbucket-a1b2c3d42 — Upload
Run the uploader with the stage's AWS profile (./for-env <env>) and the
bucket name you just found:
# Staging
CC_BRIDGE_BUCKET=dev-appfilesbucket-a1b2c3d4 \
./for-env local pnpm --filter @bike4mind/cc-bridge upload-binaries
# Production
CC_BRIDGE_BUCKET=production-appfilesbucket-xxxxxx \
./for-env prod pnpm --filter @bike4mind/cc-bridge upload-binariesThe script walks dist-bin/ and uploads every cc-bridge-* artifact it
finds. Re-runnable (each upload overwrites the same key). Defaults to the
latest version tag; override with CC_BRIDGE_VERSION=0.0.1 ... for a
pinned build alongside latest.
3 — Verify
Smoke-test the download flow end-to-end in the target stage:
- Visit the stage's tavern URL.
- Open the Claude Code window → Connect Claude Code.
- Pick a platform → Download Bridge → confirm the zip downloads.
Stage matrix
| Env | Tavern URL | SST stage | for-env arg | AWS profile |
| --------- | --------------------------------- | ------------- | ------------- | --------------- |
| Local/dev | localhost:3000 | (your local) | local | bike4mind-dev |
| Staging | app.staging.bike4mind.com | dev | local | bike4mind-dev |
| Prod | app.bike4mind.com | production | prod | bike4mind-prod|
Staging runs on the
devSST stage — AWS resources are prefixeddev-, notstaging-../for-env localis the right wrapper for anything against staging.
Infra changes (the download endpoint, lifecycle rule on
cc-bridge-downloads/, new WS routes) must be deployed to each stage
before its upload makes the download flow functional:
npx sst deploy --stage dev # staging
npx sst deploy --stage production # productionKnown limitations (PoC)
- Unsigned binaries. macOS Gatekeeper warns on first launch (right-click → Open to bypass); Windows SmartScreen does the same. The bundled README tells end users how to proceed. Code-sign + notarize before any public release.
- Manual publish step. No CI job for the build + upload matrix yet;
compile:all+upload-binariesmust be run by a human against each stage. - Download endpoint resolves
latestonly. Deploying a rebuild swaps the download out from under any in-flight users. Pinning to a version tag on the endpoint is a small follow-up before real traffic. - API key scope is
AI_CHAT. There's no dedicatedCC_BRIDGEscope yet; tightening that is a known follow-up.
