feat(bridge): vendor smux tmux-bridge as layer-2 agent comms#256
feat(bridge): vendor smux tmux-bridge as layer-2 agent comms#256
Conversation
- scripts/tmux-bridge: byte-identical copy from smux commit 95bf0b6 (github.com/ShawnPana/smux, MIT). 403-line bash CLI for cross-pane comms: list, read, type, keys, message, name, resolve, doctor. - Read-before-act guard via /tmp/tmux-bridge-read-<pane_id> sentinel prevents agents from blindly writing to panes they have not inspected. - Installed at /usr/local/bin/tmux-bridge in container images, sits alongside existing deva-bridge-tmux (layer 1 socat TCP tunnel). - Provenance pinned in scripts/tmux-bridge.VENDORED (upstream commit + SHA256 ed66862b...); upstream MIT license shipped in scripts/THIRD_PARTY_LICENSES/smux-LICENSE. - docs/tmux-bridge-agent-comms.md explains two-layer composition, security model, socket detection order, and read-guard semantics. - CI smoke step builds an ephemeral tmux server inside the image and exercises the full CLI surface (list/name/resolve/read/type) plus a negative assertion on the read-guard. - Zero touches to deva.sh, auth, or docker-entrypoint.sh; purely additive layer-2 adoption.
|
Claude finished @lroolle's task in 2m 35s —— View job Security Audit of tmux-bridge IntegrationPerforming paranoid security audit focusing on container boundaries, auth flows, shell entrypoints, privilege escalation, and permission bypasses. Todo List
Critical Security Findings🚨 BLOCKING ISSUES
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3a2276d240
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| read_guard_path() { | ||
| local pane_id="$1" | ||
| # Sanitize: %66 → _66 | ||
| echo "/tmp/tmux-bridge-read-${pane_id//%/_}" | ||
| } |
There was a problem hiding this comment.
Scope read guard by tmux socket
The read-before-act sentinel is keyed only by pane_id (/tmp/tmux-bridge-read-...), but pane IDs are reused across different tmux servers. Because detect_socket chooses the server per invocation, a read against server A can leave a guard file that lets type/message/keys proceed against server B with the same %N without any read on B. In environments where both local and bridged host tmux servers are reachable, this defeats the safety guarantee and can send commands to an unseen pane.
Useful? React with 👍 / 👎.
| result=$(tmx list-panes -a -F '#{pane_id} #{@name}' 2>/dev/null \ | ||
| | awk -v lbl="$label" '$2 == lbl { print $1; exit }') |
There was a problem hiding this comment.
Parse labels without whitespace splitting
resolve_label formats output as "#{pane_id} #{@name}" and matches with awk '$2 == lbl', so labels containing spaces are split and never match the full label string. Since name currently accepts arbitrary label text, users can create labels (for example, "worker one") that cannot be resolved by resolve, read, type, or message until renamed.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Vendors upstream smux’s tmux-bridge bash CLI into the deva container image as a “layer-2” agent-to-agent communication tool over tmux panes, designed to compose with the existing “layer-1” deva-bridge-tmux host tunnel.
Changes:
- Add vendored
scripts/tmux-bridgeplus provenance + third-party license files. - Install
tmux-bridgeinto the container image and document the two-layer bridge composition and safety model. - Extend CI with a smoke test that exercises the
tmux-bridgeCLI against an ephemeral tmux server inside the built image.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/tmux-bridge | Vendored layer-2 tmux pane communication CLI with socket detection + read-before-act guard. |
| scripts/tmux-bridge.VENDORED | Vendoring provenance (upstream commit + SHA256) and refresh instructions. |
| scripts/THIRD_PARTY_LICENSES/smux-LICENSE | MIT license text for the vendored upstream script. |
| docs/tmux-bridge-agent-comms.md | Explains layer-1/layer-2 composition, security model, socket detection, and guard semantics. |
| Dockerfile | Copies tmux-bridge into /usr/local/bin and marks it executable. |
| .github/workflows/ci.yml | Adds a smoke step validating installed CLI surface + guard behavior. |
| CHANGELOG.md | Records the addition under [Unreleased]. |
| DEV-LOGS.md | Adds a devlog entry describing motivation, contents, and outcome. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| What it is: | ||
| - tmux-bridge is a 403-line bash CLI for cross-pane communication between | ||
| AI agents running in tmux. Read/type/keys/label/envelope primitives. |
| read_guard_path() { | ||
| local pane_id="$1" | ||
| # Sanitize: %66 → _66 | ||
| echo "/tmp/tmux-bridge-read-${pane_id//%/_}" |
| socat TCP tunnel via host.docker.internal:41555 | ||
|
|
||
| Layer 2 tmux-bridge semantic CLI | ||
| (scripts/tmux-bridge) read/type/keys/label/envelope |
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - `scripts/tmux-bridge` vendored from upstream smux (commit 95bf0b6, MIT) for layer-2 agent-to-agent communication over tmux panes: read/type/keys/label/envelope/doctor |
| - Reference issue numbers in the format `#<issue-number>` for easy linking. | ||
|
|
||
| # [2026-04-13] Dev Log: adopt smux tmux-bridge as layer-2 agent comms | ||
| - Why: deva-v2 proposal left the agent-to-agent transport CLI as an open question; smux (github.com/ShawnPana/smux) shipped exactly the shape we sketched (read/type/keys/label/envelope) in 403 lines of bash, MIT-licensed. Reinventing it would be waste. The existing `deva-bridge-tmux` (socat TCP) is layer 1 (kernel boundary); `tmux-bridge` is layer 2 (semantic). They compose cleanly. |
What
Vendor upstream
smuxtmux-bridge(github.com/ShawnPana/smux, MIT) as thelayer-2 agent-to-agent communication CLI inside deva container images. Sits
alongside the existing
deva-bridge-tmux(layer 1, socat TCP tunnel to hosttmux server). Zero touches to
deva.sh, auth wiring, ordocker-entrypoint.sh.Why
The deva-v2 proposal (docs/devlog/260401-deva-v2-proposal.org) left the
agent-to-agent transport CLI as an open design question. Upstream smux shipped
almost exactly the primitives we sketched (list/read/type/keys/label + text
envelopes) in 403 lines of bash, MIT-licensed. Reinventing it would be waste.
Adopting it unblocks experiments on top (layer 3: coordinator/router,
scratchpad, state detection) without us having to own the transport layer.
The piece smux does not cover - the container-to-host kernel boundary - is
already solved by our existing
deva-bridge-tmux. The two layers composecleanly: once the socat tunnel is up,
TMUX_BRIDGE_SOCKET=/tmp/host-tmux.socklets
tmux-bridgedrive panes on the host tmux server from inside thecontainer.
What is in the commit
95bf0b639e64a4c67b4f007b1bedc26395344e01, SHA256 ed66862b...)
security model, socket detection priority, read-before-act guard semantics,
quick start, provenance
the existing smoke job. Builds an ephemeral tmux server inside the image,
exercises list/name/resolve/read/type, and asserts the read-guard blocks
a second type without re-reading.
Test plan
Verified locally against real tmux 3.6a (same version container ships):
shellcheck -S error scripts/tmux-bridge scripts/deva-bridge-tmux scripts/deva-bridge-tmux-host-> clean (matches CI severity)tmux-bridge version->tmux-bridge 2.0.0tmux-bridge --help-> contains "cross-pane communication"tmux-bridge idoutside tmux -> errors cleanlytmux-bridge listagainst ephemeral tmux server -> showssmoke:0panetmux-bridge name <pane> smoke-worker+resolve smoke-worker-> round-trip workstmux-bridge read <target> 5-> succeeds, sets guardtmux-bridge type smoke-worker "echo hi"after read -> succeedstmux-bridge type smoke-worker "echo twice"without re-read -> fails with "must read the pane before interacting" (guard works)Security
Both layers are privileged host bridges. If the host tmux bridge is running
and an agent in the container drives
tmux-bridge, it cansend-keys,run-shell, and read scrollback on the host tmux server - effectively asandbox escape, which is the deliberate tradeoff for trusted dev workflows.
Documented loudly in
docs/tmux-bridge-agent-comms.mdand unchanged from theexisting
deva-bridge-tmuxtrust model.Non-goals
scratchpad) is tracked as an open design in
docs/devlog/260401-deva-v2-proposal.organd explicitly out of scope here.This PR is additive transport only.