# CKB Configuration Guide ## Overview CKB configuration is stored in `.ckb/config.json` in your repository root. This file is created when you run `ckb init`. > **Note:** The v6.0 Architectural Memory features (ownership, decisions, hotspots) are implemented but currently use sensible defaults. Configurable settings for these features are planned for a future release. See [v6.0 Configuration Roadmap](#v60-configuration-roadmap) below. ## Configuration File ### Location ``` your-repo/ └── .ckb/ ├── config.json # Configuration └── ckb.db # SQLite database ``` ### Global Registry (v7.3) CKB also maintains a global repository registry for multi-repo management: ``` ~/.ckb/ ├── repos.json # Repository registry └── repos.lock # Lock file for concurrent access ``` **repos.json format:** ```json { "version": 1, "repos": { "myproject": { "name": "myproject", "path": "/path/to/myproject", "added_at": "2025-12-22T10:30:00Z", "last_used_at": "2025-12-22T15:00:00Z" }, "api": { "name": "api", "path": "/path/to/api", "added_at": "2025-12-22T11:00:00Z" } }, "default": "myproject" } ``` **Managing repos:** ```bash ckb repo add myproject # Add cwd as "myproject" ckb repo add api /path/to/api # Add specific path ckb repo list # List all repos ckb repo default myproject # Set default ckb repo remove api # Remove ``` ### Full Schema (Current Implementation) ```json { "version": 5, "repoRoot": ".", "backends": { "scip": { "enabled": true, "indexPath": "index.scip" }, "lsp": { "enabled": true, "workspaceStrategy": "repo-root", "servers": {} }, "git": { "enabled": true } }, "queryPolicy": { "backendPreferenceOrder": ["scip", "glean", "lsp"], "alwaysUse": ["git"], "maxInFlightPerBackend": { "scip": 10, "lsp": 3, "git": 5 }, "coalesceWindowMs": 50, "mergeMode": "prefer-first", "supplementThreshold": 0.8, "timeoutMs": { "scip": 5000, "lsp": 15000, "git": 5000 } }, "lspSupervisor": { "maxTotalProcesses": 4, "queueSizePerLanguage": 10, "maxQueueWaitMs": 200 }, "modules": { "detection": "auto", "roots": [], "ignore": ["node_modules", "build", ".dart_tool", "vendor"] }, "importScan": { "enabled": true, "maxFileSizeBytes": 1000000, "scanTimeoutMs": 30000, "skipBinary": true, "customPatterns": {} }, "cache": { "queryTtlSeconds": 300, "viewTtlSeconds": 3600, "negativeTtlSeconds": 60 }, "budget": { "maxModules": 10, "maxSymbolsPerModule": 5, "maxImpactItems": 20, "maxDrilldowns": 5, "estimatedMaxTokens": 4000 }, "backendLimits": { "maxRefsPerQuery": 10000, "maxFilesScanned": 5000, "maxUnionModeTimeMs": 60000 }, "privacy": { "mode": "normal" }, "logging": { "level": "info", "format": "human" }, "daemon": { "port": 8181, "bind": "localhost" }, "webhooks": [] } ``` ## Configuration Sections ### version Schema version number. Current version is `5`. ```json { "version": 5 } ``` --- ### repoRoot Root directory for the repository. Usually `"."`. ```json { "repoRoot": "." } ``` --- ### tier (v7.2) Analysis tier mode. Controls which backends are used for analysis. | Value | Description | |-------|-------------| | `"auto"` | Auto-detect highest available tier (default) | | `"fast"` | Use tree-sitter only, ignore SCIP even if available | | `"standard"` | Require SCIP index | | `"full"` | Require SCIP + telemetry | ```json { "tier": "standard" } ``` **Precedence:** CLI `--tier` flag > `CKB_TIER` env var > config > auto-detect **Example use cases:** - Set `"tier": "fast"` for quick lookups in large repos - Set `"tier": "standard"` to ensure SCIP is always used - Use `--tier=fast` for a single command without changing config --- ### backends Configure which backends are enabled and their settings. #### backends.scip SCIP (Source Code Intelligence Protocol) backend. | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | true | Enable SCIP backend | | `indexPath` | string | "index.scip" | Path to SCIP index file | ```json { "backends": { "scip": { "enabled": true, "indexPath": "index.scip" } } } ``` #### backends.lsp Language Server Protocol backend. | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | true | Enable LSP backend | | `workspaceStrategy` | string | "repo-root" | How to initialize workspace | | `servers` | object | {...} | Language-specific server configs | **Default servers configured:** - `go`: gopls - `typescript`: typescript-language-server - `dart`: dart language-server - `python`: pylsp ```json { "backends": { "lsp": { "enabled": true, "workspaceStrategy": "repo-root", "servers": { "go": { "command": "gopls", "args": [] }, "typescript": { "command": "typescript-language-server", "args": ["--stdio"] }, "dart": { "command": "dart", "args": ["language-server"] }, "python": { "command": "pylsp", "args": [] } } } } } ``` #### backends.git Git backend for blame, history, and fallback operations. | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | true | Enable Git backend | --- ### queryPolicy Controls how queries are routed to backends and how results are merged. | Field | Type | Default | Description | |-------|------|---------|-------------| | `backendPreferenceOrder` | string[] | ["scip", "glean", "lsp"] | Backend priority order | | `alwaysUse` | string[] | ["git"] | Backends to always query | | `maxInFlightPerBackend` | object | {...} | Max concurrent queries per backend | | `coalesceWindowMs` | int | 50 | Window for coalescing similar queries | | `mergeMode` | string | "prefer-first" | How to merge results | | `supplementThreshold` | float | 0.8 | When to supplement with additional backends | | `timeoutMs` | object | {...} | Timeout per backend in milliseconds | **Merge Modes:** - `prefer-first`: Use first successful backend response - `union`: Merge all backend responses, deduplicate > **⚠️ Resilience Note:** In `prefer-first` mode, only the primary backend is queried. If it fails, the query fails—there is no automatic fallback to secondary backends. For maximum resilience (e.g., when SCIP index may be stale), use `union` mode which queries all backends in parallel. ```json { "queryPolicy": { "backendPreferenceOrder": ["scip", "lsp"], "alwaysUse": ["git"], "maxInFlightPerBackend": { "scip": 10, "lsp": 3, "git": 5 }, "coalesceWindowMs": 50, "mergeMode": "prefer-first", "supplementThreshold": 0.8, "timeoutMs": { "scip": 5000, "lsp": 15000, "git": 5000 } } } ``` --- ### lspSupervisor Controls LSP server lifecycle and resource management. | Field | Type | Default | Description | |-------|------|---------|-------------| | `maxTotalProcesses` | int | 4 | Max LSP processes across all languages | | `queueSizePerLanguage` | int | 10 | Max queued requests per language | | `maxQueueWaitMs` | int | 200 | Max time to wait in queue | ```json { "lspSupervisor": { "maxTotalProcesses": 4, "queueSizePerLanguage": 10, "maxQueueWaitMs": 200 } } ``` --- ### modules Module detection settings. | Field | Type | Default | Description | |-------|------|---------|-------------| | `detection` | string | "auto" | Detection strategy | | `roots` | string[] | [] | Additional module roots to include | | `ignore` | string[] | [...] | Directories to ignore | **Detection Strategies:** - `auto`: Detect based on language markers (go.mod, package.json, etc.) - `manual`: Only use specified roots - `directory`: Treat each top-level directory as a module **Default ignore patterns:** - `node_modules` - `build` - `.dart_tool` - `vendor` ```json { "modules": { "detection": "auto", "roots": ["internal/legacy"], "ignore": ["node_modules", "build", ".dart_tool", "vendor", "dist"] } } ``` --- ### importScan Import/dependency scanning settings. | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | true | Enable import scanning | | `maxFileSizeBytes` | int | 1000000 | Skip files larger than this (1 MB) | | `scanTimeoutMs` | int | 30000 | Timeout for scanning (30s) | | `skipBinary` | bool | true | Skip binary files | | `customPatterns` | object | {} | Custom import patterns by language | ```json { "importScan": { "enabled": true, "maxFileSizeBytes": 1000000, "scanTimeoutMs": 30000, "skipBinary": true, "customPatterns": {} } } ``` --- ### cache Cache tier configuration. | Field | Type | Default | Description | |-------|------|---------|-------------| | `queryTtlSeconds` | int | 300 | Query cache TTL (5 min) | | `viewTtlSeconds` | int | 3600 | View cache TTL (1 hour) | | `negativeTtlSeconds` | int | 60 | Negative cache TTL (1 min) | ```json { "cache": { "queryTtlSeconds": 300, "viewTtlSeconds": 3600, "negativeTtlSeconds": 60 } } ``` --- ### budget Response budget limits for LLM optimization. | Field | Type | Default | Description | |-------|------|---------|-------------| | `maxModules` | int | 10 | Max modules in response | | `maxSymbolsPerModule` | int | 5 | Max symbols per module | | `maxImpactItems` | int | 20 | Max impact items | | `maxDrilldowns` | int | 5 | Max drilldown suggestions | | `estimatedMaxTokens` | int | 4000 | Target token budget | ```json { "budget": { "maxModules": 10, "maxSymbolsPerModule": 5, "maxImpactItems": 20, "maxDrilldowns": 5, "estimatedMaxTokens": 4000 } } ``` --- ### backendLimits Hard limits to protect against resource exhaustion. | Field | Type | Default | Description | |-------|------|---------|-------------| | `maxRefsPerQuery` | int | 10000 | Max references per query | | `maxFilesScanned` | int | 5000 | Max files to scan | | `maxUnionModeTimeMs` | int | 60000 | Max time for union merge (60s) | ```json { "backendLimits": { "maxRefsPerQuery": 10000, "maxFilesScanned": 5000, "maxUnionModeTimeMs": 60000 } } ``` --- ### privacy Privacy settings. | Field | Type | Default | Description | |-------|------|---------|-------------| | `mode` | string | "normal" | Privacy mode | **Privacy Modes:** - `normal`: Full output with paths and symbols - `redacted`: Paths and symbol names are hashed ```json { "privacy": { "mode": "normal" } } ``` --- ### logging Logging configuration. | Field | Type | Default | Description | |-------|------|---------|-------------| | `level` | string | "info" | Log level (debug, info, warn, error) | | `format` | string | "human" | Output format (human, json) | ```json { "logging": { "level": "info", "format": "human" } } ``` --- ### daemon (v6.2) Background daemon service configuration for file watching, scheduled refreshes, and webhooks. | Field | Type | Default | Description | |-------|------|---------|-------------| | `port` | int | 8181 | HTTP port for daemon | | `bind` | string | "localhost" | Bind address | | `logLevel` | string | "info" | Daemon-specific log level | | `logFile` | string | "" | Optional log file path | #### daemon.auth | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | false | Enable authentication | | `token` | string | "" | Auth token (inline) | | `tokenFile` | string | "" | Path to token file | #### daemon.watch | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | true | Enable file watching | | `debounceMs` | int | 500 | Debounce delay in milliseconds | | `ignorePatterns` | string[] | [...] | Patterns to ignore | | `repos` | string[] | [] | Additional repos to watch | #### daemon.schedule | Field | Type | Default | Description | |-------|------|---------|-------------| | `refresh` | string | "0 3 * * *" | Cron for architecture refresh | | `federationSync` | string | "0 */6 * * *" | Cron for federation sync | | `hotspotSnapshot` | string | "0 2 * * 0" | Cron for hotspot snapshots | ```json { "daemon": { "port": 8181, "bind": "localhost", "logLevel": "info", "logFile": "/var/log/ckb/daemon.log", "auth": { "enabled": true, "tokenFile": "/etc/ckb/token" }, "watch": { "enabled": true, "debounceMs": 500, "ignorePatterns": ["*.log", "*.tmp"] }, "schedule": { "refresh": "0 3 * * *", "federationSync": "0 */6 * * *", "hotspotSnapshot": "0 2 * * 0" } } } ``` --- ### webhooks (v6.2.1) Configure webhooks for event notifications. Each webhook is an object in the `webhooks` array. | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Unique identifier for the webhook | | `url` | string | Yes | Endpoint URL | | `secret` | string | No | HMAC secret for signature verification | | `events` | string[] | Yes | Events to subscribe to | | `format` | string | No | Payload format ("json" or "text") | | `headers` | object | No | Additional HTTP headers | **Supported events:** - `refresh.started`, `refresh.completed`, `refresh.failed` - `index.updated` - `federation.synced` - `hotspot.detected` ```json { "webhooks": [ { "id": "slack-notifications", "url": "https://hooks.slack.com/services/...", "events": ["refresh.completed", "refresh.failed"], "format": "json" }, { "id": "ci-webhook", "url": "https://ci.example.com/ckb-webhook", "secret": "your-hmac-secret", "events": ["index.updated"], "headers": { "X-Custom-Header": "value" } } ] } ``` --- ### telemetry (v6.4) Runtime telemetry integration for observed usage and dead code detection. See [[Telemetry]] for full documentation including OTEL Collector setup, coverage levels, and CLI commands. | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | false | Enable telemetry features | | `serviceMap` | object | {} | Service name → repo ID mapping | | `servicePatterns` | array | [] | Regex patterns for service mapping | | `aggregation` | object | {...} | Aggregation settings | | `deadCode` | object | {...} | Dead code detection settings | | `privacy` | object | {...} | Privacy settings | **Basic enablement:** ```json { "telemetry": { "enabled": true, "serviceMap": { "api-gateway": "repo-api", "user-service": "repo-users" } } } ``` **Full schema:** ```json { "telemetry": { "enabled": true, "serviceMap": { "service-name": "repo-id" }, "servicePatterns": [ { "pattern": "^order-.*$", "repo": "repo-orders" } ], "aggregation": { "bucketSize": "weekly", "retentionDays": 180 }, "deadCode": { "enabled": true, "minObservationDays": 90 }, "privacy": { "redactCallerNames": false, "logUnmatchedEvents": true } } } ``` --- ### docs (v7.3) Configure documentation indexing for doc-symbol linking. See [[Doc-Symbol Linking]] for full documentation. | Field | Type | Default | Description | |-------|------|---------|-------------| | `paths` | []string | ["docs", "README.md", ...] | Directories and files to scan | | `include` | []string | ["*.md"] | Glob patterns to include | | `exclude` | []string | ["node_modules", ...] | Glob patterns to exclude | **Default paths scanned:** - `docs/` - `README.md` - `ARCHITECTURE.md` - `DESIGN.md` - `CONTRIBUTING.md` **Default exclude patterns:** - `node_modules` - `vendor` - `.git` - `dist` - `build` ```json { "docs": { "paths": ["docs", "README.md", "ARCHITECTURE.md", "DESIGN.md", "CONTRIBUTING.md"], "include": ["*.md", "*.markdown"], "exclude": ["node_modules", "vendor", ".git"] } } ``` **Example: Custom documentation structure** ```json { "docs": { "paths": ["documentation", "wiki", "*.md"], "include": ["*.md"], "exclude": ["node_modules", "vendor", ".git", "examples"] } } ``` **Example: Only check specific docs** ```json { "docs": { "paths": ["docs/api", "README.md"], "include": ["*.md"] } } ``` --- ## Index Server Configuration (v7.3) The index server is configured via a separate TOML file, not the main `config.json`. This enables serving symbol indexes over HTTP for remote federation clients. For authentication configuration (scoped tokens, rate limiting), see [[Authentication]]. ### Enabling Index Server Mode ```bash # Start server with index-serving endpoints ckb serve --index-server --index-config /path/to/index-server.toml ``` ### Configuration File Schema ```toml [index_server] enabled = true max_page_size = 10000 cursor_secret = "your-secret-key-here" [[repos]] id = "company/core-lib" name = "Core Library" path = "/repos/core-lib" description = "Shared utilities and common code" [[repos]] id = "company/api" name = "API Service" path = "/repos/api" [repos.privacy] expose_paths = true expose_docs = false expose_signatures = false path_prefix_strip = "/home/build/" [default_privacy] expose_paths = true expose_docs = true expose_signatures = true ``` ### Section: index_server | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | bool | false | Enable index-serving endpoints | | `max_page_size` | int | 10000 | Maximum items per page for pagination | | `cursor_secret` | string | (auto) | HMAC secret for cursor signing (auto-generated if omitted) | | `data_dir` | string | `~/.ckb-server` | Server data directory for uploaded repos (Phase 2) | | `max_upload_size` | int | 524288000 | Maximum upload size in bytes (500MB default, Phase 2) | | `allow_create_repo` | bool | true | Allow creating repos via upload API (Phase 2) | | `enable_compression` | bool | true | Accept gzip/zstd compressed uploads (Phase 3) | | `supported_encodings` | array | ["gzip", "zstd"] | Supported Content-Encoding values (Phase 3) | | `enable_delta_upload` | bool | true | Enable incremental delta uploads (Phase 3) | | `delta_threshold_percent` | int | 50 | Suggest full upload when >N% files changed (Phase 3) | ### Section: repos (array) Each repository to serve is defined as a `[[repos]]` entry: | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Repository identifier (e.g., "company/core-lib") | | `name` | string | No | Human-readable display name | | `path` | string | Yes | Absolute path to repository with `.ckb/` directory | | `description` | string | No | Repository description | | `privacy` | object | No | Per-repo privacy settings (overrides default_privacy) | ### Section: default_privacy / repos.privacy Privacy settings control what information is exposed in API responses: | Field | Type | Default | Description | |-------|------|---------|-------------| | `expose_paths` | bool | true | Include full file paths in responses | | `expose_docs` | bool | true | Include documentation strings | | `expose_signatures` | bool | true | Include function signatures | | `path_prefix_strip` | string | "" | Strip this prefix from all paths | ### Privacy Examples **Full exposure (default):** ```toml [default_privacy] expose_paths = true expose_docs = true expose_signatures = true ``` **Minimal exposure (paths only):** ```toml [default_privacy] expose_paths = true expose_docs = false expose_signatures = false ``` **Strip build paths:** ```toml [repos.privacy] expose_paths = true path_prefix_strip = "/home/build/workspace/" # "/home/build/workspace/src/main.go" becomes "src/main.go" ``` ### Complete Example ```toml # index-server.toml [index_server] enabled = true max_page_size = 5000 cursor_secret = "your-hmac-secret-key" # Core library - fully exposed [[repos]] id = "company/core-lib" name = "Core Library" path = "/code/core-lib" description = "Shared utilities and common code" # API service - hide docs and signatures [[repos]] id = "company/api" name = "API Service" path = "/code/api-service" [repos.privacy] expose_paths = true expose_docs = false expose_signatures = false path_prefix_strip = "/code/" # Internal service - minimal exposure [[repos]] id = "company/internal" name = "Internal Service" path = "/code/internal-service" [repos.privacy] expose_paths = false expose_docs = false expose_signatures = false ``` ### Upload Mode Example (Phase 2) For index server mode that accepts uploads via HTTP API: ```toml # index-server-upload.toml [index_server] enabled = true max_page_size = 10000 data_dir = "~/.ckb-server" # Where uploaded repos are stored max_upload_size = 524288000 # 500MB max upload allow_create_repo = true # Auto-create repos on first upload # Phase 3: Enhanced uploads enable_compression = true # Accept gzip/zstd compressed uploads supported_encodings = ["gzip", "zstd"] enable_delta_upload = true # Enable incremental delta uploads delta_threshold_percent = 50 # Suggest full upload if >50% files changed # No [[repos]] section needed - repos are created via API upload [default_privacy] expose_paths = true expose_docs = true expose_signatures = true ``` ### Security Considerations 1. **Cursor Secret**: If not provided, a random secret is generated at startup. For multi-instance deployments, set the same `cursor_secret` on all instances. 2. **Read-Only Mode**: The index server opens all databases in read-only mode for safety. 3. **Network Binding**: Use `--host` to control binding: ```bash # Local only (default) ckb serve --index-server --host localhost # All interfaces (use with caution) ckb serve --index-server --host 0.0.0.0 ``` 4. **Authentication**: Use `--auth-token` or `CKB_AUTH_TOKEN` for simple authentication. For scoped tokens and rate limiting, configure the `[auth]` section in your `--index-config` TOML file. See [[Authentication]]. See [[Federation]] for more details on Remote Index Serving use cases. --- ## CLI Command Flags Each CLI command has specific flags. Use `--help` to see all options: ```bash ckb --help # Global help ckb search --help # Search command help ckb serve --help # Server command help ``` ### Common Command Flags #### `ckb search` | Flag | Default | Description | |------|---------|-------------| | `--scope` | "" | Limit to module ID | | `--kinds` | "" | Filter by kinds (comma-separated) | | `--limit` | 20 | Max results | | `--format` | "human" | Output format (human, json) | #### `ckb refs` | Flag | Default | Description | |------|---------|-------------| | `--format` | "human" | Output format (human, json) | #### `ckb impact` | Flag | Default | Description | |------|---------|-------------| | `--format` | "human" | Output format (human, json) | #### `ckb arch` | Flag | Default | Description | |------|---------|-------------| | `--format` | "human" | Output format (human, json) | | `--depth` | 1 | Dependency depth | #### `ckb serve` | Flag | Default | Description | |------|---------|-------------| | `--port` | 8080 | HTTP port | | `--host` | "localhost" | Bind address | | `--auth-token` | "" | Auth token for mutating requests | | `--cors-allow` | "" | Comma-separated allowed CORS origins | | `--index-server` | false | Enable index-serving endpoints (v7.3) | | `--index-config` | "" | Path to index server config file (TOML) (v7.3) | ### Load Shedding (v7.3) Load shedding protects the server under heavy load by queuing and rejecting excess requests. Disabled by default. **Configuration in config.json:** ```json { "loadShedding": { "enabled": true, "maxConcurrentRequests": 100, "queueSize": 50, "queueTimeoutMs": 5000, "priorityEndpoints": ["/health", "/ready", "/metrics", "/symbol/", "/search"], "retryAfterSeconds": 5 } } ``` | Setting | Default | Description | |---------|---------|-------------| | `enabled` | false | Enable load shedding | | `maxConcurrentRequests` | 100 | Max concurrent requests before queuing | | `queueSize` | 50 | Max requests waiting in queue | | `queueTimeoutMs` | 5000 | How long to wait in queue (ms) | | `priorityEndpoints` | [...] | Endpoints that bypass load shedding | | `retryAfterSeconds` | 5 | Value for Retry-After header | **Behavior:** - Requests beyond `maxConcurrentRequests` enter a queue - If queue is full or timeout expires, returns `503 Service Unavailable` - Priority endpoints (`/health`, `/ready`, `/metrics`) always proceed - Response includes `Retry-After` header **Adaptive Mode:** For latency-aware shedding, the adaptive shedder tracks response times and sheds earlier when latency exceeds targets: ```json { "loadShedding": { "enabled": true, "adaptive": true, "targetLatencyMs": 100 } } ``` #### `ckb diag` | Flag | Default | Description | |------|---------|-------------| | `--out` | "" | Output file path | | `--anonymize` | false | Anonymize paths and symbols | #### `ckb config` (v7.5) View and manage CKB configuration. ```bash # Show current configuration ckb config show # Show as JSON ckb config show --format=json # Show only non-default values ckb config show --diff # List all supported environment variables ckb config env # Set a configuration value ckb config set scip.indexPath index.scip # Get a configuration value ckb config get scip.indexPath ``` | Subcommand | Description | |------------|-------------| | `show` | Display current configuration | | `env` | List all supported environment variables | | `set` | Set a configuration value in .ckb/config.json | | `get` | Get a configuration value | **`config set` supported keys:** | Key | Type | Description | |-----|------|-------------| | `scip.indexPath` | string | Path to SCIP index file (default: index.scip) | ```bash # Change SCIP index location ckb config set scip.indexPath .scip/index.scip # Use root default (Sourcegraph standard) ckb config set scip.indexPath index.scip ``` **`config get` example:** ```bash $ ckb config get scip.indexPath scip.indexPath: index.scip ``` **`config show` flags:** | Flag | Default | Description | |------|---------|-------------| | `--format` | "human" | Output format (human, json) | | `--diff` | false | Only show non-default values | **Example output:** ``` CKB Configuration ────────────────────────────────────────────────── Source: .ckb/config.json Environment Overrides: CKB_LOG_LEVEL=debug → logging.level CKB_BUDGET_MAX_MODULES=50 → budget.maxModules version: 5 tier: auto backends: scip.enabled: true scip.indexPath: index.scip lsp.enabled: true git.enabled: true cache: queryTtlSeconds: 300 viewTtlSeconds: 3600 negativeTtlSeconds: 60 budget: maxModules: 50 (default: 10) maxSymbolsPerModule: 5 ... logging: level: debug (default: info) format: human Use 'ckb config show --json' for full configuration Use 'ckb config env' to see supported environment variables ``` **JSON output format:** ```json { "configPath": ".ckb/config.json", "usedDefaults": false, "envOverrides": [ { "envVar": "CKB_LOG_LEVEL", "path": "logging.level", "fromValue": "debug" } ], "config": { "version": 5, "tier": "", "backends": { ... }, ... } } ``` --- ## Environment Variables Configuration can be overridden with environment variables. Environment variable overrides are applied **after** loading the config file, allowing you to customize settings without modifying `config.json`. ### General Variables | Variable | Type | Description | |----------|------|-------------| | `CKB_CONFIG_PATH` | string | Path to custom config file | | `CKB_TIER` | string | Analysis tier mode (fast, standard, full, auto) | | `CKB_REPO` | string | Repository path for Claude Desktop (no project context) | | `CKB_NO_UPDATE_CHECK` | bool | Disable update notifications (set to any value) | | `CKB_AUTH_TOKEN` | string | Auth token for serve command | ### Logging | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_LOG_LEVEL` | `logging.level` | string | Log level (debug, info, warn, error) | | `CKB_LOG_FORMAT` | `logging.format` | string | Log format (human, json) | > **Note:** `CKB_LOGGING_LEVEL` and `CKB_LOGGING_FORMAT` are also supported as aliases. ### Cache | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_CACHE_QUERY_TTL_SECONDS` | `cache.queryTtlSeconds` | int | Query cache TTL in seconds | | `CKB_CACHE_VIEW_TTL_SECONDS` | `cache.viewTtlSeconds` | int | View cache TTL in seconds | | `CKB_CACHE_NEGATIVE_TTL_SECONDS` | `cache.negativeTtlSeconds` | int | Negative cache TTL in seconds | ### Budget | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_BUDGET_MAX_MODULES` | `budget.maxModules` | int | Max modules in response | | `CKB_BUDGET_MAX_SYMBOLS_PER_MODULE` | `budget.maxSymbolsPerModule` | int | Max symbols per module | | `CKB_BUDGET_MAX_IMPACT_ITEMS` | `budget.maxImpactItems` | int | Max impact items | | `CKB_BUDGET_MAX_DRILLDOWNS` | `budget.maxDrilldowns` | int | Max drilldown suggestions | | `CKB_BUDGET_ESTIMATED_MAX_TOKENS` | `budget.estimatedMaxTokens` | int | Target token budget | ### Backends | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_BACKENDS_SCIP_ENABLED` | `backends.scip.enabled` | bool | Enable SCIP backend | | `CKB_BACKENDS_LSP_ENABLED` | `backends.lsp.enabled` | bool | Enable LSP backend | | `CKB_BACKENDS_GIT_ENABLED` | `backends.git.enabled` | bool | Enable Git backend | ### Daemon | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_DAEMON_PORT` | `daemon.port` | int | Daemon HTTP port | | `CKB_DAEMON_BIND` | `daemon.bind` | string | Daemon bind address | ### Other | Variable | Config Path | Type | Description | |----------|-------------|------|-------------| | `CKB_TELEMETRY_ENABLED` | `telemetry.enabled` | bool | Enable telemetry features | | `CKB_PRIVACY_MODE` | `privacy.mode` | string | Privacy mode (normal, redacted) | ### Example Usage ```bash # Override budget for a large codebase CKB_BUDGET_MAX_MODULES=50 ckb arch # Debug logging for troubleshooting CKB_LOG_LEVEL=debug ckb serve # Use custom config file in CI CKB_CONFIG_PATH=/etc/ckb/config.json ckb mcp # Disable SCIP for quick tree-sitter only analysis CKB_BACKENDS_SCIP_ENABLED=false ckb search Engine # Run daemon on different port CKB_DAEMON_PORT=9090 CKB_DAEMON_BIND=0.0.0.0 ckb serve ``` ### Precedence Configuration is loaded in this order (later sources override earlier): 1. Default values (built into CKB) 2. `.ckb/config.json` file 3. Environment variables 4. CLI flags (where applicable) ### Update Check (v7.4) CKB automatically checks for updates once per day using the GitHub Releases API. This works for **all installation methods** (npm, Homebrew, go install, binary download). **How it works:** - Uses **deferred notification pattern** — notification shown at command START from cache (instant) - Background refresh updates cache for next run (no HTTP during command execution) - Caches results for 24 hours in `~/.ckb/update-check.json` - Has a 3-second timeout (fails silently if network is slow/unavailable) - Skips `mcp` and `serve` commands to avoid breaking protocols **Smart upgrade message:** - npm installs: Shows `npm update -g @tastehub/ckb` - Homebrew installs: Shows `brew upgrade ckb` - Other installs: Shows GitHub releases URL **Disable update checks:** ```bash export CKB_NO_UPDATE_CHECK=1 ``` **Example notification (npm):** ``` ╭─────────────────────────────────────────────────────╮ │ Update available: 7.3.0 → 7.4.0 │ │ Run: npm update -g @tastehub/ckb │ ╰─────────────────────────────────────────────────────╯ ``` **Example notification (go install / binary):** ``` ╭─────────────────────────────────────────────────────╮ │ Update available: 7.3.0 → 7.4.0 │ │ https://github.com/SimplyLiz/CodeMCP/releases │ ╰─────────────────────────────────────────────────────╯ ``` --- ## Examples ### Minimal Configuration ```json { "version": 5, "backends": { "scip": { "enabled": true }, "lsp": { "enabled": false }, "git": { "enabled": true } } } ``` ### SCIP-Only (Fastest) ```json { "version": 5, "backends": { "scip": { "enabled": true }, "lsp": { "enabled": false }, "git": { "enabled": true } }, "queryPolicy": { "backendPreferenceOrder": ["scip"], "alwaysUse": ["git"], "mergeMode": "prefer-first" } } ``` ### Large Codebase ```json { "version": 5, "budget": { "maxModules": 20, "maxSymbolsPerModule": 10, "maxImpactItems": 50, "estimatedMaxTokens": 8000 }, "backendLimits": { "maxRefsPerQuery": 50000, "maxFilesScanned": 20000 }, "cache": { "queryTtlSeconds": 600, "viewTtlSeconds": 7200 } } ``` ### Privacy-Focused ```json { "version": 5, "privacy": { "mode": "redacted" }, "logging": { "level": "warn" } } ``` --- ## MODULES.toml Format The `MODULES.toml` file allows you to explicitly declare module boundaries and metadata. Place this file in your repository root. > **Note:** Module declarations in MODULES.toml take priority over auto-detection and provide higher confidence scores. ### Schema Version ```toml # MODULES.toml - Explicit module declarations for CKB version = 1 ``` ### Complete Example ```toml version = 1 [[module]] name = "api" path = "internal/api" responsibility = "HTTP API handlers and middleware" owner = "@api-team" tags = ["core", "api"] language = "go" [module.boundaries] exports = ["Handler", "Middleware", "Router"] internal = ["internal/api/internal", "internal/api/helpers"] allowed_dependencies = ["internal/query", "internal/storage"] [[module]] name = "query" path = "internal/query" responsibility = "Query engine for code intelligence" owner = "@platform-team" tags = ["core", "query"] [[module]] name = "storage" path = "internal/storage" responsibility = "Database operations and persistence" owner = "@platform-team" tags = ["core", "database"] [module.boundaries] exports = ["Repository", "Query", "Transaction"] internal = ["internal/storage/schema"] ``` ### Module Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `path` | string | **Yes** | Repo-relative path to the module root | | `name` | string | No | Human-readable name (defaults to last path segment) | | `id` | string | No | Stable module ID (auto-generated if omitted) | | `responsibility` | string | No | One-sentence description of what this module does | | `owner` | string | No | Primary owner (@team or user@email.com) | | `tags` | string[] | No | Classification tags for filtering | | `language` | string | No | Primary language (auto-detected if omitted) | ### Boundaries Section The optional `[module.boundaries]` section defines the module's API surface: | Field | Type | Description | |-------|------|-------------| | `exports` | string[] | Symbol names that form the public API | | `internal` | string[] | Paths considered internal/private | | `allowed_dependencies` | string[] | Modules this module is allowed to depend on | ### Minimal Example For simple cases, you only need the `path` field: ```toml version = 1 [[module]] path = "internal/api" [[module]] path = "internal/query" [[module]] path = "pkg/utils" ``` ### Generated Module IDs When `id` is not specified, CKB generates a stable ID: ``` ckb:mod: ``` The hash is derived from the normalized module path, ensuring the ID remains stable as long as the path doesn't change. ### Benefits of Explicit Declaration 1. **Higher confidence** - Declared modules have confidence 1.0 vs 0.5-0.7 for inferred 2. **Preserved on refresh** - Declared data is never overwritten by inference 3. **Better ownership** - Explicit owners override git-blame heuristics 4. **Clearer boundaries** - Public/internal patterns define module contracts 5. **Dependency control** - `allowed_dependencies` enables future dependency violation detection ### Validation Validate your MODULES.toml: ```bash ckb doctor ``` CKB validates: - Required `path` field is present - Paths exist in the repository - TOML syntax is correct --- ## Architectural Decision Records (ADRs) CKB includes a complete ADR system for documenting architectural decisions. ADRs are stored as markdown files and indexed for search. ### What is an ADR? An **Architectural Decision Record (ADR)** documents a significant decision made about the system architecture, including: - The context and problem being addressed - The decision made - The consequences of that decision - Alternatives that were considered ### ADR Storage Locations CKB looks for ADRs in these directories (in priority order): 1. `docs/decisions/` 2. `docs/adr/` 3. `adr/` 4. `decisions/` 5. `doc/adr/` 6. `doc/decisions/` When creating new ADRs via the API/MCP, they are stored in: - `~/.ckb/repos//decisions/` (v6.0 global persistence) ### ADR File Format ADRs are markdown files with a specific structure: ```markdown # ADR-001: Use PostgreSQL for primary database **Status:** accepted **Date:** 2024-12-18 **Author:** @platform-team ## Context We need a primary database for the application. The database must support: - ACID transactions - Complex queries with JOINs - JSON column types for flexible data ## Decision We will use PostgreSQL 15 as our primary database. ## Consequences - PostgreSQL provides robust ACID compliance - JSON/JSONB columns allow schema flexibility - Requires PostgreSQL expertise on the team - Need to manage database migrations ## Affected Modules - internal/storage - internal/api - cmd/migrate ## Alternatives Considered - MySQL - Less JSON support, weaker transaction isolation - MongoDB - No ACID, eventual consistency concerns - SQLite - Not suitable for production multi-user access ``` ### ADR Statuses | Status | Description | |--------|-------------| | `proposed` | Under discussion, not yet accepted | | `accepted` | Approved and implemented | | `deprecated` | No longer recommended, being phased out | | `superseded` | Replaced by a newer decision | ### ADR Fields | Field | Required | Description | |-------|----------|-------------| | Title | Yes | Short description of the decision (in `# ADR-NNN: Title` format) | | Status | Yes | One of: proposed, accepted, deprecated, superseded | | Date | No | Decision date (defaults to file modification time) | | Author | No | Who made or proposed the decision | | Context | Yes | The problem being addressed | | Decision | Yes | What was decided | | Consequences | Yes | List of effects (positive and negative) | | Affected Modules | No | Which modules are impacted | | Alternatives Considered | No | Other options that were evaluated | | Superseded by | No | ADR ID that replaces this one (if superseded) | ### File Naming Convention ADR files should follow this naming pattern: ``` ADR-001-use-postgresql-for-database.md adr-002-adopt-hexagonal-architecture.md 003-implement-caching-layer.md ``` CKB recognizes patterns: - `ADR-NNN-*.md` or `adr-NNN-*.md` - `NNN-*.md` (3-4 digit number prefix) ### Creating ADRs #### Via CLI ```bash # Create a new decision (opens in $EDITOR or creates with title) ckb decisions new --title "Use Redis for caching" # List all decisions ckb decisions # Filter by status ckb decisions --status accepted # Search decisions ckb decisions --search "caching" ``` #### Via MCP (recordDecision) ```json { "name": "recordDecision", "arguments": { "title": "Use Redis for session caching", "context": "User sessions need fast access with automatic expiration...", "decision": "We will use Redis 7 for session storage...", "consequences": [ "Sessions stored in-memory for fast access", "Built-in TTL handles expiration", "Requires Redis infrastructure" ], "affectedModules": ["internal/auth", "internal/session"], "alternatives": [ "Database sessions - too slow for auth checks", "JWT only - no server-side revocation" ], "status": "proposed" } } ``` Returns: ```json { "adrId": "ADR-005", "filePath": "~/.ckb/repos/abc123/decisions/adr-005-use-redis-for-session-caching.md", "status": "proposed" } ``` #### Via HTTP API ```bash curl -X POST http://localhost:8080/decisions \ -H "Content-Type: application/json" \ -d '{ "title": "Use Redis for session caching", "context": "User sessions need fast access...", "decision": "We will use Redis 7...", "consequences": ["Fast access", "Built-in TTL"], "status": "proposed" }' ``` ### Querying ADRs #### Via MCP (getDecisions) ```json { "name": "getDecisions", "arguments": { "status": ["accepted", "proposed"], "search": "database", "affectedModule": "internal/storage", "limit": 10 } } ``` #### Via HTTP API ```bash # List all decisions curl http://localhost:8080/decisions # Filter by status curl "http://localhost:8080/decisions?status=accepted" # Search curl "http://localhost:8080/decisions?search=caching" # Filter by affected module curl "http://localhost:8080/decisions?affectedModule=internal/api" ``` ### ADR Workflow 1. **Propose**: Create ADR with status `proposed` 2. **Discuss**: Review with team, update context/alternatives 3. **Accept**: Change status to `accepted` 4. **Implement**: Build the solution 5. **Supersede** (if needed): Create new ADR, mark old as `superseded` ### Best Practices 1. **One decision per ADR** - Keep ADRs focused on a single decision 2. **Include context** - Future readers need to understand why, not just what 3. **Document alternatives** - Show what was considered and why it was rejected 4. **Link affected modules** - Helps with impact analysis 5. **Update status** - Keep ADRs current as decisions evolve 6. **Don't delete** - Supersede instead; history is valuable ### Integration with Federation ADRs are indexed in federation for cross-repo search: ```json { "name": "federationSearchDecisions", "arguments": { "federation": "platform", "query": "authentication", "status": ["accepted"] } } ``` --- ## v6.0 Configuration Roadmap The v6.0 Architectural Memory features are implemented and working, but currently use hardcoded defaults. Future releases will add configurable settings: ### Planned: ownership ```json { "ownership": { "enabled": true, "codeownersPath": ".github/CODEOWNERS", "gitBlameEnabled": true, "timeDecayHalfLife": 90, "excludeBots": true, "botPatterns": ["\\[bot\\]$", "^dependabot", "^renovate"] } } ``` **Current defaults:** - CODEOWNERS: `.github/CODEOWNERS` or `CODEOWNERS` - Git blame: enabled with 90-day half-life - Bot exclusion: enabled ### Planned: decisions ```json { "decisions": { "enabled": true, "directories": ["docs/decisions", "docs/adr", "adr", "decisions"], "storePath": "~/.ckb/repos/{repo}/decisions" } } ``` **Current defaults:** - Scans common ADR directories - Stores new ADRs in CKB data directory ### Planned: staleness ```json { "staleness": { "freshDays": 7, "freshCommits": 50, "staleDays": 30, "staleCommits": 200, "obsoleteDays": 90, "obsoleteCommits": 500 } } ``` **Current defaults:** - Fresh: <7 days or <50 commits - Stale: 30-90 days or 200-500 commits - Obsolete: >90 days or >500 commits --- ## Validation Validate your configuration: ```bash ckb doctor ``` This checks: - JSON syntax - Schema version compatibility - Required fields - Value ranges - Backend availability - MODULES.toml syntax --- ## Related Pages - [[Quick-Start]] — Initial setup and installation - [[Authentication]] — API tokens, rate limiting, scoped access - [[Daemon-Mode]] — Always-on service configuration - [[Telemetry]] — OpenTelemetry and metrics setup - [[Federation]] — Cross-repository configuration