Skip to content

Configuration

This is the full configuration reference. For a friendlier overview, see Settings & Customization.

Every key you can meaningfully set is documented below. Your config.json also carries a handful of keys the app writes for itself and never surfaces in the UI, such as remembered window bounds and pop-out positions, saved workspace layouts, which announcements you have dismissed, and the model lists discovered per agent. They are safe to leave alone, and deleting one just makes the app re-derive it.

Kangentic resolves settings in three layers:

  1. Built-in defaults - sensible defaults for all settings
  2. Global user config - your personal defaults for all projects
  3. Project overrides - per-repository settings

Effective config = deep-merge(defaults, global config, project config).

When you create a new project, Kangentic seeds its .kangentic/config.json with only a subset of your most recently configured project’s settings: theme, agent.permissionMode, and git.*. Everything else falls back to the built-in defaults. (terminal.* used to be seeded here; it became global-only in v0.31.0 and is no longer per-project.) Project-specific data - notably browser.* (including browser.defaultUrl) and saved backlog import sources - is stored per-project and is never copied into a new project, so one repository’s dev-server URL or issue-tracker connections cannot leak into another.

Global: %APPDATA%\kangentic\config.json

Project: <project>/.kangentic/config.json

Project settings override global settings when both are present.

KeyTypeDefaultScopeDescription
themestring"dark"BothUI theme: dark, light, moon, forest, ocean, ember, sand, mint, sky, peach
sidebarVisiblebooleantrueGlobal onlyShow/hide the sidebar
boardLayoutstring"horizontal"Global onlyBoard scroll direction: horizontal or vertical
cardDensitystring"default"Global onlyTask card density: compact, default, or comfortable
columnWidthstring"default"Global onlyColumn width: narrow, default, or wide
showTaskNumbersbooleantrueGlobal onlyShow each task’s #N (display ID) number on its board card. Labeled Ticket Numbers in Settings > Task
terminalPanelVisiblebooleantrueGlobal onlyShow the bottom terminal panel
statusBarVisiblebooleantrueGlobal onlyShow the status bar at the bottom of the window
animationsEnabledbooleantrueGlobal onlyEnable transition animations across the UI
diffViewModestring"split"Global onlyDefault layout for Git file diffs in the Changes panel: split (side by side) or inline (unified)
diffDefaultScopestring"working"Global onlyScope a freshly opened Changes panel shows: working (uncommitted edits), staged (index), or branch (the full branch vs its base)
diffIgnoreWhitespacebooleanfalseGlobal onlyHide whitespace-only changes in the diff to filter out reformatting noise
diffCollapseUnchangedbooleanfalseGlobal onlyFold away large unchanged regions, showing only the changed hunks with a little context
diffWrapLinesbooleanfalseGlobal onlySoft-wrap long lines onto the next row instead of scrolling the diff horizontally. Applies to both split and inline mode
diffUseInlineWhenNarrowbooleantrueGlobal onlyRender a narrow diff pane inline (unified) even when split is selected, instead of squeezing two columns. Off forces side by side at any pane width
diffFileSortstring"name"Global onlyChanges panel file ordering: name, status (additions first, deletions last), size (most-changed first), or ext (by extension). In the flat list, status adds a heading and count at each group boundary
diffFlatListbooleanfalseGlobal onlyShow changed files as a flat list of full paths instead of a nested directory tree
windowLightDismissstring"focused"Global onlyWhether clicking empty space outside a task-detail window dismisses windows: off (never), single (only when exactly one window is open), focused (the focused window, whichever is open), or all (every open window). Dismissing keeps the agent running and returns its terminal to the bottom panel. A persisted single migrates to focused once on upgrade
skipDeleteConfirmbooleanfalseGlobal onlySkip confirmation dialog on task delete
skipBoardConfigConfirmbooleanfalseGlobal onlySkip confirmation when applying board config changes
autoFocusIdleSessionbooleanfalseGlobal onlyAuto-switch to session tab when agent goes idle
autoNameRateLimitPerHournumber60Global onlyMaximum auto-name CLI calls per rolling 60-minute window, capping cost on burst task creation. 0 disables the limit. Config-file only (no Settings toggle)
restoreWindowPositionbooleantrueGlobal onlyRestore window position and size from last session
hotkeyOverridesRecord<string, string>{}Global onlyRebound hotkeys, mapping a keybinding action id such as commandBar.toggle to a combo. A combo is either a keyboard chord (Mod+Shift+K, where Mod is Cmd on macOS and Ctrl elsewhere) or a mouse button (Mouse:Middle, Mouse:Back, Mouse:Forward). Absent ids use the registry default. Edited in the Hotkeys tab and replaced wholesale on save, so a reset removes the key. See Hotkeys
statusBarPeriodstring"live"Global onlyDeprecated: the status-bar usage strip was replaced by the Usage Stats Dashboard in v0.30.0. Read once as a seed fallback for usageStatsPeriod, never written anymore

