@ccpocket/bridge
v1.96.0
Published
Bridge server that connects Claude Agent SDK and Codex CLI sessions to mobile devices via WebSocket
Maintainers
Readme
@ccpocket/bridge
Bridge server that connects Claude sessions powered by the Claude Agent SDK and Codex CLI to mobile devices via WebSocket.
This is the server component of ccpocket — a mobile client for Claude and Codex.
Quick Start
npx @ccpocket/bridge@latestA QR code will appear in your terminal. Scan it with the ccpocket mobile app to connect.
Claude sessions use ANTHROPIC_API_KEY by default. Subscription authentication
through the Bridge machine's Claude Code login is available only after explicit
opt-in with BRIDGE_ALLOW_CLAUDE_OAUTH=1; see
Claude Subscription Authentication.
Hosts that run Claude Code on Amazon Bedrock need neither of those; see
Claude on Amazon Bedrock.
Installation
# Recommended: run the latest Bridge directly
npx @ccpocket/bridge@latest
# Optional: install globally
npm install -g @ccpocket/bridge
ccpocket-bridge
# Show CLI help or version
ccpocket-bridge --help
ccpocket-bridge --versionConfiguration
| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| BRIDGE_PORT | 8765 | WebSocket port |
| BRIDGE_IDLE_SESSION_TTL_MINUTES | Disabled | Automatically stop idle sessions after this many minutes. Only a finite positive number enables this; unset, empty, zero, negative, or invalid values disable it. The 30-idle-session retention cap still applies. |
| BRIDGE_NOTIFY_GOAL_TURN_COMPLETED | false | Set exactly to true to notify intermediate Codex turns while a Goal is active. Goal completion, blockers, limits, approvals and errors remain enabled. Read at session creation; restart Bridge to apply to all sessions. |
| BRIDGE_HOST | 0.0.0.0 | Bind address |
| BRIDGE_API_KEY | (none) | API key authentication (enabled when set) |
| BRIDGE_ALLOWED_DIRS | $HOME | Comma-separated list of project directories the Bridge may access; set exactly to * to allow any directory |
| BRIDGE_FILE_DOWNLOAD_ALLOW_ALL_PATHS | unset (project only) | Set exactly to 1 to allow sharing/downloading any regular file readable by the Bridge process, including paths outside BRIDGE_ALLOWED_DIRS. Absolute and relative paths within the selected project work by default. |
| BRIDGE_PUBLIC_WS_URL | (none) | Public ws:// / wss:// URL used for startup deep link and QR code |
| BRIDGE_CODEX_APP_SERVER_MODE | private | Experimental Codex app-server mode: private, managed, or external |
| BRIDGE_CODEX_SHARED_APP_SERVER_URL | ws://127.0.0.1:8767 in managed mode | Experimental shared Codex app-server URL for Codex CLI co-presence |
| BRIDGE_CODEX_ASSIST_MODEL | gpt-5.6-luna | Codex model used for auto-rename and commit-message assist calls |
| BRIDGE_CODEX_ASSIST_REASONING_EFFORT | none | Reasoning effort used for Codex assist calls |
| BRIDGE_DEMO_MODE | (none) | Demo mode: hide Tailscale IPs and API key from QR code / logs |
| BRIDGE_RECORDING | (none) | Enable session recording for debugging (enabled when set) |
| BRIDGE_DISABLE_MDNS | (none) | Disable mDNS auto-discovery advertisement (macOS disables it automatically) |
| BRIDGE_ALLOW_CLAUDE_OAUTH | (none) | Set exactly to 1 to explicitly enable experimental Claude subscription authentication |
| BRIDGE_PROMPT_HISTORY_FILE | $HOME/.ccpocket/prompt-history-v2.json | Custom prompt history store path |
| BRIDGE_RECENT_SESSIONS_PROFILE | (none) | Log recent-session index timing when set to 1 or true |
| BRIDGE_FILE_LIST_MAX_ENTRIES | 5000 | Maximum file and directory entries returned to a client; non-positive or invalid values use the default |
| BRIDGE_FILE_LIST_MAX_BYTES | 524288 | Maximum serialized path bytes returned in a client file list; non-positive or invalid values use the default |
| BRIDGE_FILE_DOWNLOAD_MAX_SIZE_MB | 512 | Maximum size in MiB for a file downloaded from Explorer; non-positive or invalid values use the default |
| BRIDGE_FILE_UPLOAD_MAX_SIZE_MB | 512 | Maximum size in MiB for one file uploaded from Explorer; non-positive or invalid values use the default |
| BRIDGE_FILE_UPLOAD_MAX_RESERVED_MB | 2048 | Maximum total declared bytes reserved by pending Explorer uploads |
| BRIDGE_FILE_UPLOAD_MAX_CONCURRENT | 4 | Maximum number of Explorer upload bodies received concurrently |
| BRIDGE_DELTA_BATCH_MS | 100 | Milliseconds to batch streaming deltas per connected client; set to 0 to disable batching |
| BRIDGE_DELTA_BATCH_MAX_CHARS | 4096 | Maximum Unicode characters per batched streaming payload; non-positive or invalid values use the default |
| DIFF_IMAGE_AUTO_DISPLAY_KB | 1024 (1 MB) | Auto-display diff images up to this size, in KB |
| DIFF_IMAGE_MAX_SIZE_MB | 5 (5 MB) | Maximum diff image size available for on-demand loading, in MB |
| ANTHROPIC_API_KEY | (none) | Claude Agent SDK API key; recommended for predictable third-party product usage |
| ANTHROPIC_AUTH_TOKEN | (none) | Advanced Claude SDK auth token; prefer ANTHROPIC_API_KEY |
| CLAUDE_CODE_USE_BEDROCK | (none) | Claude Code setting; when enabled, Claude sessions run on Amazon Bedrock and no Anthropic credential is required |
| AWS_REGION / AWS_PROFILE | (none) | Bedrock region (required) and optional AWS credential profile read by Claude Code |
| OPENAI_API_KEY | (none) | Codex API key; Codex can also use ~/.codex/auth.json |
| HTTPS_PROXY / HTTP_PROXY / ALL_PROXY | (none) | Proxy for outgoing fetch requests (http://, https://, socks4://, socks5://) |
Lowercase proxy variables (https_proxy, http_proxy, all_proxy) are also
supported. When BRIDGE_PROMPT_HISTORY_FILE is not set and BRIDGE_PORT is not
8765, prompt history is stored in
$HOME/.ccpocket/prompt-history-v2-<port>.json.
Push relay uses Firebase Anonymous Auth automatically; no FCM environment variables are required.
Claude Subscription Authentication (Explicit Opt-In)
Anthropic's Legal and compliance page says its Commercial Terms do not prevent a platform from hosting the unmodified Claude Code binary when each end user signs in with their own subscription or other credentials, subject to the conditions listed there. CC Pocket similarly runs Anthropic's official Agent SDK on the user's Bridge machine and delegates credential loading to the host's Claude Code environment. CC Pocket does not copy, store, or refresh Claude OAuth credentials itself.
Running Claude Code on a user's computer and controlling it remotely is also a common pattern among tools such as OpenClaw, Happy, and Termopus, although their exact implementations differ from CC Pocket.
However, Anthropic's Agent SDK overview also says that, unless previously approved, third-party products should use API keys rather than offer Claude.ai login or subscription rate limits. The scope of these two statements is not clear for CC Pocket's architecture, so subscription authentication may be restricted or stop working in the future.
To avoid that uncertainty, use ANTHROPIC_API_KEY. If you understand the risk
and want to use the Bridge machine's Claude Code subscription login, enable it
explicitly and restart Bridge:
BRIDGE_ALLOW_CLAUDE_OAUTH=1 npx @ccpocket/bridge@latestOnly the exact value 1 enables this behavior. Service setup preserves the
setting when it is present in the setup environment.
# Example: custom port with API key
BRIDGE_PORT=9000 BRIDGE_API_KEY=my-secret npx @ccpocket/bridge@latest
# Example: allow projects outside $HOME
BRIDGE_ALLOWED_DIRS="$HOME,/scratch/$USER" npx @ccpocket/bridge@latest
# Example: expose Bridge through a reverse proxy / ngrok
BRIDGE_PUBLIC_WS_URL=wss://example.ngrok-free.app npx @ccpocket/bridge@latest
# Example: same setting via CLI flag
ccpocket-bridge --public-ws-url wss://example.ngrok-free.app
# Example: disable mDNS advertisement
BRIDGE_DISABLE_MDNS=1 npx @ccpocket/bridge@latest
# or via CLI flag
ccpocket-bridge --no-mdns
# Example: use an assist model provided by a custom Codex gateway
BRIDGE_CODEX_ASSIST_MODEL=gpt-oss:20b-cloud \
BRIDGE_CODEX_ASSIST_REASONING_EFFORT=none \
npx @ccpocket/bridge@latestWhen BRIDGE_PUBLIC_WS_URL is set, the startup deep link and terminal QR code
use that public URL instead of the LAN address. This is useful when the Bridge
is reachable through a reverse proxy, tunnel, or public domain.
Without it, the printed QR code is LAN-oriented by default and typically encodes
something like ws://192.168.x.x:8765.
Claude on Amazon Bedrock
Claude Code and the Claude Agent SDK can run against
Amazon Bedrock instead of the
first-party Anthropic API. Bedrock requests are signed with AWS credentials, so
the Bridge requires neither ANTHROPIC_API_KEY nor the subscription opt-in:
CLAUDE_CODE_USE_BEDROCK=1 \
AWS_REGION=us-west-2 \
npx @ccpocket/bridge@latest
# AWS_PROFILE optionally selects a specific credential profile. AWS_REGION is
# still required because Claude Code does not read it from the AWS profile:
CLAUDE_CODE_USE_BEDROCK=1 AWS_REGION=us-west-2 AWS_PROFILE=my-profile \
npx @ccpocket/bridge@latestAWS credentials remain on the Bridge host and are resolved through the normal
AWS credential provider chain — environment credentials, AWS_PROFILE,
~/.aws/credentials, ~/.aws/config, IAM roles, SSO, and EC2/ECS credentials.
CC Pocket has no AWS credential store of its own. The Bridge parses the Claude
settings file to detect the Bedrock flag and region, but does not access or
persist credential fields, log credential values, or send AWS configuration to
the mobile app. Claude Code resolves credentials on the Bridge host.
The Bridge also recognizes Bedrock when Claude Code's /setup-bedrock wizard
wrote CLAUDE_CODE_USE_BEDROCK into the env block of the Claude Code user
settings file (~/.claude/settings.json, or $CLAUDE_CONFIG_DIR/settings.json).
Only the Bedrock flag and AWS_REGION are accessed from the parsed settings.
Bedrock normally authenticates without Claude OAuth. If Claude Code reports an
OAuth authentication source despite the Bedrock flag, the Bridge still requires
BRIDGE_ALLOW_CLAUDE_OAUTH=1 and rejects the session without that explicit
opt-in.
Model IDs, region resolution, and IAM permissions follow the Claude Code documentation. CC Pocket adds no Bedrock-specific configuration of its own.
Verify the result with the doctor command:
npx @ccpocket/bridge@latest doctorThe Claude Code CLI line then reads
Amazon Bedrock configured; AWS credentials not verified. Doctor reports the
configuration only — it does not call AWS, so it never claims that credentials
work. If AWS_REGION is missing, doctor warns instead of reporting Bedrock as
configured.
Amazon Bedrock with the background service
ccpocket-bridge setup persists only the BRIDGE_* settings listed below, so
make the Bedrock configuration reachable from the service environment:
- macOS launchd: the generated plist starts the Bridge through a login shell
(
zsh -li), soexport CLAUDE_CODE_USE_BEDROCK=1and anyAWS_*variables in~/.zprofile/~/.zshrcare inherited. - Linux systemd: the generated unit starts the Bridge through a login shell
(
bash -lc), so exports in~/.profile/~/.bash_profileare inherited.Environment=lines added to~/.config/systemd/user/ccpocket-bridge.servicealso work, but re-running setup rewrites that file. - Either platform: keeping the configuration in the Claude Code user settings
envblock works too, and survives re-running setup.
Persistent service setup
Register the Bridge as a user-level background service:
npx @ccpocket/bridge@1 setupSetup supports macOS launchd and Linux systemd. It persists the Bridge settings that affect startup:
BRIDGE_PORT/--portBRIDGE_HOST/--hostBRIDGE_API_KEY/--api-keyBRIDGE_ALLOWED_DIRSBRIDGE_FILE_DOWNLOAD_ALLOW_ALL_PATHSBRIDGE_PUBLIC_WS_URL/--public-ws-urlBRIDGE_DISABLE_MDNS/--no-mdnsBRIDGE_ALLOW_CLAUDE_OAUTHBRIDGE_CODEX_APP_SERVER_MODE/--codex-app-server-modeBRIDGE_CODEX_SHARED_APP_SERVER_URL/--codex-shared-app-server-urlBRIDGE_CODEX_ASSIST_MODELBRIDGE_CODEX_ASSIST_REASONING_EFFORT
Example:
BRIDGE_ALLOWED_DIRS="$HOME,/scratch/$USER" \
BRIDGE_API_KEY=my-secret \
npx @ccpocket/bridge@1 setupTo persist the explicit subscription-authentication opt-in:
BRIDGE_ALLOW_CLAUDE_OAUTH=1 npx @ccpocket/bridge@1 setupCustom gateway users can persist assist overrides in the same way:
BRIDGE_CODEX_ASSIST_MODEL=gpt-oss:20b-cloud \
BRIDGE_CODEX_ASSIST_REASONING_EFFORT=none \
npx @ccpocket/bridge@1 setupOn Linux, setup gives standalone Codex installs priority by including
$HOME/.local/bin before npm-managed Node paths in the service PATH.
Experimental: Join a CC Pocket Codex Session from Codex CLI
By default, each Codex session uses a private app-server. To let Codex CLI join the same live thread that CC Pocket started, run the Bridge with shared app-server mode:
BRIDGE_CODEX_APP_SERVER_MODE=managed \
BRIDGE_CODEX_SHARED_APP_SERVER_URL=ws://127.0.0.1:8767 \
npx @ccpocket/bridge@latestThen start or resume a Codex session from CC Pocket. When the session is ready, the session screen can copy a session-specific command like:
codex resume <thread-id> --remote ws://127.0.0.1:8767Run that command in a terminal on the same machine as the Bridge. The
127.0.0.1 address is for the Mac/Linux machine running the Bridge and Codex
CLI, not for the phone.
Modes:
private: default behavior. No Codex CLI co-presence.managed: Bridge starts one local WebSocket Codex app-server and shares it with Codex CLI.external: Bridge connects to an already-running app-server. In this mode,BRIDGE_CODEX_SHARED_APP_SERVER_URLis required.
This is experimental and currently targets Codex CLI co-presence only. Codex App compatibility is not guaranteed and may use a different integration model in the future.
Requirements
- Node.js v20.18.1+
- Claude Code CLI and/or Codex CLI
Current Codex CLI docs recommend the standalone installer for macOS/Linux:
curl -fsSL https://chatgpt.com/codex/install.sh | shHealth Check
Run the built-in doctor command to verify your environment:
npx @ccpocket/bridge@latest doctorIt checks Node.js, Git, CLI providers, macOS permissions (Screen Recording, Keychain), macOS sleep settings, network connectivity, and more.
Architecture
Mobile App ←WebSocket→ Bridge Server ←stdio→ Claude Code CLIThe bridge server spawns and manages Claude Code CLI processes, translating WebSocket messages to/from the CLI's stdio interface. It supports multiple concurrent sessions.
License
This package is MIT licensed as part of CC Pocket. See LICENSE and the repository root LICENSE.
Sharing files by absolute path
Sharing accepts both project-relative and absolute file paths. By default, the
resolved file (including symlink targets) must stay inside the selected project
and BRIDGE_ALLOWED_DIRS.
To explicitly allow sharing files from any location:
BRIDGE_FILE_DOWNLOAD_ALLOW_ALL_PATHS=1 npx @ccpocket/bridge@latestThis opt-in grants connected clients download access to all regular files readable
by the Bridge process. The selected project must still be an allowed, existing
directory. Authentication, download size limits, and capability URLs remain in
place. Uploads and other file access operations retain their existing rules.
Set the variable when running setup to persist it in launchd/systemd, or update
the service environment and restart the Bridge. No mobile app update is needed.
