Kin / Reference

settings.toml keys

Every key kin reads from a settings.toml file. The file is the persistent baseline under your environment and flags — it feeds new sessions only (resuming reproduces a session's saved settings, never a live file). For…

Read as Markdown

Every key kin reads from a settings.toml file. The file is the persistent baseline under your environment and flags — it feeds new sessions only (resuming reproduces a session’s saved settings, never a live file). For the full precedence model, see Configuration.

File locations

kin reads layered TOML files, parsed with the standard-library tomllib (no extra dependency). The kin home (~/.kin, relocatable with KIN_HOME) holds three files with distinct owners:

File Path Role
Global ~/.kin/settings.toml Your machine-wide baseline — preferences and the provider catalogue. The file this page’s keys normally live in.
Credentials ~/.kin/credentials.toml Kin-managed secret store (provider_keys, api_key, brave_api_key, outpost_token, rig_token), created 0600. Written by kin connect, /models, and the key prompts — you never need to edit it.
Grants ~/.kin/grants.toml Kin-managed authority stores (sandbox_grants, git_host_grants). Audit it freely; manage it via /grants and the approval modals.
Project <workdir>/.kin/settings.toml Per-repo overlay, merged on top of the global layer.

All layers merge into one view — every key below behaves identically wherever it is stored; the sibling files exist so settings.toml stays a short file that is entirely yours. A secret or grant key found in a legacy settings.toml still works and moves to its sibling file automatically on the next settings write. Run kin settings to see the effective configuration, which file supplies each key, and configuration lint.

The project file overlays the global layer key by key. Every file is optional — a missing or malformed file degrades to “no settings” with a warning (set KIN_STRICT_SETTINGS=1 to raise instead). A complete, commented template ships as settings.toml.example in the repo; a fresh machine’s first interactive run also writes a short comments-only starter.

Project files can’t set global-only keys

A handful of keys are stripped (with a warning) from any project .kin/settings.toml — see Global-only keys. Set those in the global file, the environment, or a flag.

Keys

The scope column marks whether a key may live in a project file (project-ok) or only in the global file / environment / CLI (global-only).

Backend and model

Key Meaning Default Scope Env
provider Provider family: openai or anthropic. openai (or anthropic when a bare base_url is set and neither identity axis is selected) project-ok KIN_PROVIDER
wire_api OpenAI wire shape: public values chat or responses. Either implies provider = "openai" and bypasses the bare-URL Anthropic heuristic. provider = "openai" without this key and the built-in OpenAI preset both remain on Chat. Anthropic Messages is an internal value, not valid settings input. chat for OpenAI project-ok KIN_WIRE_API
model Model id. Set to default (any stable alias you register with your server) to follow whatever model is currently loaded; the harness probes /v1/models on session start and piggybacks response.model off each turn so the displayed name always reflects the live server. The alias survives model swaps on the wire. gpt-4o-mini (openai) / claude-opus-4-8 (anthropic) project-ok KIN_MODEL
base_url OpenAI-compat endpoint URL for the default backend (trailing /v1 trimmed for the Anthropic wire). A selected provider preset owns its endpoint; only an explicit caller URL overrides that preset identity. none global-only KIN_BASE_URL
api_key Endpoint auth. none (not-needed is sent) global-only KIN_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY
context_window Token budget for the context meter. Pins/overrides numeric server limits (max_model_len / context_length / max_input_tokens from /v1/models); capability metadata is still discovered. 200000, then refined from the server’s /v1/models metadata when base_url is set project-ok KIN_CONTEXT_WINDOW
max_tokens Per-response output cap. 16000 (anthropic) / 8192 (openai) project-ok KIN_MAX_TOKENS
provider_preset Provider preset id (openai, anthropic, minimax, zai, or a [[providers]] id). Bundles wire/endpoint/auth identity; curated rows also supply a default model, while direct OpenAI/Anthropic keep it explicit. none global-only KIN_PRESET
provider_keys Per-provider key table ({<preset_id> = "<key>"}) — the recommended shape when you swap between multiple providers. Read first by the factory’s chain (most specific selector — beats the generic api_key + env vars) so a stray ANTHROPIC_API_KEY baked into an image can’t silently shadow the key you stored for the active provider. /providers writes here when you paste a key. none global-only (also _SECRET_SETTINGS_KEYS — redacted wholesale to [SET] on read)
provider_tiers Per-provider capability tier table. MiniMax uses plus / max / ultra and Z.ai uses lite / pro / max to size ordinary subagent capacity. /providers writes the selected tier. {} (provider defaults: MiniMax plus, Z.ai lite) global-only
model_favorites List of "provider_id/model" strings the bare /model picker pins to the top (a Favorites group). Toggle a row with f in the picker. [] global-only
model_routes Named route tables ([model_routes.<id>]) that bind a trusted provider preset to an explicit model and optional capability/execution overrides. See Model routes. {} global-only
model_assignments Operator bindings for mca, vision, rig, task, workflow, utility (housekeeping side-calls such as session auto-titles), plus [model_assignments.profiles]. Values are route ids. {} global-only

Custom endpoints

A custom endpoint is a [[providers]] array-of-tables block — a self-contained preset (id, wire, base URL, default model) you can refer to from provider_preset. A custom row’s id can shadow a built-in (so operators can override a built-in’s URL without code changes), but the built-in lookup runs first so the curated catalogue wins for the common case.

[[providers]]
id = "openrouter"
provider = "openai"
wire_api = "chat" # or "responses"
base_url = "https://openrouter.ai/api/v1"
default_model = "anthropic/claude-3.7-sonnet"
models = ["anthropic/claude-3.7-sonnet"]

OpenAI custom rows may set wire_api = "chat" (the default) or opt into wire_api = "responses". Anthropic rows imply Messages and reject an OpenAI wire value. A row may carry reasoning_effort = "<level>" as the endpoint’s own default effort (opaque string, serve-owned vocabulary); on a Responses row this also opts the stream into reasoning-summary deltas — required for thinking-by-default serves like DS4 (see Models & providers). Custom rows may also set reasoning_profile = "poolside". That profile is valid only on an anthropic row and selects Laguna’s per-request chat_template_kwargs.enable_thinking control; an unknown profile or an OpenAI-wire pairing is rejected instead of guessed. See Laguna S 2.1 on vLLM. For the qualified text-only Responses shape backed by Paddock-managed llama.cpp, see Paddock and llama.cpp Responses.

Add a custom endpoint via /providers → “Custom endpoint…” or by hand. See Provider presets for the full shape and which keys are recognized.

model is an alias for default_model on custom rows

The one-key model = "default" shape (no default_model, no models) is accepted as a convenience for one-line single-model / stable-alias rows — the parser aliases modeldefault_model and seeds models = [model] so the /model picker still surfaces a pickable row. Use the explicit two-key form (default_model + models = [...]) when the picker should show every model your server actually serves.

Per-provider keys ([provider_keys])

When you swap between multiple providers, the recommended storage shape is the [provider_keys] table — one key per preset id. The factory’s resolution chain (_preset_key in src/kin/harness/backends/factory.py) reads provider_keys[<active_preset_id>] before falling back to environment variables / api_key, so a key stored here is the most specific selector. Direct OpenAI consults OPENAI_API_KEY then KIN_API_KEY; direct Anthropic consults ANTHROPIC_API_KEY then KIN_API_KEY, and neither borrows the other vendor’s conventional key. Compatibility/custom presets retain the broad legacy environment chain because their wire does not identify the credential issuer:

# ~/.kin/settings.toml (human-owned, non-secret selection)
provider_preset = "zai"          # which preset is "active" for next session
model = "glm-5.2"

[provider_tiers]
minimax = "plus"
zai = "lite"

Kin writes the corresponding secret table to its 0600 credential store:

# ~/.kin/credentials.toml (Kin-managed; shown only to explain storage)
[provider_keys]
zai = "sk-..."
minimax = "sk-..."

/providers writes to this table when you paste a key, so the next session and future routed calls find the key — no /reload, no manual settings.toml editing. For direct OpenAI/Anthropic rows, leaving the exact-model field blank refreshes the catalog for future route dispatch without switching the live MCA; running children keep their prior snapshot. The Outpost dashboard’s per-provider paste-key field writes to the same table (see Outpost). Top-level api_key is the generic fallback (one key, one endpoint); [provider_keys] is the per-provider shape.

Model routes

Model routes separate what a call is for from the endpoint wire. Every route references an existing built-in or custom provider preset; routes never own a URL or credential. Direct openai and anthropic preset ids are built in, so they work beside MiniMax, Z.ai, and custom [[providers]] rows. Their empty preset URL means the vendor SDK endpoint and does not inherit an ambient KIN_BASE_URL used by the default backend.

# ~/.kin/settings.toml
[provider_keys]
openai = "sk-..."
anthropic = "sk-ant-..."

[model_routes.primary]
provider_preset = "anthropic"
model = "your-text-model-id"
description = "Main collaboration model"
vision = false
effort = "high"
max_tokens = 16000
selectable_for = ["task", "workflow"]

[model_routes.visual]
provider_preset = "openai"
model = "your-vision-model-id"
description = "Isolated image inspection"
vision = true
selectable_for = ["task"]

[model_assignments]
mca = "primary"
vision = "visual"
rig = "visual"
task = "primary"
workflow = "primary"
utility = "visual"   # housekeeping side-calls (session auto-titles)

[model_assignments.profiles]
researcher = "primary"

Each [model_routes.<id>] accepts only these fields:

Field Required Meaning
provider_preset yes Built-in or custom preset id. This is the endpoint and credential trust boundary.
model yes Exact model id sent on that preset’s wire.
description no Operator description shown to humans and, only when selectable, to the task/workflow model.
vision no Authoritative true / false semantic-vision override. Omitted starts as unknown; Kin caches a supported or capability-rejected media attempt until reload.
reasoning_profile no Closed route request contract. qwen-llamacpp enables budget-labelled Qwen choices without applying nonstandard fields to other routes/providers.
effort no Per-route effort value, validated against that preset/model’s picker vocabulary.
max_tokens no Positive per-response output cap for this route.
selectable_for no Explicit model-choice allowlist containing only "task" and/or "workflow". Operator assignments do not need this opt-in.

Resolution is deterministic: profile assignment, then consumer assignment, then an allowed requested route, then a requested legacy model, then the current MCA backend. route and model are mutually exclusive, and an invalid model clone is an error rather than a silent fallback. Forks retain their parent’s exact backend. See Models & providers for media isolation, persistence, usage, and /reload behavior.

For reasoning_profile = "qwen-llamacpp", valid effort values are default, off, thinking-128, thinking-512, thinking-1024, and thinking-2048. The route’s max_tokens is a total output allowance and must exceed an enabled budget. A Utility assignment also requires 512 final-answer tokens beyond the budget. See Qwen bounded thinking.

utility is assignment-only: it binds kin-internal housekeeping side-calls (session auto-titles today) to a lightweight route so tiny requests stay off the main endpoint’s prompt cache. It is never model-selectable, its calls are best-effort (a busy route skips the call rather than queueing), and a failed utility call keeps the first-message fallback title instead of retrying on the main backend. Unassigned, housekeeping stays on the main backend as before.

Sampling and compatible reasoning controls

temperature, top_p, and top_k apply only on the OpenAI-compat wire. The Anthropic wire ignores per-request sampling, so set it on the server instead. enable_thinking has the explicit Poolside exception described below.

Key Meaning Default Scope Env
temperature Sampling temperature (0 = greedy). provider default project-ok KIN_TEMPERATURE
top_p Nucleus sampling. provider default project-ok KIN_TOP_P
top_k Top-k sampling (via extra_body). provider default project-ok KIN_TOP_K
enable_thinking Chat-template thinking soft switch for Qwen-style OpenAI-compatible serves and an Anthropic custom provider with reasoning_profile="poolside" (false hard-disables thinking). unset (model/server decides) project-ok KIN_ENABLE_THINKING
reasoning_effort OpenAI-proper reasoning-effort hint (real OpenAI / OpenRouter / Z.ai OpenAI-compat on GLM-5.2+; any custom Responses-wire endpoint). Top-level wire field on chat.completions.create — NOT inside extra_body; on the Responses wire it rides reasoning: {"effort": ..., "summary": "auto"} (the summary opt-in is what makes a thinking-by-default serve stream reasoning deltas). Per-serve vocab (3-value OpenAI vs 7-value Z.ai vs the Responses pass-through) is dispatched by the picker (see Models & providers); the resolver itself is opaque. Not for Qwen vLLM Chat serves (use enable_thinking above). A [[providers]] row may carry its own reasoning_effort default, which wins over this top-level file value when that row is selected; the higher-precedence KIN_REASONING_EFFORT environment override still wins over both. Cross-wire knob for the picker is effort, so this key is not in the model-writable set — reach it via effort=... which goes through the human-approval gate. unset project-ok KIN_REASONING_EFFORT
strict_tools Strict tool schemas on the streaming registry path (OpenAI-compat wire only). Each tool spec is normalized at request-build time (additionalProperties: false, all-required, optionals as ["type","null"] unions — the registry’s canonical schemas are never mutated) and stamped strict: true, so endpoints that honor it (OpenAI-proper; vLLM ≥ 0.24 auto tool choice) grammar-enforce arguments. A no-op on vLLM 0.23 auto calls; forced tool calls (the workflow schema= path) are strict-normalized unconditionally regardless of this key. Human-only (not model-writable). See Strict decoding. false project-ok KIN_STRICT_TOOLS

Fleet safety

Governance knobs for a shared, self-hosted endpoint — see Fleet safety in the headless guide.

Key Meaning Default Scope Env
token_budget Per-run cumulative token budget: once a run’s summed prompt+completion tokens (across every model round, subagent rounds included) cross this, the agent loop stops cleanly at the next model-round boundary — done reason token_budget, headless exit 1. A “run” is one root turn plus everything it fans out; the next turn starts fresh. Project-ok: the default is unlimited, so a project file can only impose a tighter cap (fail-safe). Human-only — deliberately not model-writable: the budget exists to stop a runaway model, so the model can never raise its own leash. 0 = off. 0 (off) project-ok KIN_TOKEN_BUDGET
max_turns Per-turn model-round cap: the maximum model↔tool round-trips one user turn may run before it ends with done reason turn_cap (headless exit 1). Independent of token_budget — the two limits are checked at the same round boundary. 0 = unlimited (the default) — the doom-loop guard (3× identical call+result) is the real no-progress backstop, so an unbounded cap is safe for large-model, hours-long runs. Project-ok: the default is unlimited, so a project file can only impose a tighter cap (fail-safe). Human-only — not model-writable (an operator leash, like token_budget). 0 (unlimited) project-ok KIN_MAX_TURNS
request_priority Legacy vLLM priority-scheduling passthrough (OpenAI-compat wire only). Rides extra_body["priority"] on every request; lower = scheduled earlier, with KV-swap preemption. Serve-gated: only meaningful when the server runs --scheduling-policy priority — vLLM errors on any non-zero priority otherwise, and current DS4 does not implement the field, which is why the default is absent from the request, not 0. Human-only (not model-writable). See Models & providers. unset (absent) project-ok KIN_REQUEST_PRIORITY

Media and caching

Key Meaning Default Scope Env
image_detail OpenAI vision tier for tool-returned images (low / high / auto). low project-ok KIN_IMAGE_DETAIL
effort Anthropic adaptive-thinking effort. high project-ok KIN_EFFORT
thinking_type Anthropic-wire thinking.type knob — z.ai / MiniMax / Fable honor this as their canonical reasoning control (NOT output_config.effort). Common values: adaptive (default), enabled (force on), disabled (off — avoid on serves that 400 on it). adaptive project-ok KIN_THINKING_TYPE
cache_ttl Anthropic system-prompt prefix-cache TTL (1h opts into the 1-hour cache). 5 minutes project-ok KIN_CACHE_TTL

Permissions and OS sandbox

Key Meaning Default Scope Env
mode Permission mode at launch (auto / strict; the legacy default / accept-edits / plan still resolve via the alias map). auto global-only KIN_MODE
sandbox OS sandbox backend for auto-mode shell (auto / seatbelt / bwrap / off / container). container trusts an external boundary — auto-mode shell runs unconfined instead of asking (see the auto-mode guide). auto global-only KIN_SANDBOX
sandbox_network Allow outbound networking inside Seatbelt/bubblewrap while retaining workspace write confinement and secret masking. No effect for off/container. true global-only KIN_SANDBOX_NETWORK
sandbox_strict Opt strict mode’s shell into the OS sandbox (so an un-vetted command runs contained instead of prompting). false global-only KIN_SANDBOX_STRICT
sandbox_default Legacy (pre-two-mode) name, still honored as a fallback for sandbox_strict. Prefer sandbox_strict. false global-only KIN_SANDBOX_DEFAULT
sandbox_grants Human-approved [[sandbox_grants]] rows written by the typed sandbox-access modal. Each row binds an sbg_… id and exact canonical workspace to write_paths, network, and ssh_agent capabilities. Invalid, sensitive, or mismatched rows are ignored fail-closed. Prefer /grants over hand-editing. [] global-only
git_host_grants Human-approved, secret-free [[git_host_grants]] rows written by the Git credential modal’s Trust host action. Each ghg_… row binds SSH/HTTPS + resolved user/host/port to a route fingerprint and display label; it never stores a token, key, socket path, remote URL, or repository path. A changed SSH/helper route asks again. Invalid rows are inert. Manage with /grants. [] global-only
sandbox_always_allow Inactive migration data. Older Kin versions stored fnmatch command patterns here. Current Kin lists them in /grants as requiring reapproval, but they never skip the OS sandbox. Remove them with /grants or by hand after migration. [] global-only
shell_allowlist When true, provably read-only shell commands auto-allow; false sends every command to the approval modal. true global-only KIN_SHELL_ALLOWLIST

Planning

Key Meaning Default Scope Env
persist_plans Retired, no-op. Plans are now saved to <workdir>/.kin/plans/<date>-NN-<slug>.md unconditionally on every write_plan call — this key no longer gates anything; kept only so an existing settings.toml doesn’t error. true project-ok KIN_PERSIST_PLANS

Sessions and persistence

Key Meaning Default Scope Env
session_dir Where session journals are written. ~/.kin/projects global-only KIN_SESSION_DIR
no_save Run ephemerally: write no session journal or durable prompt history (not resumable; composer recall remains memory-only for this process). false global-only KIN_NO_SAVE
prompt_history_cap Number of interactive composer submissions retained per project for ↑/↓ and ++ctrl+r++ across restarts. Includes model prompts, slash commands, and literal ! command text, but never shell output; headless kin -p prompts are excluded. 0 disables durable loading and writes without deleting the existing store, so re-enabling restores retained entries. Negative or malformed values fall back to 100. --no-save, KIN_NO_SAVE, and no_save = true always make recall memory-only. Human-only (prompt retention is a privacy choice, not a model knob). 100 project-ok KIN_PROMPT_HISTORY_CAP
detach Run interactive launches as background sessions/detach leaves the session running, kin in the same folder picks it back up. On by default when tmux ≥ 3.2 is on PATH (DR 0097); set false to opt out. A missing/too-old tmux degrades silently. kin --no-detach / --detach override per launch. Project-ok (it only re-hosts the same process locally — no egress, secret, or containment change). on (tmux available) project-ok KIN_DETACH

Notifications

Key Meaning Default Scope Env
notify The terminal bell / OSC 9 walk-away notification — a bare BEL always, plus a native desktop notification on a verified OSC-9-capable terminal (Ghostty / iTerm2 / WezTerm / kitty). Fires on a turn that ran 15s+ and on every needs-input prompt (TUI), or on process completion when stderr is a real terminal (kin -p). Default on; opt-out kill switch. Project-ok (it only toggles whether a static-string escape sequence is written; carries no model/server text). true project-ok KIN_NOTIFY
update_check The session-start update-availability check: one best-effort GET of https://get.kinra.ai/version.json (24h-cached) that renders the one-line “Update available … run: kin update” note. Privacy: the request carries only your kin version in its User-Agent. Default on; opt-out. Project-ok (the endpoint is a constant — a project file can only turn the check off). Explicit kin update / kin doctor runs don’t consult it. true project-ok KIN_UPDATE_CHECK

Appearance

Key Meaning Default Scope Env
theme TUI theme name. kin inherits the terminal background; kin-graphite is the opaque Graphite+ fallback. Bare /theme cycles that pair, while an explicit registered Textual theme name is also accepted. The command persists the choice here. Project-ok (pure display — no egress, secret, or containment impact). kin project-ok KIN_THEME
spinner The busy-spinner style name (rain · braille · arc · toggle · line — the vibe table lives in Identity). Unknown names fall back to the default; KIN_ASCII forces line. Pick interactively with /spinner (which persists here). Project-ok (pure display — no egress, secret, or containment impact). rain project-ok KIN_SPINNER

Context and compaction

Key Meaning Default Scope Env
env_context Include the Environment + git-state blocks in the system prompt. true project-ok KIN_ENV_CONTEXT
compact_threshold Auto-compact history once prompt usage crosses this fraction of the window (0.10.98). The effective trigger is capped below the hard input limit after reserving max_tokens output plus framing margin. unset (off) project-ok KIN_COMPACT_THRESHOLD
compact_keep_turns Minimum recent turns to preserve when compacting. 4 project-ok KIN_COMPACT_KEEP_TURNS

Skills and web

Key Meaning Default Scope Env
strict_skills Raise on malformed skill / agent frontmatter instead of graceful-degrading. false project-ok KIN_STRICT_SKILLS
brave_api_key Brave Search key; enables the web_search / web_context tools. none global-only BRAVE_API_KEY / KIN_BRAVE_API_KEY
search_enabled Register the search_workspace tool — ranked, chunk-aware lexical full-text search over workspace content (stdlib SQLite FTS5; the complement to grep, not semantic/vector search). Default on; set false to remove it. The index DB lives outside the workspace under ~/.kin/index/. Project-ok (a local index only — no network/egress/secret). true project-ok KIN_SEARCH_ENABLED
shelf_enabled Enable edge-triggered shelf board hints and the TUI’s fixed-refspec returned-branch watcher. true project-ok KIN_SHELF_ENABLED
shelf_watch_interval Seconds between TUI probes of refs/heads/shelf/*; read once at mount and clamped to a 30-second minimum. 120 project-ok KIN_SHELF_WATCH_INTERVAL
run_code_enabled Register the run_code / run_code_reset interpreter tools — the stateful per-session Python kernel. Default on; the tools ride the full shell permission gate (sandboxed in auto, asks in strict), so this is an opt-out kill switch. Project-ok (it only unregisters tools; it grants nothing the gate doesn’t). true project-ok KIN_RUN_CODE
diagnostics_after_edit Append a lint pass’s output to write_file/edit_file results on a nonzero exit (ruff check, v1 — shutil.which-gated, never blocks or fails the write). Default on; opt-out kill switch. true project-ok KIN_DIAGNOSTICS
diagnostics_ty Also run an opt-in ty typecheck pass inside diagnostics-after-edit. Default off — ty is slow and typed-project-specific. false project-ok KIN_DIAGNOSTICS_TY
snapshots The file snapshot-before-write safety net — a git commit-tree checkpoint under refs/kin-snapshots/ taken before the first edit of every turn, restorable via /rewind files/both. Default on; opt-out kill switch. A no-op outside a git workspace. Project-ok (only toggles whether the checkpoint runs; never touches the real index/HEAD/worktree). true project-ok KIN_SNAPSHOTS
paste_file_mentions Convert Finder drag-drops / terminal pastes of absolute file paths into @-mentions in the Composer (default on). Off → pastes insert verbatim, identical to pre-Rock-3 behavior. Project-ok (it only re-routes a paste from raw-text-insert to mention-insert — no egress / secret / containment surface beyond what a manual paste would carry); human-only (a UX toggle, NOT model-writable). true project-ok KIN_PASTE_MENTIONS
rig_enabled Register the Rig tool family when URL and token are also configured. Project-ok because it can only remove the tools; the endpoint and credential remain global-only. true project-ok KIN_RIG
rig_url Rig’s semantic API origin. Global-only so a cloned project cannot redirect a bearer-authenticated tool to a hostile endpoint. none global-only KIN_RIG_URL
rig_token Rig bearer credential, masked on every settings surface. Containers normally use KIN_RIG_TOKEN_FILE. none global-only KIN_RIG_TOKEN
browser_enabled Legacy no-op retained for migration-safe settings validation. true project-ok KIN_BROWSER
browser_allow_private Legacy no-op retained for migration-safe settings validation. Use the explicit task rig:local operator path for local/private targets. false global-only KIN_BROWSER_PRIVATE
memory_enabled Register the memory tool + the recall injections (the stable index block and per-turn top-5 recall). Default on; this is the opt-out kill switch. Project-ok (it only unregisters/disables; containment lives in the tool’s path guard). true project-ok KIN_MEMORY
memory_reflect Run the end-of-run reflection pass — a bounded extra turn over the live memory tool, fired automatically on a terminal clean kin -p stop with no pending human gate and at TUI quit. Project-ok (writes ride the same guarded store + containment as the tool). true project-ok KIN_MEMORY_REFLECT
memory_dir The memory root — where the memory tool reads and writes, and where the memory recall index lives. Global-only: memory mutations auto-apply in auto because they’re contained to this root, so a cloned repo’s project file must never be able to repoint that contained write surface at an arbitrary directory. ~/.kin/memory global-only KIN_MEMORY_DIR
ssh_hosts Deprecated no-op retained so existing settings files keep loading. Ordinary SSH uses shell; KIN_SSH_HOSTS is no longer read. [] global-only
outpost_url The origin of your Outpost (e.g. https://outpost.kinra.ai) — the outpost/outpost-send tools’ target. Both tools register only when this AND outpost_token are set. Global-only for the same reason ssh_hosts is: a cloned repo’s project file must never be able to repoint the tool at a hostile endpoint. none global-only KIN_OUTPOST_URL
outpost_token The bearer token (svc_<id>.<secret>) authenticating the outpost/outpost-send tools against your Outpost’s v1 API. A credential — masked to [SET]/[NOT SET] wherever settings render, same as api_key. none global-only KIN_OUTPOST_TOKEN

Observability

Key Meaning Default Scope Env
spans_enabled Write OTel-GenAI-shaped JSONL spans — one invoke_agent per turn, a chat per model round, an execute_tool per tool call — to <session_id>.spans.jsonl next to the journal. Metadata only (timing / names / token counts; never prompt or tool text). Project-ok (a local file, no network/egress/secret) and human-only (not model-writable). false project-ok KIN_SPANS
pricing_enabled Display a running USD cost total alongside the /tokens counts (verbose breakdown) and as a recessive cell on the StatusBar ($0.04). Sourced from a stdlib-only pricing table keyed by (provider, model id) — see Cost display. Default off (opt in) — the primary endpoint is local vLLM (no cost) and the subscription providers (MiniMax/z.ai) make per-token cost noise; turn it on with KIN_PRICING=1 / pricing_enabled = true / the /cost on slash command (which also persists the choice). An unpriced serve (local vLLM, an id not in the table) shows nothing rather than a misleading $0.00. Project-ok (a local computation + display only; no network, no secret, no containment impact) and human-only (observability, never a sampling knob). false project-ok KIN_PRICING

Background subagents

Key Meaning Default Scope Env
agent_stall_timeout Seconds without model/tool activity before an active, non-paused task agent becomes advisory stale. Staleness regains the MCA’s attention but never cancels or restarts the child. Human-only and clamped to 30–3600 seconds. 120 project-ok KIN_AGENT_STALL_TIMEOUT

Editing settings from inside kin

Two ways to change this file without leaving the TUI, both gated on a human diff-approval:

  • /edit-settings (or /config → settings) — you ask a scoped, read-only editor subagent to draft the whole file; you approve the diff. It may set any non-secret key.

  • /settings — turns on a per-turn settings guide so the model can help tune settings mid-conversation via the read_settings / propose_settings tools. The model is held to a tighter boundary than /edit-settings:

    Tier Keys the model may propose
    Model-writable temperature, top_p, top_k, max_tokens, context_window, enable_thinking, effort, thinking_type, cache_ttl, model
    Human-only (refused, hand-edit this file) mode, sandbox, sandbox_strict, sandbox_grants, sandbox_always_allow, git_host_grants, shell_allowlist (containment/trust); api_key, base_url, brave_api_key (secrets/endpoints); provider, wire_api, provider_preset, provider_tiers, providers, model_favorites, model_routes, model_assignments (presets/routes); reasoning_effort (cross-wire conflict — use effort which the picker translates per-serve)

    The model-writable list is an explicit positive allowlist — a key is refused until it’s deliberately added, so a future setting can’t silently become model-writable. read_settings masks every credential to [SET]/[NOT SET]. A proposed change goes through the same diff modal and applies to new sessions only (the live session’s mode/model are human-only — use /mode and /model). See Model-writable settings.

Global-only keys

These keys are honored from the global ~/.kin/settings.toml, the environment, or a CLI flag — but are stripped (with a one-line warning) from any project .kin/settings.toml:

base_url, api_key, mode, sandbox, sandbox_strict, sandbox_default,
sandbox_grants, sandbox_always_allow, git_host_grants, shell_allowlist,
session_dir, no_save, brave_api_key,
provider_preset, providers, provider_keys, provider_tiers, model_favorites,
model_routes, model_assignments, sandbox_network, ssh_hosts,
browser_allow_private, rig_url, rig_token, outpost_url, outpost_token

The reason is the threat model of a cloned repository. A project file you didn’t write could otherwise repoint your wire and leak your key (base_url + api_key), launch you straight into autonomous mode (mode), weaken or disable OS containment (sandbox, sandbox_strict, sandbox_network, the legacy sandbox_default, shell_allowlist), grant itself typed sandbox authority (sandbox_grants) or trusted Git credential use (git_host_grants), redirect the bearer-authenticated Rig or outpost/outpost-send tools to a hostile endpoint (rig_url / outpost_url), redirect where sessions land (session_dir, no_save, brave_api_key), or route your global api_key through a third-party endpoint (provider_preset + providers + provider_keys), or assign prompts and images to one of those endpoints (model_routes + model_assignments). Keeping them global-only means a checkout can’t silently retarget your endpoint, authorize its own remote route, route your key through an attacker-controlled host, or weaken your safety posture. sandbox_always_allow and ssh_hosts remain in the set only as inert migration-compatible data. The exact denylist and the layering rules are documented in the repo’s REFERENCE.md § Settings & config layering.

Secrets (api_key, provider_keys, brave_api_key, outpost_token, and rig_token) belong to Kin’s global credential store at ~/.kin/credentials.toml, which is created mode 0600 and never committed. Use Kin’s key prompts instead of editing it. A legacy secret in global settings.toml remains readable and migrates on the next settings write.