Persistence for the Usage Stats Dashboard. Both values are one global selection shared across all projects.

KeyTypeDefaultScopeDescription
usageStatsPeriodstring"live"Global onlySaved time range for the usage dashboard: live, today, week, month, all
usageStatsScopestring"project"Global onlySaved dashboard scope: project (current project) or all (app-wide rollup)

Persisted view preferences for the Agent Monitor, shared by the in-app overlay and the pop-out window.

KeyTypeDefaultScopeDescription
monitor.layoutstring"cards"Global onlyMonitor layout: cards, table, or list
monitor.groupBystring"project"Global onlyGrouping: project or state
monitor.sortstring"longest-running"Global onlyRow order within a group: longest-running or recently-started
monitor.liveOnlybooleanfalseGlobal onlyShow only sessions with a live agent (the Idle and Active buckets), hiding Paused - which covers both suspended and queued sessions - and Recently finished. It deliberately never hides Idle: those are agents waiting on you
monitor.textFilterstring""Global onlyPersisted toolbar filter text
monitor.projectFilterstring[][]Global onlyProject ids the monitor is scoped to; empty means every project. Written by the toolbar’s Projects multi-select and kept across restarts (sanitized to a deduped list). An id naming a project with no sessions in the next non-empty snapshot is dropped and re-saved, so the filter always stays representable in the control
monitor.stateFilterstring[][]Global onlyRestrict the monitor to these session states: needs-you, working, idle, finished. The values map to the monitor’s section labels Idle, Active, Paused, and Recently finished, in that order. No control writes it today; edit config.json directly
KeyTypeDefaultScopeDescription
backlog.prioritiesarraySee belowBothCustomizable priority levels with labels and colors
backlog.labelColorsobject{}BothDefault color mappings for backlog labels ({ "label-name": "#hex" })

Default priorities:

