Trust cmux's own Codex hooks so Codex stops asking to review them

Merged
AU
23d ago
+206-28

Summary

Starting codex in a cmux-tui terminal (every Cloud VM, and cmux-tui on a Mac) showed "Hooks need review: 11 hooks are new or changed". /hooks listed each event as Installed 2, Active 1, Review 1. Only the untrusted copy carries the terminal route, so it's the one the shared app-server needs, and it didn't run until the user clicked Trust. After this change, Codex trusts every hook cmux writes or injects, and starts without asking.

Cause. The cmux-tui codex wrapper adds a per-launch copy of each hook through -c, and the ssh-tmux helper (Resources/bin/cmux-tmux-agent.py) does the same. Both passed that copy's trust as -c hooks.state."/<session-flags>/config.toml:stop:0:0".trusted_hash=.... They also passed enabled=false for the persistent hooks.json copies. Codex splits a -c key on every ., even inside TOML quotes (codex-rs/config/src/overrides.rs apply_toml_override). Every one of these keys contains a dot (config.toml, hooks.json), so none of those settings ever applied. As a result, the persistent copy stayed enabled and trusted while the per-launch copy was untrusted. Both now pass the whole state as one inline table, -c hooks.state={"<key>"={trusted_hash="..."}, ...}. Codex merges that table with the trust already in config.toml, and user trust is untouched.

Two smaller ways the persistent producers could leave a cmux hook untrusted are fixed too:

  • cmux-tui reordered a shared hooks.json on reinstall. A reinstall removed cmux-tui's group and appended a new one at the end. When the cmux app's hooks came after it, they shifted up one group, away from their trusted key. cmux-tui's new trust entry then overwrote the app's key. cmux-tui now puts its group back in the slot it came from, as the app CLI already does.
  • The cmux CLI resolved symlinks in the trust key. It keyed trust by the fully resolved hooks.json path. Codex resolves an explicit CODEX_HOME but uses $HOME/.codex verbatim, so a symlinked home left every app hook untrusted. The CLI now builds the key the same way Codex does, and it still cleans up old resolved-path entries that carry cmux's own hashes.

Both producers stay installed. The app's hooks only act inside cmux app terminals, and cmux-tui's only inside cmux-tui terminals or tmux. Neither trusts a hook it didn't write. The Cloud boot rewrite of ~/.codex/config.toml (agent-config.sh) already copies the existing file, including [hooks.state], so it needs no change.

The first commit is a one-line rustfmt fix to session_journal.rs that's already on main. Without it, hosted cmux-tui verification stops at cargo fmt before any test runs.

Testing

Tests were committed red before the fix:

  • cmux-tui/crates/cmux-tui/tests/codex_wrapper.rs: the -c parser now applies overrides the way Codex does (split on every ., last segment replaces). codex_wrapper_scopes_trust_and_suppresses_only_installed_cmux_hooks then requires the session-flag trust and enabled=false entries to land at their real keys.
  • agent_hook_install.rs codex_reinstall_keeps_a_later_producers_hook_and_trust_in_place: installs cmux-tui, adds an app-style Stop hook after it with its trust entry, reinstalls cmux-tui, and asserts both hooks keep their positions and trust.
  • scripts/tests/test_remote_tmux_agent_helper.py: requires a single hooks.state override containing every session-flag key.
  • cmuxTests/CLIGenericHookPersistenceTests.swift testCodexHookTrustKeysUseTheDefaultCodexHomeVerbatim: installs through a symlinked $HOME and expects the unresolved key.

Results:

  • Hosted cmux-tui --filter codex_: test commit run 38524404119 (expected red) and fix run 38524560666 are still running; cargo fmt passes on both. Results will be added here.
  • python3 -m unittest test_remote_tmux_agent_helper: red before, 10/10 after. python3 scripts/verify-local.py: 17/17.
  • The Swift test runs in the app CI on this PR; I didn't build the app locally.

Checked against the real Codex 0.162.1 release (codex app-server โ†’ hooks/list, temp CODEX_HOME):

  • cmux-tui's persistent install plus the old wrapper flags reproduced the report: 11 hooks.json copies trusted and enabled, 11 /<session-flags> copies untrusted.
  • The same layout with the inline hooks.state value: hooks.json copies trusted and disabled, session-flag copies trusted and enabled. A user hook's trust from config.toml was unchanged.
  • The fixed tmux helper's actual argv: all 7 session-flag hooks trusted, no warnings.
  • $HOME/.codex through a symlink is keyed by the unresolved path.

Changelog

Fixed: Codex no longer asks to review cmux's own hooks when it starts in a cmux-tui terminal or a Cloud machine

Proof

No UI change; the hooks/list results above are the behavior check.

Checklist

  • Behavior changes have added or updated tests, or Testing says why not
  • Reviewed with a subagent before merge (cmux-review), and all bot and human review comments resolved

๐Ÿค– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Stops Codex from asking to review cmux's own hooks when it starts in a cmux-tui terminal or a Cloud VM.

  • The -c trust overrides Codex splits on every dot, even inside quotes, so the per-launch hook copies were left untrusted; trust and enabled=false now go in a single hooks.state inline table, which Codex merges with the persistent trust.
  • cmux-tui reinstalls now reinsert its hook group in its original slot in a shared hooks.json, keeping hooks another producer added later on their trusted keys.
  • The cmux CLI now keys trust by $HOME/.codex verbatim instead of the resolved path, fixing symlinked homes; user trust in config.toml is untouched.
  • Includes a one-line rustfmt fix to session_journal.rs that was blocking hosted verification.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Codex hook trust handling, including when configuration paths use environment overrides or symlinked home directories.
    • Reinstalling cmux hooks now better preserves the placement of hooks added by other tools and retains their trust settings.
    • Codex sessions now consistently apply hook trust settings when launched.