Configuration
The .ok/config.yml schema and environment variables.
Open Knowledge reads YAML config from three places:
- Project:
./.ok/config.yml(this project, committed to git) - User:
~/.ok/global.yml(every project on your machine) - Project-local:
./.ok/local/config.yml(this project on this machine; gitignored). Holds per-machine-per-project preferences such asautoSync.enabled. Maintained by the editor (auto-sync onboarding modal, sync popover, Settings pane Sync section); you don't normally hand-edit it.
All files are optional; defaults cover everything.
You can inspect and edit config three ways:
- Settings pane in the editor: Cmd/Ctrl-, or App menu → Settings…
- Your IDE:
.ok/config.ymlships with a$schemamagic comment for autocomplete and inline field descriptions - CLI:
ok config validatechecks the merged result and reports wrong-scope keys
Edits made anywhere reflect everywhere; an open Settings pane refreshes live.
Schema
The Scope column says which file a setting belongs in: project → .ok/config.yml (shared in git), user → ~/.ok/global.yml (personal, all projects), project-local → .ok/local/config.yml (this machine only, gitignored). Setting a key in the wrong-scope file is ignored; ok config validate reports it.
| Field | Type | Default | Scope | Description |
|---|---|---|---|---|
content.dir | string | "." | project | Content directory, relative to project root. Defaults to . (the project root) even when .ok/ is scaffolded at the git working-tree root from a sub-folder, so opened folder and content scope align by default. To narrow scope to a sub-folder, uncomment content.dir in .ok/config.yml post-init. Excluded paths live in .okignore; see Ignore patterns. |
appearance.theme | "light" | "dark" | "system" | (unset) | user | Editor theme. |
appearance.sidebar.showHiddenFiles | boolean | false | project-local | Show files whose path segments start with .. Server-side .gitignore / .okignore filters still apply. Toggled from the sidebar's right-click menu or the macOS View → Show Hidden Files item. |
appearance.sidebar.showAllFiles | boolean | false | project-local | Bypass every ignore filter, including both the client dot-segment drop and the server's .gitignore / .okignore / built-in exclusions. Surfaces every file on disk under the content directory (synthetic system docs stay hidden). Toggled from the sidebar's right-click menu or the macOS View → Show All Files item. |
autoSync.enabled | boolean | null | null | project-local | Per-machine git auto-sync toggle. null means "unanswered"; the editor's onboarding modal triggers on first remote-detected open. |
editor.wordWrap | boolean | true | user | Soft-wrap long lines in the source-mode CodeMirror editor. A personal preference, not project-shared. Toggle from the Settings pane. |
appearance.preview.autoOpen | boolean | true | user | Whether the agent should open or refresh the Open Knowledge preview when it edits a doc through the MCP. Default true lets the agent route the preview by host capability: the host's in-app browser (Cursor preview pane, Codex's built-in browser, Claude Code Desktop) when one exists, the system browser otherwise. Set false to keep the agent's hands off your preview window. This is useful when you're already viewing the doc in OK Desktop, a browser tab on a second display, a non-default browser, or any flow where your extensions / accessibility tooling only work in your own browser. The agent then surfaces the URL on request but does not navigate. The change takes effect on the next preview-related tool call. Toggle from Settings → Preferences → "Open preview when agent edits". |
telemetry.localSink.enabled | boolean | true | project | Write local diagnostic spans + logs under .ok/local/ for ok diagnose bundle to collect. Local-only: nothing leaves the machine until you run bundle. Set false for sensitive workspaces. |
telemetry.localSink.spans.maxBytes | number | 52428800 (~50 MB) | project | Max size of the local diagnostic spans file before it rotates. |
telemetry.localSink.logs.maxBytes | number | 26214400 (~25 MB) | project | Max size of the local diagnostic logs file before it rotates. |
telemetry.localSink.attributeDenylist | string[] | 8 credential keys | project | Attribute keys whose values are redacted ([REDACTED]) before any local span/log is written. Extends the built-in denylist (authorization, password, cookie, etc.). |
search.semantic.enabled | boolean | false | project-local | Add embeddings-based semantic ranking to the MCP search tool. Default off. When on and a key is set, the search query and matching page content are sent to the configured embeddings provider (content egress). See Semantic search below. |
search.semantic.baseUrl | string | "https://api.openai.com/v1" | project-local | Base URL of the OpenAI-compatible embeddings API. Override for Azure / self-hosted / other providers. The API key is not stored here — set it with ok embeddings set-key. |
search.semantic.model | string | "text-embedding-3-small" | project-local | Embeddings model id. Must be served by the provider at baseUrl. Changing it re-embeds the corpus. |
search.semantic.dimensions | number | (native) | project-local | Optional output vector size. Omit for the model's native size (1536 for text-embedding-3-small). Set a smaller value to shrink the on-disk cache, trading a little quality. |
Folder properties
A folder's own metadata lives in that folder's .ok/ directory, not in config.yml: its own open-shape frontmatter (any keys; title / description / tags are the conventional ones) in .ok/frontmatter.yml, and its templates in .ok/templates/. Folder properties describe only their own folder: they are not inherited by the docs inside it. (Templates do resolve leaf-to-root, so a root template is available in every subfolder.) Set them from the editor's Folder properties pane, or via the edit({ folder }) / write({ folder }) MCP tools. See Folders and templates for the full walkthrough.
Ignore patterns
Path exclusions live in a project-root .okignore file using gitignore syntax. .gitignore rules are honored automatically alongside it, and a leading ! re-includes a file .gitignore excluded. Edit patterns from the Ignore patterns section of the Settings pane, the right-click menu in the file tree, or by hand in any editor; the running server picks up changes without a restart. See Ignore patterns for the full UX.
Precedence
CLI flags (when running the bundled ok CLI) > environment variables > project-local config > project config > user config > defaults. Leaf values at higher levels override the same leaf below; arrays replace, they don't concatenate.
Environment variables
Most users never set these — the schema settings above cover the common cases. These have no config.yml key or Settings toggle; they are environment-only.
Common:
| Variable | Sets |
|---|---|
HOST | Server bind host. The --host flag wins over this. |
PORT | Server bind port. The --port flag wins over this. |
OK_MCP_AUTOSTART | Set to 0 to disable auto-starting the MCP server |
OK_LOG_LEVEL | Log verbosity (info, debug, trace). Falls back to LOG_LEVEL if unset. |
Advanced / operator:
| Variable | Sets |
|---|---|
OPEN_KNOWLEDGE_GITHUB_CLIENT_ID | Override the GitHub OAuth App client ID |
OK_SHOWALL_MAX_ENTRIES | Max entries the Show all files disk walk returns before it stops and marks the list truncated (default 50000) |
OTEL_SDK_DISABLED | OpenTelemetry OTLP push gate. Inverted sense: set to false to enable push (it is off by default). |
OK_EMBEDDINGS_API_KEY | Fallback embeddings provider API key for semantic search, used when none is stored on disk. Prefer ok embeddings set-key (writes ~/.ok/secrets.yml) for normal use; the env var is convenient for CI / scripted runs. |
Semantic search
The MCP search tool can fuse an embeddings-based semantic signal into its ranking, so an agent's query surfaces conceptually-related pages even when they share no keywords (a query about "auth retries" can surface a page titled "Session Token Refresh"). It is off by default and additive — with it off, search is byte-for-byte today's lexical ranking, and the cmd-K omnibar stays purely lexical and instant either way (semantic applies only to the agent-facing MCP tool).
Content egress. When semantic search is enabled and a key is set, the search query and the matching page content are sent to the configured embeddings provider (OpenAI by default). Only content that is already in your corpus is embedded — anything excluded by .okignore / .gitignore is never sent — and embedding is lazy: nothing leaves the machine until an agent actually runs a semantic search. The key lives only in a 0600 ~/.ok/secrets.yml file (never in config.yml, logs, or telemetry).
To turn it on (per machine):
- Store the provider key in
~/.ok/secrets.yml(0600, this machine only):ok embeddings set-key(reads the key from a hidden prompt or stdin). Check it withok embeddings status. - Set
search.semantic.enabled: truein project-local config (<project>/.ok/local/config.yml). - (Optional) point at a non-OpenAI provider via
search.semantic.baseUrl/model/dimensions.
The first semantic search kicks off a background embed of the corpus (cents for a whole vault with text-embedding-3-small); vectors are cached incrementally under .ok/local/ and only changed docs re-embed. If the key is missing, the provider errors, or you're offline, search silently degrades to lexical — it never blocks or errors. Each MCP search response reports embedding coverage so an agent knows when vectors are still filling in.
Verifying changes
The Settings pane validates .ok/config.yml against the schema as you edit and surfaces errors inline. The Ignore patterns section shows a live count of files each pattern matches, so you can confirm scope changes without leaving the editor.