IndexLabelColor
0None#6b7280
1Low#3b82f6
2Medium#eab308
3High#f97316
4Urgent#ef4444
KeyTypeDefaultScopeDescription
terminal.shellstring | nullnullGlobal onlyShell executable path. null = auto-detect
terminal.fontFamilystring"Menlo, Consolas, \"Courier New\", monospace"Global onlyTerminal font family. The Settings picker is a system-font autocomplete populated from your installed fonts
terminal.fontSizenumber14Global onlyTerminal font size (px)
terminal.cursorStylestring"block"Global onlyCursor style: block, underline, or bar
terminal.backspaceSendsCtrlHbooleanfalseGlobal onlyLabeled Word delete on Backspace: plain Backspace sends Ctrl+H (0x08) instead of Delete (0x7f), so Claude Code’s TUI deletes the previous word instead of one character. Off by default; Ctrl+W, Alt+Backspace, and Ctrl+Backspace already word-delete regardless
terminal.colorsTerminalColorOverrides{}Global onlyCustom terminal background, foreground, and cursor color, set via swatches in the Terminal tab’s Colors section. Unset slots fall back to the built-in defaults (background #0c0c0c, foreground/cursor #e4e4e7). The 16-color ANSI palette (Windows Terminal “Campbell”) is a fixed built-in scheme, not individually editable
terminal.showPreviewbooleanfalseGlobal onlyShow a live terminal preview snippet on task cards. Config-file only (no Settings toggle)
terminal.panelHeightnumber250Global onlyBottom panel height (px)
terminal.panelCollapsedbooleanfalseGlobal onlyPersisted collapsed state of the bottom terminal panel

Agent settings are unified across all thirteen coding agents: Claude Code, Codex CLI, Gemini CLI, Cursor CLI, GitHub Copilot CLI, Grok Build, Antigravity CLI, OpenCode, Aider, Qwen Code, Kimi Code, Factory Droid, and Warp/Oz CLI. The local-chat Ollama adapter is also detected and can take a CLI-path override (it appears in agent.cliPaths below), but it has no permission modes or model/effort settings of its own.

KeyTypeDefaultScopeDescription
agent.permissionModestring"acceptEdits"BothDefault permission mode for spawned agents
agent.cliPathsobject{}Global onlyPer-agent CLI path overrides, keyed by agent name (claude, codex, gemini, cursor, copilot, grok, antigravity, opencode, aider, qwen, kimi, droid, warp, ollama). null = auto-detect. Example: { "claude": null, "codex": "/usr/local/bin/codex", "kimi": "/Users/me/.local/bin/kimi" }
agent.launchOptionsobject{}Global onlyPer-agent boolean startup toggles (agent name to option id to enabled), shown as Launch Options rows in the Agent tab when the selected agent declares one. Today only Codex declares one, Disable ChatGPT Apps (disableApps), which launches with --disable apps to skip the optional cloud ChatGPT Apps connector that can hang startup
agent.executionServersobject{}Global onlyRemote-server identity for agents that support remote execution (today OpenCode), keyed by agent name: { url, auth }, where auth is none, HTTP basic, or a bearer token read from an env var. Machine-scoped like agent.cliPaths - it names a server, not a project
agent.executionobject{}BothPer-agent, per-project execution mode: { mode: "local" | "remote", workingDirectory }. An absent entry means local. workingDirectory is a path on the server for this project’s tasks. Stored per-project and never seeded into new projects
agent.maxConcurrentSessionsnumber8Global onlyMax concurrent PTY sessions across all agents
agent.queueOverflowstring"queue"Global onlyOverflow behavior: queue or reject
agent.idleTimeoutMinutesnumber0Global onlyAuto-suspend sessions after N minutes idle. 0 = disabled
agent.autoResumeSessionsOnRestartbooleantrueGlobal onlyWhen true, agent sessions that were running at last close auto-resume when Kangentic restarts. When false, sessions stay paused and require a manual Resume click on each task. Turn off if auto-resuming many agents at once overwhelms your machine.

Each agent advertises its own supported permission modes, and the Edit Column and Settings dropdowns update dynamically when you switch agents. The full set of modes is:

ModeBehaviorSupported by
planRead-only tools auto-approved; edits require approvalClaude, Codex, Gemini, Copilot, Grok, Antigravity, OpenCode (Plan agent), Aider, Qwen, Kimi, Warp
defaultUses the agent’s built-in defaults (e.g., Claude Code’s .claude/settings.json allowlist)Claude, Codex, Gemini, Cursor, Copilot, Grok, Antigravity, Aider, Qwen, Kimi, Droid, Warp
acceptEditsFile edits auto-approved; other actions prompt (OpenCode: maps to its Build agent)Claude, Codex, Gemini, Copilot, Grok, Antigravity, OpenCode, Aider, Qwen
bypassPermissionsFull autonomy, no permission prompts at allClaude, Codex, Gemini, Cursor, Copilot, Grok, Antigravity, Aider, Qwen, Kimi, Warp
dontAskDeny everything not already allowed, no interactive promptsClaude, Codex, Copilot, Grok
autoClassifier-driven auto-approvalClaude, Copilot, Grok

Per-agent defaults:

AgentDefault permission modeNotes
Claude CodeacceptEdits
Codex CLIacceptEdits
Gemini CLIacceptEdits
Cursor CLIbypassPermissionsNon-interactive mode is the default so the stream-JSON init event fires and the ContextBar model pill resolves
GitHub Copilot CLIacceptEdits
Grok BuildacceptEditsAll six Kangentic modes pass through 1:1 via --permission-mode; labels describe grok’s own behavior
Antigravity CLIacceptEditsMapped onto agy’s autonomy flags (--mode plan, --mode accept-edits, --dangerously-skip-permissions); default is agy’s request-review mode
OpenCodeacceptEditsLabels surface OpenCode’s native Plan and Build agents - selecting Plan maps to OpenCode’s read-only built-in agent
AiderbypassPermissionsAider is an edit-first CLI that expects broad file-write access
Qwen CodeacceptEditsLabeled “Auto Edit” - soft fork of Gemini CLI
Kimi CodedefaultLabels: Plan, Default (Confirm Actions), YOLO
Factory DroiddefaultSingle “Default” entry; autonomy is controlled in the Droid TUI (Shift+Tab cycles low/medium/high)
Warp (Oz CLI)defaultPermission-mode labels are informational only; Warp manages permissions via agent profiles (--profile)

Permission mode is resolved in priority order:

  1. Task’s permission_mode (if set) - pinned in the New Task dialog’s Advanced section or the task-detail edit form; it wins for the task’s whole lifetime, and column moves cannot change it
  2. Column’s permission_mode (if set)
  3. agent.permissionMode from config
KeyTypeDefaultScopeDescription
git.worktreesEnabledbooleantrueBothCreate isolated git worktrees per task
git.autoCleanupbooleantrueBothDelete branches when worktrees are removed
git.defaultBaseBranchstring"main"BothDefault base branch tasks start from: both the ref a worktree is cut from and the one a non-worktree task’s branch checkout is fast-forwarded from
git.copyFilesstring[][]BothFiles to copy from repo root into new worktrees
git.initScriptstring | nullnullBothShell script run in each new worktree after creation (e.g. npm install). Runs to completion before the agent spawns; a non-zero exit fails worktree setup
git.linkNodeModulesbooleantrueBothSymlink the repo-root node_modules into each new worktree so agents skip a fresh install. Disable to let git.initScript install dependencies in the worktree itself
git.prRefreshIntervalMinutesnumber | null5BothHow often (in minutes) to refresh linked pull-request state in the background while a project is open. null disables the periodic refresh; PR state still refreshes when the project opens
KeyTypeDefaultScopeDescription
contextBar.showShellbooleantrueGlobal onlyShow shell name in context bar
contextBar.showVersionbooleantrueGlobal onlyShow agent CLI version
contextBar.showElapsedbooleantrueGlobal onlyShow a ticking wall-clock elapsed time since the session started
contextBar.showCostbooleantrueGlobal onlyShow session cost
contextBar.showToolCallsbooleantrueGlobal onlyShow the cumulative count of completed tool calls. Click the pill for a per-tool breakdown
contextBar.showAgentActivebooleanfalseGlobal onlyShow the agent’s active time as reported by the CLI. Opt-in by default (it overlaps conceptually with elapsed time) to keep the bar lean
contextBar.showTokensbooleantrueGlobal onlyShow token usage
contextBar.showContextFractionbooleantrueGlobal onlyShow context window fraction
contextBar.showProgressBarbooleantrueGlobal onlyShow context window progress bar
contextBar.showRateLimitsbooleantrueGlobal onlyShow adapter-reported rate-limit bars (Claude reports 5-hour session and 7-day weekly windows; hidden for adapters that don’t report rate limits)

The model and effort pills are always visible when the adapter reports them. Both pills double as click-targets for the per-task model/effort picker popover, so they no longer have show/hide toggles. Effort levels are surfaced for adapters whose discoverCapabilities reports a non-empty effortLevels list (Claude Code in particular).

KeyTypeDefaultScopeDescription
sidebar.widthnumber400Global onlySidebar width in pixels

Settings for the embedded browser pane.

KeyTypeDefaultScopeDescription
browser.enabledbooleantrueBothWhen false, the Browser pill is hidden in the task detail window header, and an agent calling kangentic_browser_open_pane is refused with a message telling it to ask you to enable the pane
browser.defaultUrlstring | undefinedundefinedBothProject-default URL used when a task has no per-task override. Set only deliberately, via Save as project default in the pane or this setting; a task navigation never seeds it (it did before v0.36.0). Stored per-project; never seeded into new projects

A cross-project security policy governing whether and how an agent may drive the embedded Browser pane via the kangentic_browser_* MCP tools. These are separate from the per-project browser.* pane settings above and live under the Agent Browser settings tab. They are resolved with the defaults below when unset (they are not written into the built-in DEFAULT_CONFIG).

KeyTypeDefaultScopeDescription
browserAutomation.enabledbooleantrueGlobal onlyMaster switch. When false, the kangentic_browser_* tools are not registered at all
browserAutomation.allowInteractionbooleantrueGlobal onlyAllow click, type, keypress, and drag. When false, agents are observe-only (screenshots and DOM reads still work)
browserAutomation.allowNavigationbooleantrueGlobal onlyAllow navigating the pane to other URLs. Turn off to confine agents to the page you loaded
browserAutomation.allowEvalbooleanfalseGlobal onlyAllow arbitrary JavaScript eval in the loaded page (kangentic_browser_eval). Off by default - the one unbounded primitive, running with the page’s cookies
browserAutomation.restrictNavigationToLocalhostbooleanfalseGlobal onlyOnly allow navigation to localhost / private hosts, never public sites. Off by default (any http(s) URL allowed)

The scan range Kangentic draws from when an agent asks for a free dev-server port with kangentic_reserve_dev_ports. Config-file only: there is no Settings UI, and the keys are not written into the built-in DEFAULT_CONFIG.

Kangentic never starts or supervises a dev server, and nothing is reserved up front. A task holds ports only once its agent has asked for them, and the reservation lives until the task or its project is deleted.

The ledger itself is deliberately in the global database, not per project: ports are a shared resource, so a per-project ledger could not see that another project already holds 4200. That scopes it to one Kangentic instance rather than the whole machine. A bind probe, run against every candidate before it is handed out, is what keeps two instances (or any other process) from colliding.

KeyTypeDefaultScopeDescription
devServer.portRangeStartnumber7300Global onlyFirst port considered when reserving
devServer.portRangeEndnumber7499Global onlyLast port considered when reserving, inclusive

Local push-to-talk voice-to-text into whatever text field or terminal holds focus. Global/shared scope (hardware and user level, not per-project); lives under the Dictation settings tab. The push-to-talk key binding is set via keybindings (the dictation.pushToTalk action), not here.

KeyTypeDefaultScopeDescription
dictation.enabledbooleanfalseGlobal onlyMaster toggle: show the mic button and enable push-to-talk
dictation.engineModestring"auto"Global onlyTranscription engine selection: auto (tiers by detected hardware), sherpa-onnx, whisper-cpp, hybrid, or remote (uses the cloud backend below). The non-auto values force a specific engine for latency-vs-accuracy comparison
dictation.modelIdstring | nullnullGlobal onlyThe final (accurate) model. null = the tier default (Parakeet); "none" = keep the live text with no refinement pass
dictation.liveModelIdstring | nullnullGlobal onlyThe live (preview) model. null = the streaming Zipformer; "none" = no live preview
dictation.modestring(derived)Global onlyQuality preset: fast, balanced, or accurate (each locks the live + refinement models), or custom (unlocks manual model choice)
dictation.punctuationbooleantrueGlobal onlyAdd punctuation and capitalization to committed text
dictation.languagestring"en"Global onlyBCP-47 language. v1 ships English only
dictation.autoSubmitbooleantrueGlobal onlyPress Enter automatically after inserting the text; set false to leave it in the input for review. Refused regardless of this setting for a field inside a multi-field form, and for any field inside a page loaded in the Browser pane - see Dictation
dictation.releaseBufferMsnumber250Global onlyKeep the mic open this many ms after releasing push-to-talk so the last word isn’t clipped (0-500, snaps to 50ms steps; 0 = stop immediately)
dictation.experiencestring"popup"Global onlyLive UI surface while dictating: popup (floating panel), docked (bar by the terminal input), or live (type into the resolved target as you speak, each revision replacing the last in place). The stored default is popup, but live is what actually ships
dictation.remoteobject(unset)Global onlyOpenAI-compatible /v1/audio/transcriptions endpoint for the final text, used when engineMode is remote. The live preview still runs on-device; only the final clip is sent

Local conversation search and recall. Global/shared scope (per-machine, on-device); lives under the Memory settings tab, next to Dictation (both are keyless, on-device, model-backed features). Kangentic indexes the structured transcript of each agent conversation into a local per-project index that powers the Quick Find Conversations group (for you) and the kangentic_search MCP tool (for agents). Keyword search is on by default; the semantic (embedding) layer is opt-in. See Conversation Memory for the full feature.

KeyTypeDefaultScopeDescription
memory.indexingEnabledbooleantrueGlobal onlyIndex agent conversation transcripts locally for search and recall. When false, no indexing runs, no conversation hits appear in Quick Find or kangentic_search, and the embedding worker never starts. Fully local and keyless
memory.semanticEnabledbooleanfalseGlobal onlyEnable the semantic (embedding) layer on top of keyword search. Turning it on triggers a one-time local download of the selected memory.embeddingModel and background embedding of the index. Keyword search works regardless; if the model or vector extension is unavailable, search transparently falls back to keyword-only
memory.embeddingModelstring"bge-base"Global onlyWhich local embedding model powers semantic search, chosen by quality in the Memory tab. Options (all bge-*-en-v1.5, ONNX, keyless, offline): bge-small (Balanced, 384d, ~34 MB), bge-base (Accurate, 768d, ~110 MB), bge-large (Best accuracy, 1024d, ~337 MB). Switching re-embeds the index in the background
memory.accelerationstring"auto"Global onlyWhich hardware the embedding model runs on: auto (default) and gpu prefer a GPU execution provider (DirectML on Windows, WebGPU elsewhere) and fall back to CPU; cpu forces the universal path
KeyTypeDefaultScopeDescription
notifications.desktop.onAgentIdlebooleantrueGlobal onlyDesktop notification when agent goes idle
notifications.desktop.onAgentCrashbooleantrueGlobal onlyDesktop notification when a session exits with an error
notifications.desktop.onPlanCompletebooleantrueGlobal onlyDesktop notification when planning completes
notifications.desktop.onSpawnStalledbooleantrueGlobal onlyDesktop notification when a task spawn has been preparing (worktree/git) longer than the stall threshold
notifications.toasts.onAgentIdlebooleantrueGlobal onlyIn-app toast when agent goes idle
notifications.toasts.onAgentCrashbooleantrueGlobal onlyIn-app toast when a session exits, cleanly or with an error. The notifications.desktop.onAgentCrash row above fires on error exits only
notifications.toasts.onPlanCompletebooleantrueGlobal onlyIn-app toast when planning completes
notifications.toasts.onSpawnStalledbooleantrueGlobal onlyIn-app toast (with a Cancel action) when a task spawn stalls preparing its worktree
notifications.toasts.durationSecondsnumber4Global onlyHow long toasts display
notifications.toasts.maxCountnumber5Global onlyMaximum simultaneous toasts on screen
notifications.cooldownSecondsnumber10Global onlyMinimum seconds between repeated notifications

Each column (swimlane) can override settings individually:

FieldTypeDefaultDescription
descriptionstring | nullnullFree-form description of the column’s purpose. Shown as a header tooltip and shared with your team via kangentic.json. null when unset
permission_modestring | nullnullPermission mode override for this column
auto_spawnbooleantrueWhether moving a task here spawns an agent
auto_commandstring | nullnullCommand injected into running sessions on task arrival
auto_command_modestring'immediate'When that command fires: immediate delivers on arrival, and the CLI queues it if the agent is mid-turn, while deferred holds it until the current turn completes. Neither mode interrupts a running turn. A freshly spawned session ignores both and waits for the agent’s first activity
plan_exit_target_idstring | nullnullTarget column when plan-mode agent exits
agent_overridestring | nullnullUse a specific agent for sessions in this column (one of "claude", "codex", "gemini", "cursor", "copilot", "grok", "antigravity", "opencode", "aider", "qwen", "kimi", "droid", "warp", "ollama"). null inherits the project default agent
model_overridestring | nullnullAdapter-specific model identifier passed at spawn (e.g. Claude --model opus, Codex --model gpt-5-codex). Live-applied via the agent’s /model slash on column transition when supported
effort_overridestring | nullnullAdapter-specific effort/reasoning level passed at spawn (e.g. Claude --effort xhigh). Live-applied via the agent’s /effort slash on column transition when supported
handoff_contextbooleanfalseWhen enabled, point the next agent at the prior agent’s native session history file when a task moves into this column. Any agent can receive one; whether context carries depends on the outgoing agent. Claude, Codex, Gemini, Grok, Antigravity, OpenCode, Aider, Qwen, Kimi, and Droid leave a readable history; Cursor, Copilot, Warp, and Ollama leave nothing Kangentic can hand on
session_targetstring'main'Which session track a task runs on in this column: main (the task’s shared main conversation, resumed as it moves between normal columns) or isolated (this column’s own separate, context-isolated session, keyed by the column). Leaving an isolated column resumes the main session. Forced to main for To Do / Done columns
session_spawn_strategystring'create_or_resume'What to do with that session track on column entry: create_or_resume (resume the track’s session if one exists, else spawn) or always_spawn_new (always spawn a fresh, independent pass, retiring the prior session). The default is context-aware: isolated columns default to always_spawn_new, main columns to create_or_resume. Governs column entry only - an app restart or pause/resume still resumes an in-progress session

The available models and effort levels are surfaced from each adapter’s discoverCapabilities probe - the Edit Column dropdown shows only what the active CLI supports. See Custom Workflows for details on how these interact.

Kangentic includes 10 built-in themes:

  • Dark - Default dark theme
  • Moon - Cool-toned dark theme
  • Forest - Green-accented dark theme
  • Ocean - Blue-accented dark theme
  • Ember - Warm orange-accented dark theme

Set the theme in the settings panel or in your global config file.

These settings cannot be overridden per-project:

  • agent.maxConcurrentSessions
  • agent.queueOverflow
  • agent.cliPaths
  • agent.idleTimeoutMinutes
  • agent.autoResumeSessionsOnRestart
  • agent.launchOptions
  • agent.executionServers
  • sidebarVisible
  • skipDeleteConfirm
  • skipBoardConfigConfirm
  • autoFocusIdleSession
  • autoNameRateLimitPerHour
  • boardLayout
  • cardDensity
  • columnWidth
  • showTaskNumbers
  • terminalPanelVisible
  • statusBarVisible
  • animationsEnabled
  • diffViewMode
  • diffDefaultScope
  • diffIgnoreWhitespace
  • diffCollapseUnchanged
  • diffWrapLines
  • diffUseInlineWhenNarrow
  • diffFileSort
  • diffFlatList
  • windowLightDismiss
  • sidebar.width
  • terminal.shell
  • terminal.fontFamily
  • terminal.fontSize
  • terminal.cursorStyle
  • terminal.colors
  • terminal.backspaceSendsCtrlH
  • terminal.panelHeight
  • terminal.panelCollapsed
  • terminal.showPreview
  • restoreWindowPosition
  • statusBarPeriod (deprecated)
  • usageStatsPeriod
  • usageStatsScope
  • monitor.* (all Agent Monitor view settings)
  • mcpServer.enabled
  • mcpServer.bindAddress
  • mcpServer.callbackHost
  • notifications.* (all notification settings)
  • contextBar.* (all context bar settings)
  • browserAutomation.* (all Agent Browser settings)
  • dictation.* (all dictation settings)
  • memory.* (all conversation-memory settings)
  • mobileBridge.* (all mobile-bridge settings)
  • developer.* (all developer settings)
  • hotkeyOverrides
KeyTypeDefaultScopeDescription
mcpServer.enabledbooleantrueGlobal onlyEnable/disable the MCP server that lets agents interact with the board
mcpServer.bindAddressstring"127.0.0.1"Global onlyNetwork interface the in-process MCP HTTP server listens on. Not exposed in the Settings UI; edit config.json directly. The loopback default keeps the server local; to reach it from another machine use a wildcard like 0.0.0.0 (which still binds loopback), never a single non-loopback interface. Read once at startup
mcpServer.callbackHoststring | undefinedunsetGlobal onlyExtra hostname allowlisted alongside bindAddress for the server’s DNS-rebinding protection, so a legitimate external request is not rejected. Not exposed in the Settings UI; edit config.json directly

When enabled, each agent session gets access to MCP tools for creating tasks, searching the board, browsing the backlog, and reading session transcripts. See the MCP Server reference for the full list of tools. As of v0.15.0 the MCP server runs as an in-process streamable HTTP transport (replacing the earlier file-bridge). Disable this if you don’t want agents to be able to modify the board.

As a runaway-loop safeguard, the MCP server caps task creation at 500 tasks per app launch. Once the cap is hit, kangentic_create_task returns an error until you restart Kangentic. This is a fixed limit, not a configurable setting.

The desktop half of the mobile companion app link, configured in Settings > Mobile Devices. These keys are global: they describe this desktop installation, not any one project. The bridge ships in production builds and is off until you turn it on.

KeyTypeDefaultScopeDescription
mobileBridge.enabledbooleanfalseGlobal onlyMaster switch. While off, no relay connection is held and pairing is unavailable
mobileBridge.relayModestringresolves to "hosted"Global onlyWhich relay to dial: hosted (the Kangentic-operated relay at wss://relay.kangentic.com), or custom (your own, from relayUrl). A third value, local, is dev-build only: a shipped build reports and dials hosted even if a persisted local reaches it. Deliberately absent from the shipped defaults rather than set to "hosted", so that a config written before this key existed, but carrying a relayUrl, is still inferred as custom instead of being silently moved onto the hosted relay
mobileBridge.relayUrlstring""Global onlyThe relay address to dial, consulted only when relayMode is custom. Must be wss://, or ws:// for loopback only. An empty or invalid value falls back to the hosted relay, so the dialed address is never blank

Pairing, the paired-device roster, and the install link are UI surfaces on the same tab rather than config keys. See Pairing a Phone for the ceremony and Kangentic Relay for what the relay does and how to run your own.

Power-user toggles for diagnosing the activity engine and other internal subsystems. All are global-only. In shipped builds they default to off; several turn on automatically in dev builds (npm start and /preview), as noted per key below. Toggle the whole panel from anywhere with Ctrl+Shift+D / Cmd+Shift+D.

KeyTypeDefaultDescription
developer.activityDebugOverlaybooleanfalseShow the floating activity-engine debug overlay (live counters, current activity reason, and recent transitions per running session). Also writes a per-session JSON snapshot under .kangentic/debug/ on each state change
developer.persistConsoleLogsbooleandev: true, prod: falsePersist info/debug/log console output to .kangentic/logs/<date>.log (errors and warnings are always persisted). Read via the kangentic_tail_logs MCP tool
developer.recordIpcTrafficbooleanfalseRecord every IPC handler call (channel, args, result, duration) to .kangentic/logs/ipc-<date>.jsonl. Sensitive channels are redacted. Off in production and regular dev; auto-enabled only in the ephemeral /preview instance, whose logs are wiped on close. Non-trivial disk impact
developer.previewInspectionServerbooleandev: true, prod: falseBind a localhost-only HTTP inspection bridge powering the dev-only devtools MCP tools. The UI affordance is excluded from production builds; the key persists for type compatibility but has no effect in shipped binaries
developer.previewEvalEnabledbooleandev: true, prod: falseStricter gate on top of previewInspectionServer that enables high-risk inspection endpoints (eval, synthetic session events, raw PTY input). On in dev builds, like previewInspectionServer; the UI affordance is dropped from production builds
VariableDescription
KANGENTIC_DATA_DIROverride the config/data directory path. Takes priority over the launcher’s --data-dir flag when both are set
KANGENTIC_TELEMETRYSet to 0 to disable all anonymous telemetry: usage analytics and error reporting
KANGENTIC_ERROR_REPORTINGSet to 0 to disable crash and error reporting only, leaving usage analytics on
KANGENTIC_ANNOUNCEMENTS_URLPoint the in-app announcements feed at a different URL (see Notifications)

Kangentic sends anonymous usage analytics to Aptabase and crash and error reports to Sentry. No code or task content is collected, one per-launch event carries a stable install identifier, and stack-frame paths are normalized to the app root before an error report leaves your machine - see Privacy & Analytics. Set KANGENTIC_TELEMETRY=0 to turn off both, or KANGENTIC_ERROR_REPORTING=0 to turn off error reporting alone.

See Privacy & Analytics for full details on what is collected and how to opt out.

Kangentic is free and open source. A star helps other people find it.

Star on GitHub