Skip to content

Settings reference

Every field in settings.json. For file locations, layer-merge rules and common configuration see Configuration / settings & environment; this page is the full table.

Every field is optional (aside from built-in defaults for permissions / costWarnCNY / maxToolResultChars) — leaving one out means the feature is off.

Model & provider

FieldTypeNotes
modelstringStartup model. Unset = built-in default
availableModelsstring[]Allowlist for model. If set, model must be in it or it's ignored and falls back to the default tier. Unset = everything allowed; [] = default tier only
provider'deepseek' | 'glm' | 'kimi' | 'custom'Active provider, default deepseek
providersobjectPer-provider apiKey overrides plus the custom backend definition
apiKeystringDeepSeek key (written by the first-run wizard). Environment variables win
baseURLstringCustom API base URL
languagestringLock the reply language by injecting "always answer in X" into the system prompt

Context & compaction

FieldTypeNotes
compactTokensnumberAuto-compaction threshold (triggers when the previous request's prompt_tokens exceeds it). Unset = derived from the model
precomputeCompactionEnabledbooleanPrecomputed compaction, on by default; only === false turns it off
maxToolResultCharsnumberCharacter cap on tool results before truncation. Default 100000

Derived threshold = context window − output reserve (16k) − autocompact buffer (13k). The window can be overridden with DEEPCODE_MAX_CONTEXT_TOKENS.

Headless only

FieldTypeNotes
headlessThinkingbooleanWhether headless enables thinking. Default false
headlessMaxTurnsnumberTool-loop step cap for headless. Unset = 80

Why the headless prefix

In the TUI, thinking is session state (/think toggles it, stored in session meta). Headless has no session state to inherit, so it gets its own switch. It's a switch rather than a changed default because thinking costs tokens and turns — whether it pays off has to be A/B tested, and changing the default leaves no clean baseline to compare against. Same reasoning for the step cap, which only headless consumes (the TUI still uses 80); the prefix is there so nobody mistakes it for a global knob.

Permissions

FieldTypeNotes
permissions.allowstring[]Allow rules
permissions.denystring[]Deny rules, highest priority
permissions.askstring[]Force-prompt rules
permissions.defaultModePermissionModeStartup permission mode
disableAutoModebooleanDisable auto mode. Default false
autoModeModelstringOverride model for the auto classifier. Default: the provider's fast tier
autoModeThinkingbooleanEnable thinking for the classifier. Default false

Ecosystem & extensions

FieldTypeNotes
hooksobjectHook lifecycle configuration
mcpServersRecord<string, ...>MCP servers (stdio); key = server name
skillsobjectSkill discovery scope + listing budget. Default: scan everything, allow everything
skillOverridesobjectPer-skill on/off overrides
webSearchobjectWebSearch dual-source (bocha / tavily) configuration
worktreeobjectgit worktree config (symlinkDirectories / sparsePaths)
memoryobjectMemory subsystem configuration

Security

FieldTypeNotes
allowedHttpHookUrlsstring[]Hook URL allowlist (SSRF). Unset = unrestricted, [] = block all, non-empty = must match a glob
httpHookAllowedEnvVarsstring[]Global allowlist for env interpolation in http hook headers; intersected with each hook's own allowedEnvVars

SSRF protection only covers hooks

The two-layer SSRF guard applies to hook HTTP requests only. WebSearch and WebFetch take a different path.

Interface

FieldTypeNotes
themestringTheme name. Unset = runtime fallback to dark
tui'inline' | 'fullscreen'Renderer. Unset = decision chain (fullscreen by default)
inlinebooleanStart inline. DEEPCODE_INLINE=1 and --inline take precedence
viewMode'default' | 'focus'Initial view. 'focus' starts in — and locks — the collapsed view
outputStylestringOutput style name
statusLineCommandstringCustom status-line command; its stdout is appended to the status line
spinnerTipsbooleanRotating spinner tips, on by default
spinnerTipsOverrideobjectCustom tips (tips / excludeDefault)

Cost & notifications

FieldTypeNotes
costWarnCNYnumberSpend warning threshold; the status line changes color once
preferredNotifChannelDesktop notification channel. Unset = auto = on
messageIdleNotifThresholdMsnumberIdle time before a desktop notification fires. Default 60000

Sessions & git

FieldTypeNotes
cleanupPeriodDaysnumberSession retention in days; over-age .jsonl files are deleted at startup. Unset or ≤0 = never clean up
attribution{ commit?, pr? }Override git attribution text; empty string hides it
includeCoAuthoredBybooleanDeprecated — use attribution
autoUpdatesbooleanWhether background auto-upgrade is allowed

Workflows

FieldTypeNotes
workflowKeywordTriggerEnabledbooleanKeyword-triggered Workflow guidance, on by default
skipWorkflowUsageWarningbooleanSkip the multi-agent spend warning. Default false
doneMeansMergedboolean/loop autonomous mode: treat "merged" as task completion

Layers and "dangerous key" stripping

Configuration merges across four layers — userprojectlocalflag — each overriding the last.

But the project layer (config committed in a repo) has a set of keys stripped out, because project config may come from a repository you don't trust:

apiKey  baseURL  hooks  mcpServers  webSearch
allowedHttpHookUrls  httpHookAllowedEnvVars
provider  providers  statusLineCommand
autoModeModel  autoModeThinking  disableAutoMode
language  cleanupPeriodDays
attribution  includeCoAuthoredBy
skillOverrides  autoUpdates  availableModels

Each one is on the list for a specific reason, not as a blanket rule:

KeyWhat a hostile repo could do with it
languageIts contents land in the system prompt — a prompt-injection channel
cleanupPeriodDaysSilently delete your session history
attribution / includeCoAuthoredByErase AI attribution
skillOverridesRe-enable skills you disabled at the user layer
autoUpdatesInfluence whether your global install gets modified in the background
availableModelsIt's the gate on model; writable from a repo means expensive tiers can be added to the allowlist and the clamp becomes meaningless
statusLineCommandArbitrary command execution

Stripping is never silent — startup reports which keys were dropped on stderr. /config shows the merged configuration along with the source layer of every key.