feat(sessions): drive Codex sessions via Remote Control (issue #103) - #134
Conversation
|
Let me confirm the one thing that determines what the fix looks like — whether codex has an offline daemon-start path that the PR bypassed. That's the decisive test. Here's my analysis. Root cause: the PR uses the wrong codex primitiveCodex exposes two ways to bring up the app-server daemon, and they differ in exactly the dimension that matters here: Command | Needs login + network? | Brings up local socket? -- | -- | -- codex remote-control start (what the PR wires) | Yes — eagerly opens the backend relay connection; aborts if it errors | No, if the connection fails codex app-server daemon start (what it should use) | No — just starts the local daemon | Yes, offlineI proved both, offline, no login, on this box:
So remote-controllability is: start the local daemon (offline-safe) → mark it remote-control-enabled → the relay connection attaches opportunistically once the user logs in. The PR collapsed that into The tell: the wrapper contradicts itselfThe supervisor starts with Why this is worse than a failing test — it's a default-path regression
The fixSwap the primitive in
Secondary, worth a comment but not blocking: even after the fix, Want me to write this up as a PR review comment, or draft the wrapper change against the branch? |
144f7b9 to
f76ec35
Compare
Wire codex into the remoteControl option instead of ignoring it. Unlike
claude's `--remote-control` TUI flag, codex ships a dedicated app-server
daemon (`codex remote-control {start,stop,pair}`) that the Codex apps
drive. `start` detaches, so it can't be a session's foreground command
directly; add a supervisor wrapper that (re)starts the daemon, blocks on
its control socket, and tears it down on session kill/restart so no
detached daemon is leaked.
skipPermissions rides in as `-c approval_policy=never -c
sandbox_mode=danger-full-access` since the subcommand rejects the TUI's
--dangerously-bypass flag. remoteControlName stays claude-only (the codex
daemon names itself from the hostname). Update README, AWS template docs,
and add a NixOS test asserting the wrapper runs and the daemon answers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdKG7KmEiwGB4AtLfddYLT
f76ec35 to
fdaf1f5
Compare
The sessions VM test never saw the codex control socket appear: every
`app-server daemon start` inside the agent unit died with
Error: failed to record pid-managed app-server process <pid> startup
Caused by: failed to invoke ps for pid-managed app server
No such file or directory (os error 2)
The pid-managed daemon backend records and probes its app-server child by
shelling out to a bare `ps`, and the agent unit runs with a curated PATH
that has no procps on this branch. The wrapper then hit its `|| { stop;
exit 1; }` path, so the session fell through to the post-mortem shell
with no daemon and no socket — while the test's own pgrep kept passing
because, run via `su ... -c`, it matched its own invoking shell's command
line rather than the wrapper.
So append procps to the wrapper's own PATH (the feature must not depend
on how the agent PATH is curated), and run the test's pgrep as root so
`-u agent` filters the invoking shell out and the assertion means what it
says.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0191AtHPdSKYEWzR85Q5m4bU
What
Wires codex into the existing
remoteControloption instead of ignoring it. Codex sessions can now be driven from the Codex desktop/mobile apps, closing issue #103.How
Unlike claude's
--remote-controlTUI flag, codex ships a dedicated app-server daemon (codex remote-control {start,stop,pair}) that the Codex apps drive.codex remote-control startdetaches (reparents to init) and returns immediately, so it can't be a session's foreground command — the tmux session would exit at once and the reconcile loop would respawn it every ~2s while the real daemon ran unsupervised.codexRemoteControl): the actual foreground command for a remote-controlled codex session. It clears any leftover daemon, (re)starts a fresh one, then blocks as long as the control socket answers, so the session's life tracks the daemon's. On session kill/restart (SIGHUP/INT/TERM) it tears the daemon down, so no detached daemon is ever leaked.skipPermissionsrides in as-c approval_policy=never -c sandbox_mode=danger-full-access, since theremote-control startsubcommand rejects the TUI's--dangerously-bypass-approvals-and-sandboxflag.remoteControlNamestays claude-only — the codex daemon names itself from the hostname. Pair a running box withcodex remote-control pair.remoteControlon at most one codex session per user.Docs & tests
README.md,aws/template.yamlparameter/output descriptions, and the module option descriptions to reflect that both agents support Remote Control.tests/sessions.nix) asserting the supervisor wrapper runs with the autonomy-coverrides (and not the rejected--dangerously-bypassflag), and that the daemon's control socket answers.🤖 Generated with Claude Code
https://claude.ai/code/session_01EdKG7KmEiwGB4AtLfddYLT