Tasks, sessions, and agent lifecycle
Repository work often spans commands, turns, or agent processes. Knowl records bounded event state and explicit checkpoints so work can resume without retaining raw conversations.
Manual work loops
For one bounded command, task run performs the initial focused lookup and records success or a
failure checkpoint with the child exit code:
knowl task run "Run tests" --query "test verification" -- npm test
For resumable work, start once, checkpoint meaningful progress or blockers, and finish after verification:
knowl task start "Implement search UI" --query "search retrieval"
knowl task checkpoint <task-id> "Search tests are in place" \
--goal "Ship the search UI" \
--completed "Added empty and error-state tests" \
--next-action "Implement the result list" \
--artifact "src/search-ui.ts" \
--verification-status "tests-passing"
knowl task finish <task-id> "Search UI implemented and verified"
Use these manual tools only when verified lifecycle hooks are unavailable. Hook-owned sessions
must be left to their host lifecycle; a manual task finish or knowl_session_finish must not
close them.
Session retention, recovery, and promotion
Lifecycle events are temporary scratch records and expire after 48 hours. Active session rows
receive a nominal seven-day expiresAt, but the current implementation does not automatically
purge those rows. A session idle for more than two hours can be marked recovered; recovery does
not finalize the session or promote candidates.
At a normal terminal event, deterministic promotion selects at most eight durable candidates.
Decision candidates outrank generic outcomes. A repeatedly successful command becomes a skill
atom candidate after three runs, but that promoted atom is still descriptive knowledge, not an
executable .knowl/skills package. Failed terminal events create a handoff for the next matching
host session.
Hooks run as separate, short-lived knowl agent-hook processes. They normalize host events and
never start, stop, or supervise the long-lived stdio knowl serve process. Lifecycle capture
itself stores no raw prompts, transcripts, stdout, stderr, or environment variables. When
transcript indexing is explicitly enabled, the separate transcript index reads supported host
transcript files already present on the machine; it does not create them.
Leaving work for later
Two different shapes, deliberately not merged:
knowl_handoff |
knowl_park / knowl_resume |
|
|---|---|---|
| How many | One per project | Many at once |
| Who holds it | The project | The user, as a short key |
| Delivery | Pushed to the next session here | Pulled on demand, by key |
| Spent on use | Yes, one-shot | No, resume repeatedly |
| Reach | Next session in this repository | Any session, any directory, any time later |
"I am stopping for the night, whoever picks this up should know where I left it" is a handoff. "Park this branch of work, I will come back to it in a fortnight" is a resume point. A parked baton reads as planned work rather than as a crash, because a session told it "ended before a clean finish" goes looking for damage that does not exist.
Both are passes, not durable notes. Anything worth keeping goes to knowl_store.
Searchable session transcripts (optional, off by default)
Atoms are distilled and therefore lossy: whatever the writer did not judge salient is gone. The
raw Claude Code .jsonl transcripts are the complete record underneath. Indexing them turns a
memory miss into a slower lookup instead of amnesia.
Off by default, and off means nothing exists — no database file, no registered tools, no tokens spent in the guidance card.
// .knowl/config.json
"search": {
"transcripts": {
"enabled": false, // nothing is created, no MCP tools are registered
"share": false // let linked workspace repos read this index
}
}
knowl config # toggle it interactively
knowl reindex --transcripts --budget 5 # build the index, resumable
What it indexes and what it costs, measured on this repository's own archive: prose is 2.7% of
80.9 MB across 75 transcripts. Only user messages and assistant prose are indexed; tool_use
and tool_result blocks are skipped entirely. Rows are pointers — (session, line, role) — and
message bodies stay in the .jsonl, so the whole index is under 3 MB.
Ranking fuses BM25 with whole-corpus semantic search over int8 vectors, so a message that shares
no word with your query can still win. Semantic ranking follows search.vector.enabled; with
vectors off, transcript search is keyword-only and every result says so.
Three tools appear only when the feature is enabled, which is why they are absent from the canonical tool table below:
knowl_session_list— browse past sessions: best-known name, opening ask, status, and what each one promoted into memory.knowl_transcript_search— search prose across sessions; returnstranscript://<repo>/<session>#L<line>locators.knowl_transcript_read— open one locator with the surrounding turns.
Disabling the feature deletes .knowl/transcripts.db. An index nothing will refresh is not
something to leave on the disk of the person who just turned it off.
Workspace peers may opt in with share: true, which lets linked repositories open the index
read-only. Sharing is re-checked on every read, so revoking it revokes previously issued
locators too.
Both Claude Code and Codex archives are discovered. They are found by different mechanisms
because they are laid out differently: Claude Code names a directory after the project
(~/.claude/projects/<encoded-root>/), while Codex partitions by date
(~/.codex/sessions/YYYY/MM/DD/) and records the project inside each file as
session_meta.payload.cwd. Every Codex candidate is therefore opened, with a bounded header read.
knowl transcripts — turning sessions into candidates
Searching a transcript answers a question. This turns one into memory. Extraction runs the configured model over indexed sessions and stages what it finds; nothing reaches the knowledge store until you approve it.
knowl transcripts extract --limit 10 # prints the estimate, then stops
knowl transcripts extract --limit 10 --yes # actually runs
knowl transcripts candidates # review what was staged
knowl transcripts approve <id>... # promote, or --all
knowl transcripts discard <id>... # reject, or --all
Extraction spends your model quota, so it tells you first. extract prints the session count,
the character estimate and the provider it would call, and does nothing without --yes. The
default is 10 sessions, not the archive. It requires ai.provider and ai.model; without them,
distil a session yourself with knowl_transcript_read and store the result through
knowl_ingest_atoms, which needs no AI configuration.
Nothing is promoted automatically, and that is the point. A first run over a real archive produces on the order of a thousand atoms. An unreviewed corpus that size would be answering every future query while nobody had yet decided any of it was true, so approval is a separate, explicit act — one candidate at a time, each passing the same secret validation, confidence range and dedup checks that every other write does.
Runs are resumable and never pay twice. An extracted session is watermarked, including one that yielded nothing — short sessions yield nothing most often and would otherwise dominate the bill. A session whose extraction failed is deliberately left unwatermarked, because a provider error is not a verdict about that session. Long sessions are truncated from the start, keeping the tail, where a session's conclusions are.
Promoted atoms carry provenance: inferred and source: transcript:<harness>:<session>. A model
distilled them from a conversation nobody re-read at approval time; calling that observed would
rank it above knowledge somebody actually verified.
Candidates live in .knowl/transcripts.db, not the knowledge store, so speculative rows never
reach a query and disabling transcript search discards them with the index. They are regenerable
from the transcripts, which is what makes that safe.
Host and subagent behavior
| Host | MCP | Automatic lifecycle | Subagent lifecycle | Current session behavior or limit |
|---|---|---|---|---|
| Codex | Yes | Yes | Yes | Main turns share one memory session |
| Claude Code | Yes | Yes | Yes | Main turns share one memory session; prompt guidance is also installed |
| Cursor | Yes | Yes | No | Finalizes per turn; supplied additional_context may not surface to the model |
| Gemini CLI | Yes | No | No | MCP plus the manual work loop |
| Claude Desktop | Yes | No | No | MCP plus the manual work loop |
Claude Code and Codex subagents share their parent's memory session, but each subagent has its own binding, reminder counter, change watermark, and lifecycle identity. Their retrieved memory is capped at half of the normal 3,000-character context allowance, plus a compact workflow card. Cursor does not expose a corresponding subagent event.
Each accepted successful non-Knowl tool event advances a per-agent drift counter. After 12 consecutive events, a mid-turn card reminds the agent to re-query. A Knowl call or an emitted change card resets the counter. Change cards report new knowledge commits since that agent's watermark; matched writes made through that agent's own MCP call are suppressed so the caller is not notified about its own change.