Let a project turn a globally-enabled Claude Code setting back off

The six boolean settings were plain `bool`s merged with
`if p.x { true } else { g.x }`, so a project could only ever add to the
global set. There was no project value that produced `false` — turning a
switch off at project level simply fell through to the global value and
the control did nothing.

Widen them to `Option<bool>`. `None` means "not set at this level":
inherit the global on a project, leave Claude Code's own default alone
globally. `Some(false)` is a deliberate off and wins outright.

The fingerprint now formats with `{:?}` rather than `{}` — `None` and
`Some(false)` mean different things, and conflating them would leave the
container un-recreated when a project switched from inherit to off.

The project editor grows a third "Global" state per switch; the global
editor has nothing to inherit from, so it stays a plain toggle and keeps
collapsing to null at the default. Its three existing tests passed
unchanged and caught a first attempt that rendered unset as off, which
would have told every user their session recap was disabled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GBq2rGum6GX7xXgsas1fDc
This commit is contained in:
2026-08-23 09:05:39 -07:00
co-authored by Claude Opus 5
parent bb41275cea
commit 0a022dfcf0
6 changed files with 268 additions and 73 deletions
+12 -6
View File
@@ -133,22 +133,28 @@ export interface OpenAiCompatibleConfig {
haiku_model_id: string | null;
}
/**
* Every field is three-state. `null` means "not set at this level": on a
* project that is "inherit the global value", and on the global settings it is
* "leave Claude Code's own default alone". `false` is a deliberate off, which
* is what lets a project turn a globally-enabled setting back off.
*/
export interface ClaudeCodeSettings {
/** `null` = let Claude Code choose the renderer; `"default"` = classic, `"fullscreen"` = alt-screen. */
tui_mode: string | null;
/** `null` = unset, else `"low" | "medium" | "high" | "xhigh"`. Written as `effortLevel`. */
effort: string | null;
auto_scroll_disabled: boolean;
auto_scroll_disabled: boolean | null;
/** Written as `viewMode: "focus"`. */
focus_mode: boolean;
show_thinking_summaries: boolean;
focus_mode: boolean | null;
show_thinking_summaries: boolean | null;
/**
* Turns the session recap **off**. Held in the disabled sense because Claude
* Code's recap is on by default — see the Rust doc on `ClaudeCodeSettings`.
*/
session_recap_disabled: boolean;
env_scrub: boolean;
prompt_caching_1h: boolean;
session_recap_disabled: boolean | null;
env_scrub: boolean | null;
prompt_caching_1h: boolean | null;
}
export interface ContainerInfo {