fix: 0.35.5rc8 — adopt Claude Code's native auto permission mode (#741), fix the stale/unenforced allowlist (#742), persist private-chat topic sessions (#734) - #744
Conversation
), fix the stale/unenforced allowlist (#742), persist private-chat topic sessions (#734) Claude Code 2.1.228 ships its own `auto` permission mode, which Untether's same-named sugar shadowed: `build_args` rewrote `auto` to `--permission-mode plan` and rubber-stamped the ExitPlanMode control request, so the CLI's classifier-gated mode was unreachable. Auto mode becomes the CLI default for new Pro/Max/Team sessions on 2026-08-14. - #741 rename the sugar to `plan-auto`; pass every genuine CLI mode through verbatim. Chat prefs migrate on read (Claude-only); TOML keeps its value and gets a one-shot WARN. `/config → Permission mode` gains a `plan-auto` button. - #742 re-derive the allowlist against CLI 2.1.228 (+`manual`, +`dontAsk`; `default` retained — the CLI still accepts it, contrary to the issue) and apply it to `[engines.claude]`, which was read raw. Adds a drift test that re-derives the set from the installed binary. - #734 private-chat topics key on `(chat_id, thread_id)` instead of being dropped, so each topic resumes independently. Verified against CLI 2.1.228 with Untether's exact argv: AskUserQuestion still raises a can_use_tool control_request under `auto`, so Telegram interactivity survives the adoption. 3222 tests pass, ruff clean, coverage 83.5%. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Caught by integration testing on @untether_dev_bot: the first attempt migrated stored `auto` -> `plan-auto` on every read. That is right for a legacy value but wrong the moment `auto` becomes a value the user can choose — pressing Auto in /config stored `auto`, the next read rewrote it to `plan-auto`, and the run spawned `--permission-mode plan`. The new mode was unreachable through its own UI. The rewrite now runs once per state file, guarded by a persisted `permission_mode_migrated` flag. It is a field rather than a STATE_VERSION bump because JsonStateStore discards state on a version mismatch, so bumping would wipe every chat's prefs to migrate one value. 4 new tests covering the legacy rewrite, the marker, and the regression guard that a deliberately chosen `auto` survives a reload. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Three advisories published after dev's last CI run; pip-audit failed on this batch's PR. aiohttp is a direct dependency (webhook server), so the bump ships here rather than as a follow-up. Full suite green on the new pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…e /config page (#741) Guides: plan-mode.md gains the four-mode table and a renamed-in-v0.35.5 note; the per-cron override sections in plan-mode / schedule-tasks / webhooks-and-cron gain a semantics-change warning, and their valid-value lists were stale anyway (missing manual/dontAsk/plan-auto). README, glossary, commands reference, triggers reference, interactive-control tutorial, inline-settings and FAQ Q6 brought into agreement. /config: the Claude section is retitled "Permission mode" on both the home page and the sub-page — with Claude Code's own auto mode in the list, "Plan mode" no longer describes what the setting controls. Verified live on @untether_dev_bot. Audited and found to need no change: the onboarding wizard and shipped config templates write no permission_mode (fresh installs unaffected), and /model + /reasoning only pass the stored value through. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude Code 2.1.228 ships its own
autopermission mode, and Untether's same-named sugar shadowed it. Auto mode becomes the CLI default for new Pro/Max/Team sessions on 2026-08-14, two days after this was found.build_argsrewroteauto→--permission-mode planand armed an ExitPlanMode rubber stamp, so the CLI's classifier-gatedautowas unreachableplan-auto; pass every genuine CLI mode through verbatim. One-shot chat-pref migration; TOML keeps its value + one-shot WARN./config → Permission modegains a Plan-auto button/proc/<pid>/cmdline:--permission-mode auto --permission-prompt-tool stdio.plan-autostill spawnsplanand rubber-stamps ExitPlanMode[engines.claude]was read raw, so a typo died at subprocess spawnmanual, +dontAsk); apply the same allowlist inbuild_runner(); add a drift test that re-derives it from the installed binarypermission_mode = "palan"→ConfigErrorat load naming key/value/path;"auto"loads and warns once_chat_session_key()returnedNonefor anythread_id, but private-chat topics carry one andTopicStateStoredeclines them — no resume token was ever written(chat_id, thread_id); main thread keeps(chat_id, None); group/supergroup topics still defer toTopicStateStoreThe load-bearing question
#741 asked whether upstream
autoswallows the control channel and costs Untether its interactivity. It does not. Probed against CLI 2.1.228 using Untether's exact argv, then confirmed on@untether_dev_bot:AskUserQuestionstill raises acan_use_toolcontrol_request underauto, renders option buttons, and round-trips the answer. Classifier fallback after repeated blocks routes through--permission-prompt-tool stdioas an ordinary Telegram approval.diff_previewis inert underauto— but it has been inert underacceptEditssince it shipped. That is a pre-existing property of any non-prompting mode, not a new regression, and it is documented rather than silently accepted.autodeliberately does not arm the ExitPlanMode rubber stamp: that mode has no plan gate, and arming it would recreate the blanket downstream bypass tracked by #383 somewhere it means far more.Two corrections to the issues as filed
permission_modeallowlist is stale (CLI 2.1.228) and only enforced for crons, not[engines.claude]#742 claimeddefaultis rejected by the CLI. It is not —claude --helplistsmanualin its place, but a spawn probe of--permission-mode defaultexits 0, and the docs confirmmanualis a documented alias fordefault(CLI ≥ 2.1.200).defaultstays in the allowlist; the drift test excludes it from the comparison rather than dropping it.auto→plan-autoon every read is right for a legacy value but wrong the momentautois a value the user can choose: pressing Auto in/configstoredauto, the next read rewrote it, and the run spawned--permission-mode plan. The rewrite is now one-shot, guarded by a persistedpermission_mode_migratedflag — a field rather than aSTATE_VERSIONbump, becauseJsonStateStorediscards state on a version mismatch.Breaking
permission_mode = "auto"inuntether.tomlchanges meaning: it now selects the CLI's classifier-gated auto mode instead of plan-mode-plus-rubber-stamp. Unattended crons that set it lose the plan ceremony and gain per-action classification with a hard exfiltration deny. Set"plan-auto"to keep the old behaviour; the runner logsclaude.permission_mode.auto_semantics_changedonce when it sees the ambiguous value.Caveat
#734's private-chat-topic path could not be driven live — the dev bot has no private-chat-topic binding and the feature can't be created through the test tooling. It is covered by 8 unit tests, and the group/DM paths it touches were verified live.
Tests
3226 passing (+65), ruff clean, coverage 83.5%. New
tests/test_claude_permission_modes.py(46) covers mode mapping, allowlist contents, cron↔engine-config accept/reject parity, the one-shot migration and its regression guard, and a drift test that re-derives the mode set from the installed CLI so this rots loudly. Attestation marker written for0.35.5rc8, SHA-bound to815eb90.🤖 Generated with Claude Code