feat(tmux): auto-accept the bypass-permissions prompt on fresh installs#12
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee54f5a6a7
ℹ️ 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".
| if _BYPASS_TITLE_RE.search(text) and _BYPASS_MENU_RE.search(text): | ||
| return PaneState.BYPASS_PROMPT |
There was a problem hiding this comment.
Scope bypass prompt matching to the live modal
Because _capture() includes tmux scrollback (capture-pane ... -S -200), this whole-pane check also sees normal transcript text. If a completed reply quotes the bypass warning title and the 2. Yes, I accept menu line while the pane is otherwise idle, classify_state returns BYPASS_PROMPT instead of READY; the watchdog does not include this new state in _SERVICEABLE, so after the stall threshold it can force-recover a healthy session. Please constrain this detection to the actual modal region or otherwise prefer the live idle/footer state when the anchors only appear in scrollback.
Useful? React with 👍 / 👎.
First run with --dangerously-skip-permissions on a fresh CLAUDE_CONFIG_DIR shows a full-screen "WARNING: Claude Code running in Bypass Permissions mode" with a numbered menu (1. No, exit / 2. Yes, I accept). classify_state knew nothing of it → UNKNOWN → "session not ready in 90s" RuntimeError on every fresh install (the bot recovered only after a human accepted it by hand). Add PaneState.BYPASS_PROMPT and auto-select "2. Yes, I accept" in _ensure_locked (debounced to the transition, like TRUST). Unlike TRUST the safe default sits on "1. No, exit", so we must actively send "2". Detection uses a TRIPLE guard so a model reply can't be mistaken for the modal: the verbatim warning title AND the numbered accept line must both be present, AND the idle "bypass permissions on" footer must be ABSENT. The real modal precedes the normal TUI (no footer yet); a working/idle session always shows the footer. Without the footer guard a reply quoting the warning from scrollback (capture spans -S -200) would classify as BYPASS_PROMPT, which the watchdog does not list as serviceable → it would force-recover a healthy session. Screen text taken verbatim from the Claude Code binary v2.1.179. Tests: classify positive; three negatives (prose mention; a numbered-list reply; the warning quoted in scrollback while the idle footer is present — all stay READY); session accepts via "2" and reaches READY; "2" debounced across repeated captures. Reported by a downstream fork; footer guard added after Codex review.
ee54f5a to
484f474
Compare
Problem (reported by a downstream fork)
On a fresh machine / config dir, the bot launches
claude --dangerously-skip-permissions, which shows a one-time full-screen modal:classify_statedidn't know this screen →UNKNOWN→RuntimeError: session not ready in 90s. The bot couldn't start until a human accepted the modal by hand. Hidden in production only because the modal was already accepted there once.Fix
PaneState.BYPASS_PROMPT, auto-selecting "2. Yes, I accept" in_ensure_locked— debounced to the state transition like the existing TRUST handling. Unlike TRUST, the safe default❯sits on "1. No, exit", so we actively send2(consistent with the survey-dismisssend-keys "0"pattern).Tests
test_classify_bypass_prompt— the real screen classifies.test_classify_bypass_not_triggered_by_proseand…_by_numbered_list_reply— a reply mentioning bypass, or one whose line 2 reads "2. Yes, I accept the terms", stays READY (no false2-injection by the watchdog'scurrent_state()).test_ensure_session_accepts_bypass_prompt/…_does_not_spam_bypass— sends2once and reaches READY; debounced across repeated captures.Closes feedback item #1 (bypass-permissions modal blocks first run).