{"_id":"@bike4mind/cc-bridge","_rev":"19-8104ff70e885dbd4beadd0f9921bb556","name":"@bike4mind/cc-bridge","dist-tags":{"chore-migrate-to-changesets":"0.0.1","latest":"0.0.1"},"versions":{"0.0.1":{"name":"@bike4mind/cc-bridge","version":"0.0.1","keywords":["bike4mind","claude-code","tavern","bridge"],"author":{"name":"Bike4Mind"},"license":"UNLICENSED","_id":"@bike4mind/cc-bridge@0.0.1","maintainers":[{"name":"stormyb4m","email":"stormy@milliononmars.com"},{"name":"mai___","email":"michael@milliononmars.com"},{"name":"ken-b4m","email":"ken@milliononmars.com"},{"name":"jonasi","email":"isao.jonas@gmail.com"},{"name":"victor_milliononmars","email":"victor@milliononmars.com"},{"name":"jasonbdaro","email":"jason@milliononmars.com"},{"name":"erikbethke","email":"erik@milliononmars.com"},{"name":"judecal","email":"jude@milliononmars.com"},{"name":"mom_nao","email":"nao@milliononmars.com"},{"name":"illiamom","email":"illia@milliononmars.com"},{"name":"cgtorniado","email":"cleo@milliononmars.com"},{"name":"ktdejesus","email":"kevin@milliononmars.com"},{"name":"julsanchez","email":"julie@milliononmars.com"},{"name":"matttan25","email":"matt@milliononmars.com"},{"name":"allanrhey","email":"allan@milliononmars.com"},{"name":"jjmrf","email":"james@milliononmars.com"},{"name":"rexendy","email":"rexen@milliononmars.com"},{"name":"jarlmom","email":"jarl@milliononmars.com"},{"name":"jaydeebee","email":"six.random.letters@gmail.com"},{"name":"maxb4m","email":"max@milliononmars.com"},{"name":"juicewa","email":"joshua@milliononmars.com"},{"name":"poymode","email":"poy@milliononmars.com"}],"homepage":"https://github.com/bike4mind/lumina5#readme","bugs":{"url":"https://github.com/bike4mind/lumina5/issues"},"bin":{"cc-bridge":"bin/cc-bridge.mjs","b4m-cc-bridge":"bin/cc-bridge.mjs"},"dist":{"shasum":"ca6e203472582ccdf7ff5a584bc0a34f7eefbbec","tarball":"https://registry.npmjs.org/@bike4mind/cc-bridge/-/cc-bridge-0.0.1.tgz","fileCount":2,"integrity":"sha512-/e2Kdi9bxmKOF8XfgKbAwq/w+kILP5ZVYngwrCJYbfuYgYrabPMfyE6QJD5kw4+tXWjWaJ+gjk90342JW2T8ZQ==","signatures":[{"sig":"MEUCIFTu3Tt3siEfrNRkPKmhw+pC3x8UC+15BxA19VyHGtaPAiEAkd/KaPDbx2bC0vjMaF9s8Jpq/xkw4fIF50wjfSZkqT8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9552},"type":"module","_from":"file:bike4mind-cc-bridge-0.0.1.tgz","engines":{"node":">=20.0.0"},"scripts":{"dev":"tsx src/index.ts","build":"tsdown","start":"node dist/index.mjs","typecheck":"tsc --noEmit","compile:all":"pnpm run compile:linux-x64 && pnpm run compile:linux-arm64 && pnpm run compile:darwin-x64 && pnpm run compile:darwin-arm64 && pnpm run compile:win32-x64","upload-binaries":"tsx scripts/upload-binaries.ts","compile:linux-x64":"bun build --compile --target=bun-linux-x64 --minify --outfile dist-bin/cc-bridge-linux-x64 src/index.ts","compile:win32-x64":"bun build --compile --target=bun-windows-x64 --minify --outfile dist-bin/cc-bridge-win32-x64.exe src/index.ts","compile:darwin-x64":"bun build --compile --target=bun-darwin-x64 --minify --outfile dist-bin/cc-bridge-darwin-x64 src/index.ts","compile:linux-arm64":"bun build --compile --target=bun-linux-arm64 --minify --outfile dist-bin/cc-bridge-linux-arm64 src/index.ts","compile:darwin-arm64":"bun build --compile --target=bun-darwin-arm64 --minify --outfile dist-bin/cc-bridge-darwin-arm64 src/index.ts"},"_npmUser":{"name":"poymode","email":"poy@milliononmars.com"},"_resolved":"/tmp/4977b76a23386a230d491681072d2c1a/bike4mind-cc-bridge-0.0.1.tgz","_integrity":"sha512-/e2Kdi9bxmKOF8XfgKbAwq/w+kILP5ZVYngwrCJYbfuYgYrabPMfyE6QJD5kw4+tXWjWaJ+gjk90342JW2T8ZQ==","repository":{"url":"git+https://github.com/bike4mind/lumina5.git","type":"git"},"_npmVersion":"10.9.7","description":"Local daemon that surfaces your Claude Code sessions as sprites in the Bike4Mind Tavern","directories":{},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.19.0","zod":"^4.3.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","tsdown":"^0.21.7","@types/ws":"^8.18.1","typescript":"^5.9.3","@types/node":"^22.9.0","@bike4mind/common":"0.0.0-chore-migrate-to-changesets-20260418165836","@aws-sdk/client-s3":"^3.1026.0"},"_npmOperationalInternal":{"tmp":"tmp/cc-bridge_0.0.1_1776531526308_0.24858378431170403","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-04-18T16:58:46.236Z","modified":"2026-08-31T18:38:27.839Z","0.0.1":"2026-04-18T16:58:46.428Z"},"bugs":{"url":"https://github.com/bike4mind/lumina5/issues"},"author":{"name":"Bike4Mind"},"license":"UNLICENSED","homepage":"https://github.com/bike4mind/lumina5#readme","keywords":["bike4mind","claude-code","tavern","bridge"],"repository":{"url":"git+https://github.com/bike4mind/lumina5.git","type":"git"},"description":"Local daemon that surfaces your Claude Code sessions as sprites in the Bike4Mind Tavern","maintainers":[{"email":"stormy@milliononmars.com","name":"stormyb4m"},{"email":"michael@milliononmars.com","name":"mai___"},{"email":"ken@milliononmars.com","name":"ken-b4m"},{"email":"lboyles413@gmail.com","name":"lboyless"},{"email":"rodelcruzph@gmail.com","name":"rodelcruzph"},{"email":"michaelg@bike4mind.com","name":"michaeljymsgutierrez"},{"email":"aflordelis.dev@gmail.com","name":"aflordelis"},{"email":"angelolao.08@gmail.com","name":"angelolao"},{"email":"gsreyson@gmail.com","name":"gsreyson"},{"email":"cleffrem@bike4mind.com","name":"cleffrem-dev"},{"email":"mariah@bike4mind.com","name":"mariah.milliononmars"},{"email":"chad@milliononmars.com","name":"chadyuson"},{"email":"victor@milliononmars.com","name":"victor_milliononmars"},{"email":"riley@bike4mind.com","name":"rileygb4m"},{"email":"ariel.lopezf@gmail.com","name":"choyno"},{"email":"james@milliononmars.com","name":"jjmrf"},{"email":"wilfred@milliononmars.com","name":"wescarda"},{"email":"jason@milliononmars.com","name":"jasonbdaro"},{"email":"erik@milliononmars.com","name":"erikbethke"},{"email":"jude@milliononmars.com","name":"judecal"},{"email":"nao@milliononmars.com","name":"mom_nao"},{"email":"illia@milliononmars.com","name":"illiamom"},{"email":"cleo@milliononmars.com","name":"cgtorniado"},{"email":"kevin@milliononmars.com","name":"ktdejesus"},{"email":"julie@milliononmars.com","name":"julsanchez"},{"email":"matt@milliononmars.com","name":"matttan25"},{"email":"allan@milliononmars.com","name":"allanrhey"},{"email":"rexen@milliononmars.com","name":"rexendy"},{"email":"jarl@milliononmars.com","name":"jarlmom"},{"email":"max@milliononmars.com","name":"maxb4m"},{"email":"joshua@milliononmars.com","name":"juicewa"},{"email":"poy@milliononmars.com","name":"poymode"}],"readme":"# @bike4mind/cc-bridge\n\nLocal daemon that makes your running Claude Code sessions show up as sprites\nin the Bike4Mind Tavern. Distributed as a single self-contained binary users\ndownload from the tavern.\n\n## How it works\n\n1. User clicks **Connect Claude Code** in the tavern → server mints a\n   one-time pairing token + wraps the bridge binary in a zip.\n2. User unzips, double-clicks the binary. On first run it:\n   - Redeems the pairing token via `POST /api/cc-bridge/redeem` for a\n     durable, device-scoped API key.\n   - Writes durable config to `~/.b4m/cc-bridge.json`.\n   - Merges hooks into `~/.claude/settings.json`.\n   - Opens a persistent WebSocket to the tavern's API Gateway.\n3. Every `claude` session on the machine fires hooks that the bridge\n   translates to `cc_agent_*` WS messages → sprite appears in the tavern.\n\n## What the bridge sends to the tavern\n\nThe bridge is outbound-only and sends exactly these fields to the\nconfigured `baseUrl`. Nothing else on disk, no transcripts, no tool\noutput — hooks are the only source:\n\n| Event                 | Fields sent                                                                                       |\n| --------------------- | ------------------------------------------------------------------------------------------------- |\n| `cc_agent_register`   | `instanceId`, `deviceId`, `workspaceName` (basename of cwd), `workspacePath` (cwd), `startedAt`   |\n| `cc_agent_event` status | Status (`running` / `idle` / `awaiting_input`), optional short `text` (≤240 chars, from hook)   |\n| `cc_agent_event` message | **User prompt first 240 chars** only when `UserPromptSubmit` fires                             |\n| `cc_agent_disconnect` | `instanceId`, optional `reason`                                                                   |\n\n**Prompt text leaves your machine.** Every `/exit`'d Claude session's\nfirst 240 characters of each prompt are transmitted so the tavern can\nshow a compact \"last request\" hover preview. If you want to run the\nbridge without that, disable the `UserPromptSubmit` entry in\n`~/.claude/settings.json` after first launch — hooks are merged, not\nlocked, and the bridge will still function (it just loses the hover\ntext).\n\nClaude Code tool outputs, assistant responses, and file contents are\n**not** captured by any hook the bridge installs and are never sent.\n\n## Running from source (dev loop)\n\nNo need to compile a binary during iteration:\n\n```bash\n# 1. Mint a pair.json via the tavern's \"Advanced\" flow.\n# 2. Save it OUTSIDE the repo (or in apps/cc-bridge/pair.json — that path\n#    is gitignored so the token never gets committed).\n# 3. Point the bridge at it and run:\nCC_BRIDGE_PAIR_FILE=/tmp/my-pair.json pnpm --filter @bike4mind/cc-bridge dev\n```\n\n> Pairing tokens grant an API key on first redemption. Never commit one,\n> paste one into a PR, or check `pair.json` into git — the file is listed\n> in `.gitignore` specifically for this reason.\n\nThe `dev` script runs `src/index.ts` directly via `tsx`, auto-discovers\n`pair.json` (via `CC_BRIDGE_PAIR_FILE` or adjacent to the entry script),\nand connects.\n\n## Building distributable binaries\n\nBun cross-compiles natively — no Docker, no target-specific toolchain, no\nenv juggling. Five single-file binaries come out of one command on any host:\n\n```bash\npnpm --filter @bike4mind/cc-bridge compile:all\n```\n\nOr pick one:\n\n```bash\npnpm --filter @bike4mind/cc-bridge compile:linux-x64\npnpm --filter @bike4mind/cc-bridge compile:linux-arm64\npnpm --filter @bike4mind/cc-bridge compile:darwin-x64\npnpm --filter @bike4mind/cc-bridge compile:darwin-arm64\npnpm --filter @bike4mind/cc-bridge compile:win32-x64\n```\n\nArtifacts land in `apps/cc-bridge/dist-bin/`. First build for each new\ntarget downloads that platform's Bun runtime (~30–50 MB, cached after).\n\n**Prerequisite:** Bun must be installed locally (`curl -fsSL https://bun.sh/install | bash`).\n\n### Binaries are env-agnostic\n\nNothing stage-specific is baked in. The binary reads `baseUrl` from the\n`pair.json` it ships with and resolves the WS endpoint at runtime via\n`/api/settings/serverConfig`. **Build once, upload to every stage's\nbucket.** Don't rebuild per env.\n\n## Publishing binaries\n\nBinaries live in each stage's `appFilesBucket` under\n`cc-bridge/artifacts/<version>/cc-bridge-<os>-<arch>[.exe]`. The download\nendpoint pulls from the `latest` tag by default.\n\n### 1 — Find the bucket name for the stage\n\nEach SST stage has its own bucket; names include a random suffix, so you\nneed to look them up once per stage:\n\n```bash\n# Staging (SST stage = \"dev\")\n./for-env local aws s3 ls | grep -i appfiles\n\n# Production\n./for-env prod aws s3 ls | grep -i appfiles\n```\n\nExample output:\n\n```\n2026-01-22 18:03:11 dev-appfilesbucket-a1b2c3d4\n```\n\n### 2 — Upload\n\nRun the uploader with the stage's AWS profile (`./for-env <env>`) and the\nbucket name you just found:\n\n```bash\n# Staging\nCC_BRIDGE_BUCKET=dev-appfilesbucket-a1b2c3d4 \\\n  ./for-env local pnpm --filter @bike4mind/cc-bridge upload-binaries\n\n# Production\nCC_BRIDGE_BUCKET=production-appfilesbucket-xxxxxx \\\n  ./for-env prod pnpm --filter @bike4mind/cc-bridge upload-binaries\n```\n\nThe script walks `dist-bin/` and uploads every `cc-bridge-*` artifact it\nfinds. Re-runnable (each upload overwrites the same key). Defaults to the\n`latest` version tag; override with `CC_BRIDGE_VERSION=0.0.1 ...` for a\npinned build alongside `latest`.\n\n### 3 — Verify\n\nSmoke-test the download flow end-to-end in the target stage:\n\n1. Visit the stage's tavern URL.\n2. Open the **Claude Code** window → **Connect Claude Code**.\n3. Pick a platform → **Download Bridge** → confirm the zip downloads.\n\n## Stage matrix\n\n| Env       | Tavern URL                        | SST stage     | `for-env` arg | AWS profile     |\n| --------- | --------------------------------- | ------------- | ------------- | --------------- |\n| Local/dev | `localhost:3000`                  | (your local)  | `local`       | `bike4mind-dev` |\n| Staging   | `app.staging.bike4mind.com`       | `dev`         | `local`       | `bike4mind-dev` |\n| Prod      | `app.bike4mind.com`               | `production`  | `prod`        | `bike4mind-prod`|\n\n> Staging runs on the `dev` SST stage — AWS resources are prefixed\n> `dev-`, not `staging-`. `./for-env local` is the right wrapper for\n> anything against staging.\n\nInfra changes (the download endpoint, lifecycle rule on\n`cc-bridge-downloads/`, new WS routes) must be deployed to each stage\nbefore its upload makes the download flow functional:\n\n```bash\nnpx sst deploy --stage dev           # staging\nnpx sst deploy --stage production    # production\n```\n\n## Known limitations (PoC)\n\n- **Unsigned binaries.** macOS Gatekeeper warns on first launch\n  (right-click → Open to bypass); Windows SmartScreen does the same.\n  The bundled README tells end users how to proceed. Code-sign +\n  notarize before any public release.\n- **Manual publish step.** No CI job for the build + upload matrix yet;\n  `compile:all` + `upload-binaries` must be run by a human against each\n  stage.\n- **Download endpoint resolves `latest` only.** Deploying a rebuild\n  swaps the download out from under any in-flight users. Pinning to a\n  version tag on the endpoint is a small follow-up before real traffic.\n- **API key scope is `AI_CHAT`.** There's no dedicated `CC_BRIDGE`\n  scope yet; tightening that is a known follow-up.\n","readmeFilename":"README.md"}