~/.claude/settings.json is generated by modules/settings.nix from
programs.claude.* options. Two layers exist:
-
Typed sub-options (
modules/options-settings.nix,modules/options-runtime.nix) — validated, documented, discoverable vianix repl/nix eval --json. Prefer these when a key you need is listed below. -
Freeform passthrough — any other key set on
programs.claude.settingsflows intosettings.jsonverbatim:programs.claude.settings.someUndocumentedKey = "value";
This is how you reach any key from the full settings.json reference that doesn't have a typed option yet.
These ship with a non-null default because the upstream default is
either surprising or actively unhelpful:
| Option | Default | Why it's set |
|---|---|---|
programs.claude.settings.askUserQuestionTimeout |
"5m" |
Real runtime default is "never" despite the docs — blocks a session indefinitely. |
programs.claude.settings.useAutoModeDuringPlan |
true |
Runs plan mode through the cheaper/faster auto-mode classifier, not its own gating. |
programs.claude.settings.autoCompactThresholdPercent |
60 |
Compact well before the hard limit — see below for the full rationale and override. |
autoCompactThresholdPercent isn't a real settings.json key — Claude Code has
none for this (context windows are trending toward 1M tokens, and Claude's own
default of ~90%+ used leaves too little headroom for the summarization pass
itself at that scale). It's emitted as the CLAUDE_AUTOCOMPACT_PCT_OVERRIDE
env var instead (see "Builder-merged defaults" below). Set it to null to
omit and fall back to Claude's own default, or set
programs.claude.settings.env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE directly to
override just the env var.
programs.claude.defaultMode ("auto", in modules/core.nix) and
programs.claude.autoUpdatesChannel ("latest", in
modules/options-runtime.nix) are also non-default-upstream but predate this
document — see those files for rationale.
Declared in modules/options-settings.nix, all default to null — meaning
"omit the key, use Claude's own upstream default" — until you set one:
| Option | Type | Upstream default when unset |
|---|---|---|
autoCompactEnabled |
bool | true |
outputStyle |
str | unset |
includeCoAuthoredBy |
bool | true |
enableAllProjectMcpServers |
bool | false |
editorMode |
"normal" | "vim" |
"normal" |
includeGitInstructions |
bool | true |
fileCheckpointingEnabled |
bool | true |
plansDirectory |
str | ~/.claude/plans |
language |
str | unset (follows conversation) |
fallbackModel |
list of str | unset (no fallback) |
Two values are merged by modules/settings.nix rather than exposed as plain
options, because a Nix option default would be replaced wholesale the
moment a caller sets the option — these need to always apply while still
letting callers add to or override individual entries:
permissions.additionalDirectoriesalways includes~/.claude/and/tmp/, concatenated withprograms.claude.settings.additionalDirectories(deduplicated).envalways includesMCP_TIMEOUT,MCP_TOOL_TIMEOUT,ENABLE_TOOL_SEARCH,CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS, andCLAUDE_AUTOCOMPACT_PCT_OVERRIDE(derived fromautoCompactThresholdPercentabove), merged underprograms.claude.settings.env— set any of these keys yourself to override just that one.hooksregisters each configuredprograms.claude.hooks.<event>(preToolUse,sessionStart, etc. — seemodules/options-events.nix) under its Claude Code event name (PreToolUse,SessionStart, ...), pointing at the scriptmodules/hooks.nixwrites to~/.claude/hooks/<event>.sh. Writing the script alone does nothing — Claude Code only runs hooks registered insettings.json, and has no directory-convention auto-discovery — so this registration is required, not cosmetic. Merged underprograms.claude.settings.hooks, so a caller-supplied entry for the same event wins.
programs.claude.validateSettings.enable (default false) runs a warn-only
JSON Schema check of the deployed settings.json against
programs.claude.settings.schemaUrl after every activation. It never blocks
home-manager switch — failures are printed to stderr as a warning. Off by
default because it shells out to nix shell nixpkgs#check-jsonschema and
fetches the schema URL, adding network dependency to activation.