Skip to content

Index Management

CKB automatically keeps your SCIP index up-to-date using several mechanisms. This page explains how index refresh works and how to monitor it.

How Index Refresh Works

CKB offers multiple ways to keep your index fresh:

Method Latency Best For
Manual (ckb index) Immediate On-demand updates
Daemon file watcher ~7s Always-on development
MCP watch mode ~10s IDE sessions
Webhooks Immediate CI/CD integration

Branch Switching

The daemon handles branch switches automatically. No git hooks needed.

When using the daemon, branch switches are detected within seconds:

  1. You run git checkout feature-branch
  2. Git updates .git/HEAD
  3. Daemon detects the change (polling .git/HEAD every 2s)
  4. After 5s debounce, reindex triggers automatically
  5. Total latency: ~7 seconds worst case

For MCP-only users (no daemon), watch mode provides similar functionality:

# Default 10s polling interval
ckb mcp --watch

# Faster polling (5s minimum)
ckb mcp --watch --watch-interval 5s

Refresh Triggers

CKB tracks what triggered each index refresh. You can see this in the getStatus MCP response:

{
  "lastRefresh": {
    "at": "2024-12-25T10:00:00Z",
    "trigger": "head-changed",
    "triggerInfo": "branch or commit changed",
    "durationMs": 1200
  }
}

Trigger Types

Trigger Description Source
head-changed Branch switch or new commit Daemon/MCP watching .git/HEAD
index-changed Staged files modified Daemon watching .git/index
manual CLI ckb index command User action
scheduled Daemon scheduler Cron-like schedule
webhook External webhook trigger CI/CD or external system
stale Generic staleness detection Polling detected changes

Daemon Mode

The daemon provides the most responsive index refresh:

# Start daemon
ckb daemon start

# Check what it's watching
ckb daemon status

What the Daemon Watches

The daemon uses polling (not fsnotify) for simplicity and cross-platform compatibility:

  • .git/HEAD - Detects branch switches and new commits (content comparison)
  • .git/index - Detects staged file changes (modification time)

Polling intervals:

  • File check: every 2 seconds
  • Debounce: 5 seconds (batches rapid changes)

Configuration

{
  "daemon": {
    "watch": {
      "enabled": true,
      "debounceMs": 5000,
      "ignorePatterns": ["*.log", "node_modules/**", ".git/objects/**"]
    }
  }
}

See Daemon-Mode for complete daemon configuration.

MCP Watch Mode

For users running CKB via MCP without the daemon:

# Enable watch mode with default 10s interval
ckb mcp --watch

# Custom interval (5s to 5m)
ckb mcp --watch --watch-interval 15s

MCP watch mode uses polling only (no file watchers). It periodically checks CheckFreshness() which compares:

  1. Current HEAD commit vs indexed commit
  2. Current repo state ID vs indexed state ID
  3. Uncommitted changes

When staleness is detected, it triggers a reindex automatically.

Checking Index Freshness

Via CLI

ckb status

Shows:

  • Current index state
  • Commits behind HEAD
  • Index age
  • Last refresh info (if available)

Via MCP

The getStatus tool returns comprehensive freshness info:

{
  "repoState": {
    "commit": "abc123",
    "branch": "feature/auth",
    "dirty": false
  },
  "lastRefresh": {
    "at": "2024-12-25T10:00:00Z",
    "trigger": "head-changed",
    "triggerInfo": "branch or commit changed",
    "durationMs": 1200
  }
}

Programmatically

meta, _ := index.LoadMeta(ckbDir)
freshness := meta.CheckFreshness(repoRoot)

if !freshness.Fresh {
    fmt.Printf("Stale: %s (%d commits behind)\n",
        freshness.Reason, freshness.CommitsBehind)
}

Manual Refresh

Force an immediate reindex:

# Standard reindex
ckb index

# Force full reindex (ignores incremental)
ckb index --force

CI/CD Integration

For CI/CD pipelines, use webhooks to trigger refresh:

# Trigger refresh via daemon API
curl -X POST http://localhost:9120/api/v1/refresh

# Full reindex
curl -X POST http://localhost:9120/api/v1/refresh -d '{"full":true}'

See CI-CD-Integration for complete CI/CD setup.

Troubleshooting

Index seems stale after branch switch

  1. Check if daemon is running: ckb daemon status
  2. Check last refresh: Use getStatus MCP tool
  3. Force refresh: ckb index

Daemon not detecting changes

  1. Verify daemon is watching the repo: ckb daemon status
  2. Check logs: ~/.ckb/daemon.log
  3. Ensure .git/HEAD exists and is readable

MCP watch mode not refreshing

  1. Check watch is enabled: should see "Watch mode enabled" in stderr
  2. Reduce interval: --watch-interval 5s
  3. Check for lock contention: another process may be indexing

Implementation Notes

Why polling instead of fsnotify?

CKB uses polling for file watching because:

  • Cross-platform consistency (fsnotify has platform-specific edge cases)
  • Simpler implementation and debugging
  • 2s poll interval is imperceptible for most workflows
  • Avoids inotify watcher limits on Linux

The 7s worst-case latency (2s poll + 5s debounce) is acceptable for the "instant reindex on branch switch" use case.