# Configuration reference

> YAML config keys in `.ok/config.yml`, `~/.ok/global.yml`, and `.ok/local/config.yml`; precedence order; published JSON Schema paths; and environment-only variables.

- Repository: sashimikun/open-knowledge
- GitHub: https://github.com/sashimikun/open-knowledge
- Human docs: https://grok-wiki.com/public/docs/sashimikun-open-knowledge-5c45105c876e
- Complete Markdown: https://grok-wiki.com/public/docs/sashimikun-open-knowledge-5c45105c876e/llms-full.txt

## Source Files

- `packages/core/src/config/schema.ts`
- `packages/core/src/config/merge-layered.ts`
- `packages/core/src/config/validate-patch-scopes.ts`
- `packages/cli/scripts/build-config-schema.mjs`
- `packages/cli/src/commands/config.ts`
- `docs/content/reference/configuration.mdx`
- `.env.example`

---

---
title: "Configuration reference"
description: "YAML config keys in `.ok/config.yml`, `~/.ok/global.yml`, and `.ok/local/config.yml`; precedence order; published JSON Schema paths; and environment-only variables."
---

Open Knowledge stores typed YAML configuration in three scope-specific files under `.ok/` and `~/.ok/`. At runtime the editor and collaboration server merge layers with `mergeLayered` (scope-aware leaf resolution), validate writes with `validatePatchScopes`, and publish JSON Schema artifacts from `ConfigSchema` in `@inkeep/open-knowledge-core`. All config keys are human-only (`agentSettable: false`); agents cannot patch config through MCP tools.

## Config files

| Scope | Path | Git | Purpose |
| --- | --- | --- | --- |
| **User** | `~/.ok/global.yml` | No | Personal preferences across every project on this machine |
| **Project** | `.ok/config.yml` | Yes | Team-shared project defaults committed to the repo |
| **Project-local** | `.ok/local/config.yml` | No (gitignored) | Per-machine, per-project settings that must not sync |

All three files are optional. Missing files fall back to built-in defaults from `ConfigSchema.parse({})`.

<Note>
Embeddings API keys are **not** config keys. Store them with `ok embeddings set-key` in `~/.ok/secrets.yml` (mode `0600`), or set `OK_EMBEDDINGS_API_KEY` for scripted runs.
</Note>

## Precedence

Effective values resolve in two stages: **layer merge** for YAML config, then **environment and CLI overrides** for settings that have no `config.yml` key.

```text
Built-in defaults
  → ~/.ok/global.yml          (user)
  → .ok/config.yml            (project)
  → .ok/local/config.yml      (project-local)
  → environment variables     (env-only settings)
  → CLI flags                 (highest)
```

Within the YAML layers, `mergeLayered(user, project, projectLocal)` applies **scope-aware short-circuiting** at each leaf field:

| Scope | Reads from | Fallback when absent |
| --- | --- | --- |
| `user` | `~/.ok/global.yml` only | No fallback to lower layers |
| `project` | `.ok/config.yml` | `~/.ok/global.yml` |
| `project-local` | `.ok/local/config.yml` | `.ok/config.yml`, then `~/.ok/global.yml` |

Arrays replace wholesale at the highest defined layer; they are not concatenated. Setting a leaf to `null` in project-local clears that value. Keys placed in the wrong-scope file are **not used** for the effective merged config, even if YAML parsing succeeds.

<Warning>
`ok config validate` merges **user + project** YAML and checks schema validity and removed keys. It does not load project-local config. The editor and running server use all three layers via `mergeLayered`.
</Warning>

### Auto-sync resolution

Git auto-sync uses a dedicated two-step lookup outside the generic merge table:

1. If `autoSync.enabled` in `.ok/local/config.yml` is `true` or `false`, that value wins.
2. Otherwise, if project config is valid, `autoSync.default` in `.ok/config.yml` applies (`true` enables, `false` disables, `null` leaves onboarding to prompt).
3. If project-local config is invalid, the server logs a warning and falls back to the project default; if project config is also invalid, auto-sync defaults to **disabled**.

## JSON Schema artifacts

Schemas are generated at build time by `packages/cli/scripts/build-config-schema.mjs` from `ConfigSchema` and the field registry (`CONFIG_SCHEMA_MAJOR` is `0`, path segment `v0`).

### Published paths

| Artifact | Path in `@inkeep/open-knowledge` package |
| --- | --- |
| Full merged schema | `dist/config-schema.json` |
| Project scope | `dist/schemas/v0/config.project.schema.json` |
| User scope | `dist/schemas/v0/config.user.schema.json` |
| Project-local scope | `dist/schemas/v0/config.project-local.schema.json` |

Back-compat aliases also ship at the `dist/` root: `config.project.schema.json`, `config.user.schema.json`, `config.project-local.schema.json`.

### IDE `$schema` URLs

New config files receive a `yaml-language-server: $schema=` magic comment pointing at unpkg:

