Configuration reference (knosh.json)¶
Knosh reads its global configuration from ~/.config/knosh/knosh.json and, optionally, a project-local configuration from .knosh.json in the current directory. When both files exist, their contents are merged: local values take precedence over global values. If a key is missing from both files, the default is used.
Run knosh init to create a file pre-populated with all defaults.
Options¶
agentsDir¶
Type: string
Default: ~/.config/knosh/agents
Path to the directory containing agent Markdown files. Knosh looks for <agentsDir>/<agentId>.md when an agent is referenced by ID.
~ and $HOME are expanded to the user's home directory.
commandsDir¶
Type: string
Default: ~/.config/knosh/commands
Path to the directory containing file-defined command Markdown files. Knosh loads every .md file in this directory at startup and registers each one as a subcommand.
~ and $HOME are expanded to the user's home directory.
defaultAgentId¶
Type: string or null
Default: none
Agent ID to use when a command does not specify one explicitly. When set, --agentId becomes optional for prompt, kdocs, and any file-defined command that does not declare agent: in its frontmatter. The explicit --agentId option always takes precedence when supplied.
The value must match an agent filename (without the .md extension) in the agents directory. Knosh validates that the agent exists at startup and exits with an error if the file is missing.
anthropicApiKey¶
Type: string or null
Default: none
API key for the Anthropic provider. Required to use models with model: "anthropic/..." in an agent configuration. If this is unset, Knosh falls back to the ANTHROPIC_API_KEY environment variable.
mistralApiKey¶
Type: string or null
Default: none
API key for the Mistral provider. Required to use models with model: "mistral/..." in an agent configuration. If this is unset, Knosh falls back to the MISTRAL_API_KEY environment variable.
Note
Mistral support is currently in beta.
ollamaURL¶
Type: string
Default: http://localhost:11434
Base URL of the Ollama server. Required to use models with model: "ollama/..." in an agent configuration. The default points to a locally running Ollama instance.
openAiApiKey¶
Type: string or null
Default: none
API key for the OpenAI provider. Required to use models with model: "openai/..." in an agent configuration. If this is unset, Knosh falls back to the OPENAI_API_KEY environment variable.
toolLimits¶
Type: object
Default: all sub-fields at their defaults (shown below)
Upper bounds on the size of tool responses. Each sub-field is an integer that must be greater than zero; a non-positive value makes Knosh exit at startup with a configuration error. Each field name carries its unit of measure.
| Field | Unit | Default | Controls |
|---|---|---|---|
globMaxFiles |
files | 100 |
Maximum files the glob tool returns before truncating |
grepMaxMatches |
matches | 100 |
Maximum matches the grep tool returns before truncating |
grepMaxLineLength |
characters | 100000 |
Maximum characters of a line the grep tool feeds to the regex matcher; longer lines are matched only within this prefix |
grepTimeoutMillis |
milliseconds | 5000 |
Wall-clock time budget for a single grep search; the search stops early and returns partial results with a note once exceeded |
textReadMaxBytes |
bytes | 51200 |
Maximum output bytes the text-read tool emits (50 KB) |
webFetchMaxBytes |
bytes | 131072 |
Maximum bytes of content the web-fetch tool returns (128 KB, ≈32K tokens) |
Because config files are merged at the level of top-level keys, a project-local toolLimits object replaces the global one entirely rather than merging field by field. Within a single toolLimits object, any omitted field falls back to its default.
"toolLimits": {
"globMaxFiles": 100,
"grepMaxMatches": 100,
"grepMaxLineLength": 100000,
"grepTimeoutMillis": 5000,
"textReadMaxBytes": 51200,
"webFetchMaxBytes": 131072
}
webFetch¶
Type: object
Default: {"allowedHosts": [], "allowInternalHosts": false}
SSRF egress policy for the web-fetch tool: an optional host allowlist and a toggle for blocking requests that resolve to internal network addresses.
| Field | Type | Default | Controls |
|---|---|---|---|
allowedHosts |
array of strings | [] |
The hosts web-fetch may reach, matched case-insensitively against the request URL's host. An empty list (the default) allows any host, subject to allowInternalHosts. A non-empty list refuses any host not present in it |
allowInternalHosts |
boolean | false |
When false, a request that resolves to a loopback, link-local (including the 169.254.169.254 cloud-metadata address), site-local, any-local, multicast, or IPv6 unique-local (fc00::/7) address is refused. Set to true to allow an agent to deliberately reach an internal resource — a local dev server, an intranet wiki; allowedHosts, if non-empty, still applies |
Every requested URL is checked against this policy, and so is every redirect hop the tool follows (up to an internal cap of 5), so a clean allowlisted URL cannot 302 into an internal address.
Because config files are merged at the level of top-level keys, a project-local webFetch object replaces the global one entirely rather than merging field by field. Within a single webFetch object, any omitted field falls back to its default.
Note
The allowlist is host-based, not domain-name based — subdomains are not implicitly included. The internal-address block is IP-range based (name-based blocklists are trivially bypassed by IP literals). See web-fetch's Security / SSRF section for the full list of blocked ranges and a known limitation around DNS rebinding.
Config file merging¶
When both a global and a local config exist, their JSON keys are merged before parsing. The local file's values win on any key that appears in both. This lets you set API keys globally and override individual settings (such as agentsDir) per project.
File permission advisory¶
A knosh.json that anyone on the system can modify undermines the trust that other settings — such as
the webFetch SSRF allowlist — are meant to provide: a local attacker who can write the
file can simply rewrite it. At startup, Knosh checks whether the global config file
(~/.config/knosh/knosh.json), its parent directory (~/.config/knosh/), the local config file
(.knosh.json), and its parent directory (the current working directory) are writable by other users
on the system, and prints a Warning: … line to stderr for each one that is.
This check is advisory only: Knosh does not refuse to start, and it does not change or repair the
file's permissions. It only flags the others-writable (world-writable) bit — group-writable files are
not flagged, since per-user private groups make that bit common and not necessarily a security issue.
The check is POSIX-only; on a filesystem with no POSIX permission view (such as Windows), it is a silent
no-op.
Note
The permission check and the actual config read happen as separate filesystem operations, so a
race is possible between the two (check-then-use, or TOCTOU). The warning is a best-effort signal
of an existing exposure, not a guarantee that the file read afterward is untampered — the same
caveat noted for DNS rebinding in the web-fetch SSRF guard.