Push sessions
A push session receives new bus mail while idle. It needs the bus-push entry from client setup and must be started with a name and the development channels flag. scripts/claude-push.sh does both.
Start one
scripts/claude-push.sh laptop-api
Without a name it uses <short-host>-<repo>:
scripts/claude-push.sh
# claude-push: session name laptop-api
Ask the session "what bus session are you?". It should answer with the name.
Extra Claude Code arguments
Everything after the name goes to claude. The first argument is the name unless it starts with -:
scripts/claude-push.sh laptop-api --resume # name laptop-api, resume picker
scripts/claude-push.sh --continue # default name, continue last conversation
scripts/claude-push.sh server-ci --model opus # name server-ci
The script puts --allowedTools mcp__bus and the channels flag last, because both take a variable number of values.
What the script sets
SESSION_BUS_NAME=<name>for thisclaudeprocess only.--dangerously-load-development-channels server:bus-push.--permission-mode default. A bus message is a peer request, not your authorization. Do not combine push with skip-permissions.--allowedTools mcp__bus: bus tool calls do not prompt; other tools still do.- Clears
DISABLE_TELEMETRYandCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICfor this process (see below).
Set SESSION_BUS_NAME only on launches with the channels flag. A named shim in a session without the flag still moves its cursor while Claude Code drops the pushes. The mail stays unacked and inbox still returns it.
Availability
Channels are a Claude Code research preview.
- On Claude Code 2.1.312, the channels flag is ignored, with the message "Channels are not currently available", while both
DISABLE_TELEMETRYandCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICare set (any value, including0). Clearing one alone is not enough. Verified on 2026-10-28. claude-push.shclears both for its own process, in the environment and through--settings. Your settings files are not changed. That session sends telemetry. If you do not want that, remove those lines from the script; push then stays off and pull still works.- For org-managed accounts,
channelsEnabledmust not be turned off by policy. Look for a startup warning.
What arrives
A pushed message shows as ← bus-push: <body> with meta:
{ "msg_id": "42", "to": "laptop-api", "from": "server-ci", "from_principal": "me", "thread_id": "" }
The model is told to ack with session=<meta.to> and ids=[<msg_id>] after handling it.
Only messages from allowlisted principals are pushed. The default is the shim's own principal. To accept others, add --allow-from to the bus-push entry's args, for example ["/path/to/dist/cli.js","channel","--allow-from","me,teammate"].
Ending a session
When claude exits cleanly, the shim calls unregister for its name (up to 3 s). If the session still has unacked mail, the bus refuses and keeps both the session and the mail; the shim keeps its cursor file. The next claude-push.sh with the same name picks up from there.
Per-launch fallback
If a stdio server ever does not inherit claude's environment, write a per-launch config with a distinct server name and --session in args, then:
claude --mcp-config ./bus-push-laptop-api.json --dangerously-load-development-channels server:bus-push-laptop-api
This was not needed in testing (stdio servers do inherit the environment). Whether the channels flag resolves a server defined only in --mcp-config is untested.