```yaml
# yaml-language-server: $schema=https://unpkg.com/@inkeep/open-knowledge@latest/dist/schemas/v0/config.project.schema.json
```

Per-scope URLs:

| Scope | Schema filename |
| --- | --- |
| Project | `config.project.schema.json` |
| User | `config.user.schema.json` |
| Project-local | `config.project-local.schema.json` |

Scope-pruned schemas include only fields whose `scope` metadata matches that file. The full `config-schema.json` includes every key for documentation and validation tooling.

## Config keys

The **Scope** column is authoritative: writes to the wrong file return `SCOPE_VIOLATION` from the Settings pane, `writeConfigPatch`, or `bindConfigDoc.patch`.

### `content`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `content.dir` | string | `"."` | project | Content root relative to the project directory (the folder containing `.ok/`). Exclude paths with `.okignore`. |

### `appearance`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `appearance.theme` | `"light"` \| `"dark"` \| `"system"` | (unset) | user | Editor color theme. |
| `appearance.preview.autoOpen` | boolean | `true` | user | When `true`, the agent opens or refreshes the live preview after each MCP edit. Set `false` to manage preview yourself. |
| `appearance.sidebar.showHiddenFiles` | boolean | `false` | project-local | Show dot-prefixed entries (`.ok/`, `.okignore`) in the file tree. |

### `editor`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `editor.wordWrap` | boolean | `true` | user | Soft-wrap long lines in source (CodeMirror) mode. |

### `autoSync`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `autoSync.enabled` | `boolean` \| `null` | `null` | project-local | Per-machine git auto-sync toggle. `null` means unanswered; onboarding prompts on first remote-detected open. |
| `autoSync.default` | `boolean` \| `null` | `null` | project | Committed default for a machine's first `autoSync.enabled`: `true` on, `false` off, `null` ask. A per-machine `autoSync.enabled` choice overrides this. |

### `terminal`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `terminal.enabled` | `boolean` \| `null` | `null` | project-local | Opt-out for the in-app terminal (real OS shell at full user privilege). Terminal is on by default; set `false` to disable for this project on this machine. Never shared via git, clone, or sync. |

### `telemetry`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `telemetry.localSink.enabled` | boolean | `true` | project | Write local diagnostic spans and logs under `.ok/local/` for `ok diagnose bundle`. Set `false` for sensitive workspaces. |
| `telemetry.localSink.spans.maxBytes` | number | `52428800` (~50 MB) | project | Max spans file size before rotation. |
| `telemetry.localSink.logs.maxBytes` | number | `26214400` (~25 MB) | project | Max logs file size before rotation. |
| `telemetry.localSink.attributeDenylist` | `string[]` | 8 credential keys | project | Attribute keys redacted to `[REDACTED]` before local span/log writes. Built-in denylist includes `authorization`, `auth.token`, `auth.bearer`, `cookie`, `set-cookie`, `x-api-key`, `password`, `secret`. |

### `search.semantic`

| Key | Type | Default | Scope | Description |
| --- | --- | --- | --- | --- |
| `search.semantic.enabled` | boolean | `false` | project-local | Add embeddings-based ranking to MCP `search`, fused with lexical results. **Content egress** when enabled and a key is set. |
| `search.semantic.baseUrl` | string | `"https://api.openai.com/v1"` | project-local | OpenAI-compatible embeddings API base URL. Override for Azure, self-hosted, or other providers. |
| `search.semantic.model` | string | `"text-embedding-3-small"` | project-local | Embeddings model id served at `baseUrl`. Changing it re-embeds the corpus. |
| `search.semantic.dimensions` | number | (native) | project-local | Optional output vector size. Omit for native dimensions (1536 for `text-embedding-3-small`). |
| `search.semantic.similarityFloor` | number (0–1) | (unset) | project-local | Optional hard cosine-similarity cutoff. Off by default; retrieval is rank-based. Set only when you know your provider's cosine scale. |

<Info>
Folder metadata (`title`, `description`, templates) lives in per-folder `.ok/frontmatter.yml` and `.ok/templates/`, not in `config.yml`. Path exclusions live in `.okignore`, not config.
</Info>

## Editing and validating config

<Steps>
<Step title="Choose an edit surface">

- **Settings pane** (Cmd/Ctrl-,): validates live against the scope-appropriate schema; blocks `SCOPE_VIOLATION` writes.
- **IDE**: edit the YAML file directly; use the `$schema` magic comment for autocomplete.
- **CLI**: `ok config validate` and `ok config migrate`.

</Step>
<Step title="Validate merged config">

```bash
ok config validate
```

On success, prints merged sources (user and project paths, or `defaults only`). On failure, prints `SCHEMA_INVALID` or `REMOVED_KEY` errors with file:line:column when available.

</Step>
<Step title="Remove deprecated keys">

```bash
ok config migrate
ok config migrate --scope project
ok config migrate --dry-run
```

