Troubleshooting
Start with npx kenkeep doctor --verbose.
Nothing is being captured
.ai/kenkeep/_sessions/ stays empty.
- Hooks aren’t registered. Check
.claude/settings.jsonfor the knowledge base hook entries. Re-runinit --upgradeif missing. - A wrapper script around
claudeleaked the internal flag (KENKEEP_BUILDER_INTERNAL=1) into a normal session.
A hook seems to be silently doing nothing
Check <kk-root>/_logs/hook-errors-YYYY-MM-DD.log for the most recent day. Each line is a JSON object recording one swallowed hook failure, either a parse error (the harness sent malformed JSON) or an uncaught throw inside the hook, with the hook name, phase, and error message. The file is dated; rotation is implicit. Hooks always exit 0 by design, so this log is the primary breadcrumb when a hook appears to do nothing.
Captured sessions never get extracted
Session logs are stuck pending.
- Background extraction runs at the start of the next Claude Code session. Open a new one.
- Make sure
claudeis on PATH in the shell that runs the hook. - A stale
proposal-drainlock can briefly block extraction. The drain usesproper-lockfileon.ai/kenkeep/.state/state.jsonwith a 60s stale threshold, so a lock left by an interrupted (SIGKILLed) drain auto-reclaims on the next drain within about a minute. To recover immediately, remove the.ai/kenkeep/.state/state.json.lockdirectory. (Curate and bootstrap don’t take a state lock — they run single-author in one host session.)
/kk-curate says “no pending sessions”
Either everything is already curated, or some session logs have invalid frontmatter and are being silently skipped. Run doctor.
If session logs clearly exist under .ai/kenkeep/_sessions/ but the skill reports none, a flat *.md glob may have missed them in your harness. The skill falls back to listing the directory directly (or find .ai/kenkeep/_sessions -type f -name '*.md') before giving up, so this is normally self-healing; if it still misses, confirm the files end in .md and carry proposal_status: pending frontmatter.
/kk-curate fails with EBUSY running a primitive
In Cursor-like environments a direct node/npx shell call can fail with EBUSY even when the command is valid. The skill retries the same argv through Python’s subprocess list form (no wrapper, no shell), so a transient EBUSY is expected to recover on its own. A persistent failure through both paths is a real error — check that npx --yes kenkeep@latest <command> runs in a plain terminal.
/kk-curate asks which harness to use, or picks the wrong one
The skill resolves the harness id via the shared detector at .ai/kenkeep/scripts/kk-detect-harness.mjs (needed for index rebuild). When that detector cannot run, it falls back to .ai/kenkeep/.state/installed-version: if exactly one harness is installed it uses that; if several are installed it uses your runtime only when it matches one of them; otherwise it asks you to pick. To stop the prompt, make installed-version unambiguous (one installed harness) or run from a runtime whose id matches an installed harness.
Curator reported add_collision or modify_missing_target failures
add_collision: the curator wanted to write a new node, but a node with that id already exists. Pick a different title for the candidate (re-run/kk-curateafter deleting/editing the offending session log) or treat the existing node as the canonical version.modify_missing_target: the curator pointed at atarget_node_idthat’s not on disk, usually because the node was renamed or deleted between captures. Either restore the target file or treat the modification as an addition by editing the session log so the next curate run reproposes it asadd.
ENTRY.md is stale
doctor reports a hash drift. Cause: someone hand-edited or rebased nodes/ without running the curator.
Fix:
npx kenkeep index rebuild
Curator produces weird proposals
The prompt has drifted from your project’s needs. Edit .ai/kenkeep/.config/prompts/curator.md and bump its Version: comment. See Customization.
Bootstrap re-processes done docs
bootstrap-state.json keys on file content hash. Causes:
- The file was actually modified (even whitespace).
- The state file was deleted or is malformed.
Logs directory keeps growing
_logs/ is gitignored but unbounded. Prune periodically:
npx kenkeep logs prune
This deletes *.jsonl files older than logsRetentionDays (default 30) across the whole _logs/ tree.
Reviewing changes to nodes/
The curator writes directly to .ai/kenkeep/nodes/<folder>/<id>.md. Review with git diff nodes/, your editor, or a tool like self-review. Accept with git commit (the pre-commit hook regenerates and stages a fresh INDEX/GRAPH). Reject with git restore <path> — then run npx kenkeep index rebuild, because the curator already rebuilt the index over the rejected node and restoring it without committing a nodes/ change leaves that index stale.
Resolving curator contradictions
Each contradiction lands as a markdown file under .ai/kenkeep/conflicts/<id>.md with status: pending; the existing node is never overwritten. Run /kk-curate and the skill walks each one with the y/n/s/k prompt (see Daily use → Conflict walkthrough). To resolve by hand, edit the target node yourself and git restore (or git commit) the conflict file.
/kk-bootstrap uses a lot of context on large repos
/kk-bootstrap reads every candidate doc into your harness session, so on a large doc tree (hundreds of markdown files) it can force a compaction mid-run, or in extreme cases exhaust the session’s context window.
Remediation, in order of preference:
- Scope the run.
/kk-bootstrap docs/limits the walk to that subtree. - Tighten
.kkignore. Add entries to deny large vendored or generated markdown subtrees. - Run multiple smaller scopes one at a time instead of one repo-wide pass.
On Claude Code and Cursor, drafting fans out to native sub-agents, which keeps each candidate doc out of the main session’s context (see Architecture → Parallel drafting and per-batch logs).
Bootstrap is still sequential: why?
Per-harness support for native host sub-agents varies: Claude Code and Cursor ship a documented in-session Task tool and run the parallel path by default; Codex supports subagent dispatch at the workflow level (the exact in-LLM tool surface depends on your runtime); opencode is treated as a conservative fallback because its headless run --format json mode does not affirm Task-dispatch in current vendor docs. The kk-bootstrap and kk-curate skills probe their own tool surface at the start of each run and silently degrade to inline sequential drafting when no dispatch primitive is detected. This is by design, never an error, so a sequential run on an unsupported harness looks identical to a healthy parallel run from the outside.
To confirm which path actually ran, inspect the per-batch artefacts:
ls .ai/kenkeep/_logs/bootstrap/
You’ll see one <runId>__<batchN>.jsonl per batch in either mode (the JSONL contract is the cross-harness lowest-common-denominator trace). The accompanying <runId>__<batchN>.draft.json files are only written by the parallel path. If they are missing while .jsonl files exist, the inline fallback ran. Same convention under _logs/curator/ and _logs/kk-add/.
When all else fails
npx kenkeep doctor --verbose
cat .ai/kenkeep/.state/state.json
ls .ai/kenkeep/_sessions/
ls .ai/kenkeep/_logs/*/
Then file an issue.