-
Notifications
You must be signed in to change notification settings - Fork 1
Configuration
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 below.
your-repo/
└── .ckb/
├── config.json # Configuration
└── ckb.db # SQLite database
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:
{
"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:
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{
"version": 5,
"repoRoot": ".",
"backends": {
"scip": {
"enabled": true,
"indexPath": ".scip/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": []
}Schema version number. Current version is 5.
{
"version": 5
}Root directory for the repository. Usually ".".
{
"repoRoot": "."
}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 |
{
"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=fastfor a single command without changing config
Configure which backends are enabled and their settings.
SCIP (Source Code Intelligence Protocol) backend.
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Enable SCIP backend |
indexPath |
string | ".scip/index.scip" | Path to SCIP index file |
{
"backends": {
"scip": {
"enabled": true,
"indexPath": ".scip/index.scip"
}
}
}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
{
"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": []
}
}
}
}
}Git backend for blame, history, and fallback operations.
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Enable Git backend |
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: Inprefer-firstmode, 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), useunionmode which queries all backends in parallel.
{
"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
}
}
}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 |
{
"lspSupervisor": {
"maxTotalProcesses": 4,
"queueSizePerLanguage": 10,
"maxQueueWaitMs": 200
}
}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_modulesbuild.dart_toolvendor
{
"modules": {
"detection": "auto",
"roots": ["internal/legacy"],
"ignore": ["node_modules", "build", ".dart_tool", "vendor", "dist"]
}
}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 |
{
"importScan": {
"enabled": true,
"maxFileSizeBytes": 1000000,
"scanTimeoutMs": 30000,
"skipBinary": true,
"customPatterns": {}
}
}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) |
{
"cache": {
"queryTtlSeconds": 300,
"viewTtlSeconds": 3600,
"negativeTtlSeconds": 60
}
}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 |
{
"budget": {
"maxModules": 10,
"maxSymbolsPerModule": 5,
"maxImpactItems": 20,
"maxDrilldowns": 5,
"estimatedMaxTokens": 4000
}
}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) |
{
"backendLimits": {
"maxRefsPerQuery": 10000,
"maxFilesScanned": 5000,
"maxUnionModeTimeMs": 60000
}
}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
{
"privacy": {
"mode": "normal"
}
}Logging configuration.
| Field | Type | Default | Description |
|---|---|---|---|
level |
string | "info" | Log level (debug, info, warn, error) |
format |
string | "human" | Output format (human, json) |
{
"logging": {
"level": "info",
"format": "human"
}
}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 |
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable authentication |
token |
string | "" | Auth token (inline) |
tokenFile |
string | "" | Path to token file |
| 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 |
| 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 |
{
"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"
}
}
}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.updatedfederation.syncedhotspot.detected
{
"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"
}
}
]
}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:
{
"telemetry": {
"enabled": true,
"serviceMap": {
"api-gateway": "repo-api",
"user-service": "repo-users"
}
}
}Full schema:
{
"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
}
}
}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.mdARCHITECTURE.mdDESIGN.mdCONTRIBUTING.md
Default exclude patterns:
node_modulesvendor.gitdistbuild
{
"docs": {
"paths": ["docs", "README.md", "ARCHITECTURE.md", "DESIGN.md", "CONTRIBUTING.md"],
"include": ["*.md", "*.markdown"],
"exclude": ["node_modules", "vendor", ".git"]
}
}Example: Custom documentation structure
{
"docs": {
"paths": ["documentation", "wiki", "*.md"],
"include": ["*.md"],
"exclude": ["node_modules", "vendor", ".git", "examples"]
}
}Example: Only check specific docs
{
"docs": {
"paths": ["docs/api", "README.md"],
"include": ["*.md"]
}
}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.
# Start server with index-serving endpoints
ckb serve --index-server --index-config /path/to/index-server.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| 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) |
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) |
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 |
Full exposure (default):
[default_privacy]
expose_paths = true
expose_docs = true
expose_signatures = trueMinimal exposure (paths only):
[default_privacy]
expose_paths = true
expose_docs = false
expose_signatures = falseStrip build paths:
[repos.privacy]
expose_paths = true
path_prefix_strip = "/home/build/workspace/"
# "/home/build/workspace/src/main.go" becomes "src/main.go"# 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 = falseFor index server mode that accepts uploads via HTTP API:
# 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-
Cursor Secret: If not provided, a random secret is generated at startup. For multi-instance deployments, set the same
cursor_secreton all instances. -
Read-Only Mode: The index server opens all databases in read-only mode for safety.
-
Network Binding: Use
--hostto control binding:# Local only (default) ckb serve --index-server --host localhost # All interfaces (use with caution) ckb serve --index-server --host 0.0.0.0
-
Authentication: Use
--auth-tokenorCKB_AUTH_TOKENfor simple authentication. For scoped tokens and rate limiting, configure the[auth]section in your--index-configTOML file. See Authentication.
See Federation for more details on Remote Index Serving use cases.
Each CLI command has specific flags. Use --help to see all options:
ckb --help # Global help
ckb search --help # Search command help
ckb serve --help # Server command help| Flag | Default | Description |
|---|---|---|
--scope |
"" | Limit to module ID |
--kinds |
"" | Filter by kinds (comma-separated) |
--limit |
20 | Max results |
--format |
"json" | Output format (json, human) |
| Flag | Default | Description |
|---|---|---|
--format |
"json" | Output format |
| Flag | Default | Description |
|---|---|---|
--format |
"json" | Output format |
| Flag | Default | Description |
|---|---|---|
--format |
"json" | Output format |
--depth |
1 | Dependency depth |
| 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 protects the server under heavy load by queuing and rejecting excess requests. Disabled by default.
Configuration in config.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
maxConcurrentRequestsenter a queue - If queue is full or timeout expires, returns
503 Service Unavailable - Priority endpoints (
/health,/ready,/metrics) always proceed - Response includes
Retry-Afterheader
Adaptive Mode:
For latency-aware shedding, the adaptive shedder tracks response times and sheds earlier when latency exceeds targets:
{
"loadShedding": {
"enabled": true,
"adaptive": true,
"targetLatencyMs": 100
}
}| Flag | Default | Description |
|---|---|---|
--out |
"" | Output file path |
--anonymize |
false | Anonymize paths and symbols |
View and manage CKB configuration.
# 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| Subcommand | Description |
|---|---|
show |
Display current configuration |
env |
List all supported environment variables |
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: .scip/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:
{
"configPath": ".ckb/config.json",
"usedDefaults": false,
"envOverrides": [
{
"envVar": "CKB_LOG_LEVEL",
"path": "logging.level",
"fromValue": "debug"
}
],
"config": {
"version": 5,
"tier": "",
"backends": { ... },
...
}
}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.
| 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 |
| 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_LEVELandCKB_LOGGING_FORMATare also supported as aliases.
| 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 |
| 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 |
| 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 |
| Variable | Config Path | Type | Description |
|---|---|---|---|
CKB_DAEMON_PORT |
daemon.port |
int | Daemon HTTP port |
CKB_DAEMON_BIND |
daemon.bind |
string | Daemon bind address |
| Variable | Config Path | Type | Description |
|---|---|---|---|
CKB_TELEMETRY_ENABLED |
telemetry.enabled |
bool | Enable telemetry features |
CKB_PRIVACY_MODE |
privacy.mode |
string | Privacy mode (normal, redacted) |
# 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 serveConfiguration is loaded in this order (later sources override earlier):
- Default values (built into CKB)
-
.ckb/config.jsonfile - Environment variables
- CLI flags (where applicable)
CKB automatically checks for updates once per day using the GitHub Releases API. This works for all installation methods (npm, 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
mcpandservecommands to avoid breaking protocols
Smart upgrade message:
- npm installs: Shows
npm update -g @tastehub/ckb - Other installs: Shows GitHub releases URL
Disable update checks:
export CKB_NO_UPDATE_CHECK=1Example 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 │
╰─────────────────────────────────────────────────────╯
{
"version": 5,
"backends": {
"scip": { "enabled": true },
"lsp": { "enabled": false },
"git": { "enabled": true }
}
}{
"version": 5,
"backends": {
"scip": { "enabled": true },
"lsp": { "enabled": false },
"git": { "enabled": true }
},
"queryPolicy": {
"backendPreferenceOrder": ["scip"],
"alwaysUse": ["git"],
"mergeMode": "prefer-first"
}
}{
"version": 5,
"budget": {
"maxModules": 20,
"maxSymbolsPerModule": 10,
"maxImpactItems": 50,
"estimatedMaxTokens": 8000
},
"backendLimits": {
"maxRefsPerQuery": 50000,
"maxFilesScanned": 20000
},
"cache": {
"queryTtlSeconds": 600,
"viewTtlSeconds": 7200
}
}{
"version": 5,
"privacy": {
"mode": "redacted"
},
"logging": {
"level": "warn"
}
}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.
# MODULES.toml - Explicit module declarations for CKB
version = 1version = 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"]| 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) |
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 |
For simple cases, you only need the path field:
version = 1
[[module]]
path = "internal/api"
[[module]]
path = "internal/query"
[[module]]
path = "pkg/utils"When id is not specified, CKB generates a stable ID:
ckb:mod:<hash>
The hash is derived from the normalized module path, ensuring the ID remains stable as long as the path doesn't change.
- Higher confidence - Declared modules have confidence 1.0 vs 0.5-0.7 for inferred
- Preserved on refresh - Declared data is never overwritten by inference
- Better ownership - Explicit owners override git-blame heuristics
- Clearer boundaries - Public/internal patterns define module contracts
-
Dependency control -
allowed_dependenciesenables future dependency violation detection
Validate your MODULES.toml:
ckb doctorCKB validates:
- Required
pathfield is present - Paths exist in the repository
- TOML syntax is correct
CKB includes a complete ADR system for documenting architectural decisions. ADRs are stored as markdown files and indexed for search.
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
CKB looks for ADRs in these directories (in priority order):
docs/decisions/docs/adr/adr/decisions/doc/adr/doc/decisions/
When creating new ADRs via the API/MCP, they are stored in:
-
~/.ckb/repos/<repo-hash>/decisions/(v6.0 global persistence)
ADRs are markdown files with a specific structure:
# 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| 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 |
| 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) |
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-*.mdoradr-NNN-*.md -
NNN-*.md(3-4 digit number prefix)
# 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"{
"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:
{
"adrId": "ADR-005",
"filePath": "~/.ckb/repos/abc123/decisions/adr-005-use-redis-for-session-caching.md",
"status": "proposed"
}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"
}'{
"name": "getDecisions",
"arguments": {
"status": ["accepted", "proposed"],
"search": "database",
"affectedModule": "internal/storage",
"limit": 10
}
}# 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"-
Propose: Create ADR with status
proposed - Discuss: Review with team, update context/alternatives
-
Accept: Change status to
accepted - Implement: Build the solution
-
Supersede (if needed): Create new ADR, mark old as
superseded
- One decision per ADR - Keep ADRs focused on a single decision
- Include context - Future readers need to understand why, not just what
- Document alternatives - Show what was considered and why it was rejected
- Link affected modules - Helps with impact analysis
- Update status - Keep ADRs current as decisions evolve
- Don't delete - Supersede instead; history is valuable
ADRs are indexed in federation for cross-repo search:
{
"name": "federationSearchDecisions",
"arguments": {
"federation": "platform",
"query": "authentication",
"status": ["accepted"]
}
}The v6.0 Architectural Memory features are implemented and working, but currently use hardcoded defaults. Future releases will add configurable settings:
{
"ownership": {
"enabled": true,
"codeownersPath": ".github/CODEOWNERS",
"gitBlameEnabled": true,
"timeDecayHalfLife": 90,
"excludeBots": true,
"botPatterns": ["\\[bot\\]$", "^dependabot", "^renovate"]
}
}Current defaults:
- CODEOWNERS:
.github/CODEOWNERSorCODEOWNERS - Git blame: enabled with 90-day half-life
- Bot exclusion: enabled
{
"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
{
"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
Validate your configuration:
ckb doctorThis checks:
- JSON syntax
- Schema version compatibility
- Required fields
- Value ranges
- Backend availability
- MODULES.toml syntax
- 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