Strips obsolete keys from `config.yml` and/or `global.yml`, including silently dropped legacy keys (`sync.*`, `persistence.*`, `server.port`) plus every entry in the `REMOVED_KEYS` registry.

</Step>
</Steps>

<AccordionGroup>
<Accordion title="Removed config keys and replacements">

| Removed path | Use instead |
| --- | --- |
| `content.include` | `content.dir` + `.okignore` |
| `content.exclude` | `.okignore` at project root |
| `folders` | `<folder>/.ok/frontmatter.yml` and `<folder>/.ok/templates/` |
| `appearance.editorModeDefault` | Editor mode button (always WYSIWYG on open) |
| `appearance.sidebar.showAllFiles` | `appearance.sidebar.showHiddenFiles` |
| `server.host` | `--host` flag or `HOST` env |
| `server.port` | `--port` flag or `PORT` env |
| `mcp.autoStart` | `OK_MCP_AUTOSTART=0` |
| `github.oauthAppClientId` | `OPEN_KNOWLEDGE_GITHUB_CLIENT_ID` |
| `preview.baseUrl` | `ok ui` / running UI process |
| `upload.maxBytes`, `mcp.tools.*.maxResults` | Hardcoded in core; not configurable |

Run `ok config migrate` to strip these automatically.

</Accordion>
</AccordionGroup>

## Environment-only variables

These settings have no `config.yml` key and no Settings toggle. CLI flags beat environment variables where both apply.

### Common

| Variable | Effect |
| --- | --- |
| `HOST` | Collaboration server bind host. `--host` wins. Default: `localhost`. |
| `PORT` | Server bind port when `--port` / `--ui-port` are absent. |
| `OK_MCP_AUTOSTART` | Set to `0` to disable MCP shim auto-starting `ok start` when no server lock exists. |
| `OK_LOG_LEVEL` | Log verbosity (`info`, `debug`, `trace`). Falls back to `LOG_LEVEL`. |
| `OK_MCP_SPAWN_TIMEOUT_MS` | Milliseconds to wait for MCP auto-spawned server startup (positive integer; default internal timeout is 5000 ms when unset). |

### Advanced / operator

| Variable | Effect |
| --- | --- |
| `OPEN_KNOWLEDGE_GITHUB_CLIENT_ID` | Override the bundled GitHub OAuth App client ID. |
| `OK_EMBEDDINGS_API_KEY` | Fallback embeddings API key when none is in `~/.ok/secrets.yml`. Prefer `ok embeddings set-key`. |
| `OK_SHOWALL_MAX_ENTRIES` | Max file-tree entries per directory level before truncation (default `50000`). |
| `OK_SEARCH_MAX_ENTRIES` | Max entries in the search corpus name-only tier before deepest-tail paths drop (default `50000`). |
| `OK_BRIDGE_TOLERANCE_TELEMETRY` | Set to `1` to record bridge-tolerance events in `.ok/local/tolerance-telemetry.jsonl` (opt-in, local-only, records doc paths in cleartext). |
| `OTEL_SDK_DISABLED` | Inverted gate for OTLP push telemetry. Set to `false` to **enable** push (off by default). |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP endpoint (default `http://localhost:4318`). |
| `OTEL_EXPORTER_OTLP_TIMEOUT` | OTLP export timeout in milliseconds. |

### Contributor / dev-only

These appear in `.env.example` for the monorepo dev server; they do not affect end-user `ok` CLI runtime the same way:

| Variable | Effect |
| --- | --- |
| `VITE_PORT` | Vite dev server port (default `5173`). Does not affect `ok start` / `ok ui` port resolution. |
| `VITE_OTEL_ENABLED` | Frontend OpenTelemetry instrumentation in the Vite app. |

## Semantic search quick reference

Semantic search is off by default and configured entirely in project-local config plus secrets:

1. `ok embeddings set-key` — store provider key in `~/.ok/secrets.yml`.
2. Set `search.semantic.enabled: true` in `.ok/local/config.yml`.
3. Optionally override `search.semantic.baseUrl`, `model`, `dimensions`, or `similarityFloor`.

When enabled with a key set, search queries and matching document content are sent to the configured embeddings provider. Search degrades silently to lexical ranking if the key is missing, the provider errors, or you are offline.

## Related pages

<CardGroup>
<Card title="Project scaffold" href="/project-scaffold">
`.ok/` layout, the three config scopes, `.okignore`, and `content.dir` semantics.
</Card>
<Card title="Semantic search setup" href="/semantic-search-setup">
Enable embeddings ranking, store API keys, and understand content-egress constraints.
</Card>
<Card title="CLI reference" href="/cli-reference">
`ok config validate`, `ok config migrate`, and global flags that override env config.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
`ok diagnose health`, `ok diagnose bundle`, and recovering from stale config or server state.
</Card>
</CardGroup>
