Skip to content

Configuration

Lisa edited this page Dec 26, 2025 · 18 revisions

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 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:

{
  "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

Full Schema (Current Implementation)

{
  "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": []
}

Configuration Sections

version

Schema version number. Current version is 5.

{
  "version": 5
}

repoRoot

Root directory for the repository. Usually ".".

{
  "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
{
  "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 ".scip/index.scip" Path to SCIP index file
{
  "backends": {
    "scip": {
      "enabled": true,
      "indexPath": ".scip/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
{
  "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.

{
  "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
{
  "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
{
  "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
{
  "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)
{
  "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
{
  "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)
{
  "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
{
  "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)
{
  "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
{
  "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
{
  "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:

{
  "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
    }
  }
}

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
{
  "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"]
  }
}

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

# Start server with index-serving endpoints
ckb serve --index-server --index-config /path/to/index-server.toml

Configuration File Schema

[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):

[default_privacy]
expose_paths = true
expose_docs = true
expose_signatures = true

Minimal exposure (paths only):

[default_privacy]
expose_paths = true
expose_docs = false
expose_signatures = false

Strip build paths:

[repos.privacy]
expose_paths = true
path_prefix_strip = "/home/build/workspace/"
# "/home/build/workspace/src/main.go" becomes "src/main.go"

Complete Example

# 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:

# 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:

    # 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:

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 "json" Output format (json, human)

ckb refs

Flag Default Description
--format "json" Output format

ckb impact

Flag Default Description
--format "json" Output format

ckb arch

Flag Default Description
--format "json" Output format
--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:

{
  "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:

{
  "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.

# 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": { ... },
    ...
  }
}

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

# 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, 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
  • Other installs: Shows GitHub releases URL

Disable update checks:

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

{
  "version": 5,
  "backends": {
    "scip": { "enabled": true },
    "lsp": { "enabled": false },
    "git": { "enabled": true }
  }
}

SCIP-Only (Fastest)

{
  "version": 5,
  "backends": {
    "scip": { "enabled": true },
    "lsp": { "enabled": false },
    "git": { "enabled": true }
  },
  "queryPolicy": {
    "backendPreferenceOrder": ["scip"],
    "alwaysUse": ["git"],
    "mergeMode": "prefer-first"
  }
}

Large Codebase

{
  "version": 5,
  "budget": {
    "maxModules": 20,
    "maxSymbolsPerModule": 10,
    "maxImpactItems": 50,
    "estimatedMaxTokens": 8000
  },
  "backendLimits": {
    "maxRefsPerQuery": 50000,
    "maxFilesScanned": 20000
  },
  "cache": {
    "queryTtlSeconds": 600,
    "viewTtlSeconds": 7200
  }
}

Privacy-Focused

{
  "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

# MODULES.toml - Explicit module declarations for CKB
version = 1

Complete Example

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:

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:<hash>

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:

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/<repo-hash>/decisions/ (v6.0 global persistence)

ADR File Format

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

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

# 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)

{
  "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"
}

Via HTTP API

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)

{
  "name": "getDecisions",
  "arguments": {
    "status": ["accepted", "proposed"],
    "search": "database",
    "affectedModule": "internal/storage",
    "limit": 10
  }
}

Via HTTP API

# 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:

{
  "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

{
  "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

{
  "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

{
  "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:

ckb doctor

This checks:

  • JSON syntax
  • Schema version compatibility
  • Required fields
  • Value ranges
  • Backend availability
  • MODULES.toml syntax

Related Pages

Clone this wiki locally