Skip to content

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.

"webFetch": {
  "allowedHosts": ["example.com", "api.example.com"],
  "allowInternalHosts": false
}

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.

Example

{
  "agentsDir": "~/.config/knosh/agents",
  "anthropicApiKey": "sk-ant-...",
  "defaultAgentId": "my-default-agent",
  "ollamaURL": "http://localhost:11434",
  "toolLimits": {
    "webFetchMaxBytes": 131072
  }
}