Skip to content

Commit 29d4473

Browse files
authored
Merge pull request #413 from thevibeworks/feat/deva-tmux-412
feat(tmux): deva-tmux — tmux as a built-in module, both transports
2 parents ee997b5 + 21a5431 commit 29d4473

11 files changed

Lines changed: 966 additions & 174 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.claude/
55
*.bak
66

7+
/.cctrace
78
### Node ###
89
# Logs
910
logs

CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- `deva-tmux` (#412): tmux interaction is now a built-in module instead of
12+
loose scripts. One in-container CLI, two transports — `ssh` (default:
13+
authenticated, reboot-durable, runs the host's tmux client so there is
14+
no client/server protocol coupling) and `socat` (fallback: the old
15+
unauthenticated TCP daemon, kept for hosts without sshd, loud warning
16+
every start). Both land the host server on `/tmp/host-tmux.sock`, so
17+
`tmux-bridge` (Layer 2) and `htmux` muscle memory work unchanged.
18+
Container->host stays opt-in: `deva.sh --host-tmux` mounts `~/.ssh`
19+
read-only and passes `DEVA_HOST_USER`; without it the baked CLI is
20+
inert. Host-side lifecycle moved where it belongs: `deva.sh tmux setup`
21+
authorizes your key by writing your own `authorized_keys` (killing the
22+
in-container docker-mount write from the #406 draft), `deva.sh tmux
23+
host-daemon start|stop|status` manages the socat fallback, `deva.sh
24+
tmux doctor` diagnoses the host side. `deva-bridge-tmux` is now a compat
25+
shim. Verified live against a real host: both transports, bridge
26+
lifecycle, native client + Layer 2 through the forwarded socket.
27+
1028
## [0.15.0] - 2026-07-14
1129

1230
### Added
@@ -59,7 +77,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5977
deva validates and reports the captured credentials (subscription type,
6078
expiry), or removes the placeholder on abort. Combine with `-Q --rm`
6179
for a clean one-shot provisioning flow.
62-
6380
## [0.14.0] - 2026-07-10
6481

6582
### Added

DEV-LOGS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
- Minimal markdown markers, no unnecessary formatting, minimal emojis.
1414
- Reference issue numbers in the format `#<issue-number>` for easy linking.
1515

16+
# [2026-07-10] Dev Log: deva-tmux — tmux as a built-in module, both transports #412
17+
- Why: tmux interaction was four loose scripts with zero deva.sh integration; #406 built the right transport (ssh) but deleted the socat fallback and stayed a loose script. Direction split matters: host->container (deva.sh shell) and agent<->agent (tmux-bridge) keep the sandbox; container->host breaks it and must be opt-in.
18+
- What:
19+
- scripts/deva-tmux (new, baked into both images): ls/attach/tmux/bridge/setup/doctor with transport backends — ssh default (authenticated, launchd-durable, host-side tmux client so zero protocol coupling), socat fallback (unauthenticated TCP, warns loudly). DEVA_TMUX_TRANSPORT=auto|ssh|socat; auto probes ssh then socat. Both transports land on /tmp/host-tmux.sock -> tmux-bridge Layer 2 unchanged
20+
- inert-without-provisioning is the security property: baked binary + no key + no daemon = no host reach. deva.sh --host-tmux is the opt-in: mounts ~/.ssh ro (dedup-safe, user -v wins), passes DEVA_HOST_USER, launcher's deva-tmux copy overrides the image copy in repo mode (skew insurance)
21+
- deva.sh tmux command group (host side): setup writes your OWN authorized_keys — the #406 draft did this from inside the container via a docker host-mount, which is exactly the host-reach pattern the tool exists to gate; moving it host-side dissolved the scariest code. host-daemon start|stop|status wraps the socat daemon (inline fallback when scripts/ absent). doctor for the host view
22+
- deva-bridge-tmux -> compat shim (old flags -> env -> deva-tmux bridge start --transport socat --foreground); deva-bridge-tmux-host unchanged; tmux-bridge stays vendored byte-for-byte (read-guard TTL idea goes upstream, not a fork)
23+
- found+fixed in live test: backgrounded ssh -N -L inherited the caller's stdout, so `deva-tmux bridge start | tail` hung forever waiting for EOF — the #406 draft had the same latent bug. Bridge children now detach stdio to a state-dir log
24+
- Result: verified live against a real macOS host from inside the dev container — doctor sees both transports, ssh bridge + socat bridge both land the host server on the socket, native tmux client and tmux-bridge list work through it, lifecycle idempotent, socket cleaned on stop; mount-shape suite asserts off/on/dedup provisioning shapes; shellcheck severity=error clean
25+
1626
# [2026-07-10] Dev Log: repo surface burnish #409
1727
- Why: product ships four agents but half the storefront said three; agents visiting the repo had no llms.txt; nightly 2026-07-09 failed on a transient ubuntu mirror sync and partially published (base pushed, rust did not — nightly/nightly-rust tags diverged a day)
1828
- What:

Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,17 @@ RUN --mount=type=cache,target=/home/deva/.npm,uid=${DEVA_UID},gid=${DEVA_GID},sh
240240
USER root
241241

242242
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
243+
# deva-tmux: container->host tmux CLI (ssh + socat transports). Baked but
244+
# inert without host-side provisioning (deva.sh --host-tmux / tmux setup).
245+
COPY scripts/deva-tmux /usr/local/bin/deva-tmux
246+
# deva-bridge-tmux: compat shim -> deva-tmux bridge --transport socat
243247
COPY scripts/deva-bridge-tmux /usr/local/bin/deva-bridge-tmux
244248
# tmux-bridge: vendored from smux (layer-2 agent comms CLI over tmux panes)
245249
# See scripts/tmux-bridge.VENDORED for upstream commit and SHA256 pin.
246250
COPY scripts/tmux-bridge /usr/local/bin/tmux-bridge
247251

248252
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh && \
253+
chmod 755 /usr/local/bin/deva-tmux && \
249254
chmod 755 /usr/local/bin/deva-bridge-tmux && \
250255
chmod 755 /usr/local/bin/tmux-bridge && \
251256
chmod -R 755 /usr/local/bin/scripts || true

Dockerfile.rust

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,14 @@ RUN --mount=type=cache,target=/home/deva/.npm,uid=${DEVA_UID},gid=${DEVA_GID},sh
157157
USER root
158158

159159
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
160+
# deva-tmux: container->host tmux CLI (ssh + socat transports). Baked but
161+
# inert without host-side provisioning (deva.sh --host-tmux / tmux setup).
162+
COPY scripts/deva-tmux /usr/local/bin/deva-tmux
163+
# deva-bridge-tmux: compat shim -> deva-tmux bridge --transport socat
160164
COPY scripts/deva-bridge-tmux /usr/local/bin/deva-bridge-tmux
161165

162166
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh && \
167+
chmod 755 /usr/local/bin/deva-tmux && \
163168
chmod 755 /usr/local/bin/deva-bridge-tmux && \
164169
chmod -R 755 /usr/local/bin/scripts || true
165170

0 commit comments

Comments
 (0)