thread-keeper
Multi-agent shared brain across Claude, Codex, Antigravity, Gemini, Copilot, and VS Code.
Connector by po4erk91 · GitHub account verified by the MCP Registry
Install
Works with Claude Code, Codex, VS Code, Cursor, Windsurf, Claude Desktop. Read the repository before you give any tool access to your data.
npx agentmarket install connector/po4erk91-thread-keeper
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: agent-memory, agent-orchestration
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this server can do and what it asks for, from its tool list, install config and code. Checked Oct 25, 2026.
- Tools
- 67 read · 65 write · 12 delete
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Python package
Tools by what they do 144
Read from the source code; the running server may list different tools.
Read 67 · Look things up without changing anything.
agent_statusagent_status_refreshauto_review_triggerbriefcandidate_review_runcandidate_review_statuscapability_searchcompostconfig_watch_statuscontextcore_getcore_list
Show 55 more tools
curator_research_writecurator_reviewcurator_review_statusdialectic_mine_statusdialectic_reviewdialectic_synthesisdialectic_validate_rundialectic_validate_statusdialog_searchevolve_formatevolve_reviewexpand_conceptextract_recentfind_invariantsfind_missed_spawnsinboxlesson_getlesson_listlesson_neighborslist_conceptslive_statusmemory_authorize_actionmemory_guard_statusmemory_scope_statusmodel_router_statusmp_dashboardmp_healthneighborsopen_dashboardpeerspending_distillatespickup_candidatespresencereliability_forrespondreview_candidatesreview_threadsearchsearch_via_parentshadow_review_runshadow_review_statusskill_listskill_validatespawn_budget_statusspawn_statustask_logstask_threadtasksvalidate_threadsverbatim_userwaitweak_spotswhoamiwikilink_healthworkflow_retention_preview
Write 65 · Create, change, send or run things.
accept_candidateaskbroadcastclaim_pickupclose_threadconfig_reloadconvene_panelcore_setcurator_merge_verdictcurator_report_writecurator_restorecurator_run
Show 53 more tools
db_compactdialectic_claimdialectic_evidencedialectic_mine_rundialectic_observation_resolvedialectic_supersededistillevolve_applyevolve_apply_conflicted_prevolve_apply_curator_reportevolve_apply_roadmap_issueevolve_apply_statusevolve_decideevolve_issue_createevolve_mark_appliedevolve_mark_curator_report_appliedevolve_mark_roadmap_issue_appliedevolve_research_handoffexport_distillatesidle_threadingestlesson_appendlesson_patchlesson_restorelesson_violationlinkmark_skill_materializedmemory_guard_reclaimmodel_route_writemodel_router_runnoteopen_dialog_windowopen_threadrecord_attemptregister_conceptregister_probereject_candidaterelease_pickuprun_probesession_endshadow_review_snapshotskill_recordspawnspawn_budget_setstyle_setsync_nowsync_peerssync_statustag_signaltasks_refreshtournamentvote_distillwhisper
Delete 12 · Delete, drop, revoke or wipe things.
agent_memory_cleanupconcept_manageconsolidatecore_removedb_deduplicate_embeddingsevolve_prune_managed_venvforgetlesson_removememory_guard_checkmp_cleanupskill_manageunlink
Network hosts it talks to 8
antigravity-cli-auto-updater-974169037036.us-central1.run.app· found in codeapi.anthropic.com· found in codeapi.github.com· found in codeapple.com· found in codecodeload.github.com· found in codegithub.com· found in codeglama.ai· found in codeslsa.dev· found in code
Files it touches
~/.claude.json~/.claude/CLAUDE.md~/.claude/plugins/cache~/.claude/plugins/marketplaces~/.claude/projects~/.claude/settings.json~/.claude/skills~/.config/Claude/claude_desktop_config.json~/.threadkeeper/.env/dev/stdin/opt/homebrew/bin/opt/homebrew/bin/claude/usr/lib/libSystem.B.dylib- Your home directory (~)
~/.agents/skills~/.cache/huggingface/hub~/.codex~/.codex/AGENTS.md~/.codex/config.toml~/.codex/plugins/cache~/.codex/sessions~/.codex/skills/.system~/.config/Code/User/mcp.json~/.copilot/copilot-instructions.md~/.copilot/hooks.json~/.copilot/mcp-config.json~/.copilot/session-store.db~/.gemini/antigravity-cli~/.gemini/antigravity-cli/conversations~/.gemini/config~/.memory_partner~/.threadkeeper~/.threadkeeper/curator~/.threadkeeper/db.sqlite~/.threadkeeper/ingest_denylist.txt~/.threadkeeper/lessons.md~/.threadkeeper/model_catalog.json~/.threadkeeper/tasks~/AppData/Roaming- Any path the agent passes to its tools
Tools (144)
Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].
accept_candidateMaterialize candidate into its target table. target_kind overrides candidate's kind. thread_id optional.
agent_memory_cleanupTrim ThreadKeeper memory and clean orphan/over-limit server processes. By default this applies the safe cleanup path. Set dry_run=True to inspect the plan first. It does not kill active spawned child agents.
agent_statusShow autonomous learning loops with state, backlog, last pass, and RSS. Set json_output=True for the same stable shape used by the menu-bar app. Always returns structuredContent (AgentStatusSnapshot); the text block is the JSON dump when json_output else the formatted summary.
agent_status_refreshRefresh persisted task RSS/lifecycle state, then return the snapshot.
askSend a question to a peer and wait synchronously for their answer. Mechanics: posts a whisper with kind='question'; blocks until target posts a whisper/answer back to me, or `timeout_s` elapses. Use peers() to find available cids; 8-char prefix accepted. Note: requires the target to be in a `wait()` loop or actively calling inbox()+respond(). If they're idle, you'll just timeout.
auto_review_triggerCheck current counters + close-thread state and, if conditions are met, fire review_thread(mode='auto') for the richest pending thread. `force=True` skips the counter check (always trigger if there's a rich pending closed thread). Use this when you've seen a skill_nudge or skill_hint and want to act without manually picking the thread_id.
briefCompact Claude-native memory brief. CALL AT THE START OF EVERY CONVERSATION. Format is dense, structural, not designed for human reading. Pass the user's first message as `query` to inline semantically relevant past notes. `scope` controls how much is rendered (context-footprint knob): 'full' (default) — the complete brief: static memory (core_memory, style, verbatim, user_model, concepts, weak_spots) + live working set + nudges. Use for the FIRST call of a session. 'query' — only the live working set (ctx, inbox, tasks, threads) plus the query-relevant hit…
broadcastPost a message visible to ALL concurrent claude conversations. Other peers see it in their next brief() under `inbox` (unread) and via inbox(). Use for: shared insights, status updates, work claims, anything you'd want sibling sessions to know.
candidate_review_runFire one candidate-review pass. `force=True` runs even when CANDIDATE_REVIEW_INTERVAL_S=0 (daemon disabled). `dry_run=True` short-circuits before the spawn — returns the inventory and pending count. No spawn, no cursor advance.
candidate_review_statusShow candidate-reviewer configuration + last 5 passes + current pending queue size.
capability_searchFind hidden capability families without exposing their concrete tools. Select the returned profile when starting the server to advertise that family. A search result is descriptive only; it cannot enable any tool.
claim_pickupClaim a thread for self-initiated work. Marks it claimed by my cid. If `auto_spawn=True`, immediately spawns a headless child with the thread context (question + recent notes + plan) for parallel work. `spawn_role` defaults to 'executor' when auto_spawn is on.
close_threadClose a thread with a 5-15 word outcome.
compostSurface N random idle threads. Call when current threads feel exhausted or you want to shake loose dormant ideas.
concept_managePrune, consolidate, or re-grade concepts — the curator's eviction path. Concepts are ALL system-generated (there is no foreground/pinned concept class the way lessons/skills have one), so unlike `lesson_remove` this tool needs no `force` escape hatch: every concept is fair game for curation. The guard is simply that the target id must exist. action='remove' — delete one concept (the curator's PRUNE_CONCEPT). action='consolidate' — keep `concept_id`, fold each id in `merge_ids` (comma-separated) into it — their triangulation …
Show 129 more tools
config_reloadRe-read the watched config files and hot-apply changed env knobs. Re-reads the universal env-file (`~/.threadkeeper/.env`, every host) and the host CLI's own env-block file (Claude Code → `~/.claude/settings.json`) into the live process — no CLI restart — then republishes the changed constants to every daemon and tool. Newly enabled daemons are started; changed intervals take effect on the next daemon tick. Returns the pass outcome (e.g. `env=reloaded changed=2 ... cli=unchanged`).
config_watch_statusShow hot-config-reload state + the last 5 reload passes. In hybrid mode reports both watched files: the universal env-file (`~/.threadkeeper/.env`, all hosts) and the host CLI's env-block file (resolved via identity). `THREADKEEPER_CONFIG_WATCH_PATH` pins a single file (legacy single-file mode).
consolidatePeriodic memory hygiene. dry_run=True (default) reports only. merge_dup_notes : intra-thread cosine ≥ note_cosine, keep oldest idle_stale : active threads not touched in stale_days dedupe_verbatim : exact text + (if embeddings) cosine ≥ verbatim_cosine release_orphan : claim ≥ orphan_days old, no progress past claim mark prune_tasks : ended task rows outside retention bounds gc_task_spool : task spool files with no retained task row
contextRuntime context: session id, age, semantic on/off, db path, thread counts. Returns structuredContent (ContextStatus) plus the legacy text block. The same snapshot is reachable read-only as the ``memory://context`` resource — both render through ``brief.render_context``.
convene_panelSpawn a panel of independent agents to vote on a distillate or claim, filling the promotion quorum the way a second human otherwise would. `target_kind`: 'distill' (vote via vote_distill) or 'claim' (vote via dialectic_evidence). `target_id`: Dxxx or UCxxx. `size`/`roles` override the configured PANEL_SIZE / PANEL_ROLES. The panel runs adversarially: with a skeptic present (default), each child's vote carries full weight (`panel_vote` origin); a panel without a skeptic is discounted so it can't rubber-stamp. Children are fire-and-forget — they vote directly into the DB and aggregates recompu…
core_getReturn the full content of a single core-memory entry.
core_listList all core-memory entries, ordered by priority DESC then key.
core_removeDelete a core-memory entry by key.
core_setUpsert a core-memory entry. ALWAYS shown in brief, sorted by priority DESC. Use sparingly — this is the 'what new-claude must know' surface, not a note store. Good: 'project_root=/Users/.../ai-memory'. Bad: 'today we tried X'. `priority` 0-100 (higher = shown first). `content` capped 1KB.
curator_merge_verdictRemember a curator-reviewed lesson pair that should remain separate. This records only the safe `keep_both` outcome for a rejected merge candidate. The next curator inventory includes the pair and short reason, so a later pass can respect the deliberate layering without re-reading both full lesson bodies.
curator_report_writeAtomically write one Curator report inside the configured report dir. This narrow tool is the cross-CLI alternative to direct filesystem Write: Codex workspace sandboxes cannot write ``~/.threadkeeper/curator`` when the project is elsewhere. ``pass_id`` is filename-safe and cannot select an arbitrary path. A bounded multi-child pass supplies ``batch_index`` and ``batch_total`` so children cannot overwrite each other's reports. Repeated calls replace the same pass/batch report so the Curator can persist its plan before mutation and then add actual validation/rollback results. Only a parent-aut…
curator_research_writePersist bounded public web evidence to a parent-authorized handoff. Only a spawned ``curator_researcher`` child carrying the matching pass ID may call this tool. The parent chooses the filename from pass and batch metadata; callers cannot select a destination or hand evidence to another batch. The web-only child receives no local inventory, memory, or repository access.
curator_restoreRestore one lesson or skill from a curator pre-mutation snapshot. Pass exactly one of `lesson_slug` or `skill_name`. Restoring a lesson replaces the current same-slug section if present, otherwise re-adds it. Restoring a skill replaces the primary skill dir and mirrors it to the configured skill roots.
curator_reviewFire one curator pass. `force=True` runs even when CURATOR_INTERVAL_S=0 (daemon disabled). Use for one-shot triage or testing the prompt. `dry_run=True` short-circuits before the spawn — returns the capped inventory preview plus n_lessons/n_skills. No spawn, no cursor advance. Use to inspect the inventory shape before paying for the batched spawn.
curator_review_statusShow curator config + inventory fingerprints + latest REPORT path. Sanity-check for whether the daemon is alive, advancing the cursor, and producing REPORTs the user can read.
curator_runMove stale agent-created skills to archive. Lifecycle: active → stale when last activity > stale_after_days stale → archived when last activity > archive_after_days (also moves primary directory to .archive/ and removes its mirrors, so a sync cannot revive it) Activity is the last use, foreground view or creation. Patches do not count: autonomous loops patch skills routinely, which is maintenance, not proof that anyone relies on the skill. A skill must spend the gap between the two windows in 'stale' before it is archived, and renewed a…
db_compactShrink the DB file: VACUUM + mandatory dialog_fts rebuild. Run in a quiet window — VACUUM needs an exclusive lock and copies the whole file (minutes on a multi-GB DB); concurrent FTS searches during the vacuum→rebuild gap may map to wrong rows until the rebuild commits. Fails soft (with a retry hint) when the DB is busy.
db_deduplicate_embeddingsRemove base-table embedding BLOBs already represented in sqlite-vec. The operation is coverage-gated: rows without a confirmed vec0 mirror keep their BLOB fallback. Defaults to a report-only dry run. Run ``db_compact`` afterwards to return the newly freed pages to the filesystem.
dialectic_claimRegister a new claim about the user. Optionally seed with first piece of evidence — pass the supporting (or contradicting) quote in `evidence`, set `evidence_kind` to 'support' (default) or 'contradict', and supply its immutable `source` reference (for example `dialog:<uuid>`). Empty/`manual` means direct input from this session. `domain` is free-text; recommended values: 'style','workflow','values','context','skills','other'. Returns: 'ok id=<UCxxx> conf=<level> tier=<tier>'.
dialectic_evidenceAttach evidence to a claim. `kind`: 'support' | 'contradict'. `source` is a freeform pointer like 'thread:T7f3', 'verbatim:42', 'dialog:<uuid>', or 'manual'. `weight` ∈ [0,1] is the BASE trust (default 1.0); the effective stored weight is base × discount( WRITE_ORIGIN of the calling session). foreground sessions store `weight` as-is; shadow/background/candidate/curator forks store weight × 0.5 to prevent self-confirmation loops. Bumps support_count or contradict_count, recomputes confidence and tier (which may emit a tier_promoted/demoted event).
dialectic_mine_runFire one mechanical capture pass now (force=True runs even when the miner daemon interval is 0).
dialectic_mine_statusMiner config + buffer sizes + last 5 capture passes.
dialectic_observation_resolveMark a dialectic_observations buffer row 'processed' so the validator never re-interprets it. Called by the validator child after it has written (or deliberately skipped) the observation's claims/evidence.
dialectic_reviewList active claims filtered by confidence floor and optional domain. Retired/superseded claims are omitted by default. If `as_of` is provided (unix seconds or ISO-8601), returns claims whose valid-time interval covered that instant, including currently superseded claims that were valid then. `include_validity=True` appends state + valid_from/valid_to without changing the default output. `min_confidence`: one of 'low','medium','high','disputed'. Note that 'disputed' is treated as its own bucket (not ordered against the others) — passing `min_confidence='disputed'` returns only disputed. Form…
dialectic_supersedeRetire `old_claim_id` and register `new_claim` that refines or replaces it. The old claim moves to state='superseded' with superseded_by=<new_id>; its evidence is preserved (not deleted). If `quote` is provided, it seeds the new claim with one supporting piece of evidence sourced as 'supersede:<old_id>'. If `domain` is empty, the new claim inherits the old claim's domain. On hosts that advertise MCP form-mode elicitation, this asks the user to confirm/reject the supersede before mutating. Hosts without elicitation keep the prior behavior and apply immediately. Returns: 'ok new=<UCxxx> old=…
dialectic_synthesisTerse rendering of accumulated beliefs about the user, grouped by domain. Used as brief() input. Excludes low/disputed claims. By default only active claims are rendered; `as_of` switches to valid-time filtering, and `include_history=True` also includes superseded claims with their validity interval. Returns at most 12 lines. Tier markers in the output: ★ validated — load-bearing; act on it without asking · observed — pattern with backing; reference, mention if used ? hypothesis — currently testing (only shown if no observed/validated in same domain, to avoid sur…
dialectic_validate_runFire one validator pass. dry_run shows pending count + would_spawn without spawning or advancing the cursor.
dialectic_validate_statusValidator config + pending observation count + last 5 passes.
dialog_searchSearch ingested Claude Code transcripts. mode='hybrid' (default) combines semantic and FTS5 keyword via RRF. mode='semantic' is pure cosine. mode='fts' is pure FTS5 keyword.
distillMark content as worth carrying forward (distillation channel). `kind` ∈ {insight, pattern, anti-pattern, fix, terminology, concept}. `confidence` ∈ {low, medium, high}. `source_thread` optional. Other sessions can vote on it via vote_distill; export_distillates emits a curated jsonl bucket.
evolve_applyImplement a PROMOTED + not-yet-applied format-evolution suggestion. Spawns an `evolve_applier` child that: edits render_brief() in threadkeeper/brief.py to make the change; adds/extends a GOLDEN test asserting the new behavior appears AND the existing brief still renders; runs the FULL suite (`.venv/bin/python -m pytest -q`) until green; then opens a PULL REQUEST on a feature branch via `gh` — it NEVER pushes or commits to main. The applier daemon's landing sweep squash-merges the PR once GitHub reports it up to date with required checks green (THREADKEEPER_EVOLVE_AUTOLAND=0 leaves the merge …
evolve_apply_conflicted_prRepair an already-open applier PR that currently has merge conflicts. With `pr_number=0`, picks the oldest open same-repo applier PR (`roadmap/…` or `evolve/…` head branch) authored by the account `gh` acts as whose GitHub merge state is conflicted. With a number, validates that specific PR is open, applier-owned, and conflicted. The child resolves conflicts, runs the suite, and pushes the SAME PR branch; it never merges, opens a new PR, or marks a roadmap issue applied. The daemon's landing sweep merges the PR once GitHub reports it green.
evolve_apply_curator_reportApply a Curator advisory report using the existing evolve_applier role. With no `report_path`, picks the latest complete `REPORT-*.md` in `THREADKEEPER_CURATOR_REPORTS_DIR` that has not already been marked applied. Single-flight: refuses while any evolve_applier child is in flight. The child may patch/delete memory through curated MCP tools, but does not edit code, use git, or open a PR.
evolve_apply_roadmap_issueImplement one open GitHub issue through the evolve_applier role. With `issue_number=0`, picks the next open issue: `roadmap`-labeled issues first, then FIFO by issue number. The child implements exactly one issue, runs the suite, opens a PR with `Closes #N`, then calls evolve_mark_roadmap_issue_applied(issue_number, pr_url).
evolve_apply_statusShow evolve-applier config + open applier PRs with their landing action + curator/evolve queues + running applier + the latest apply, landing, and recovery events.
evolve_decideTriage a pending format-evolution suggestion. Used by the autonomous evolve reviewer daemon (and available manually). `decision`: 'promote' — still relevant + worth doing → status='promoted', so the brief surfaces it sharply (★) for the foreground agent / human to ACTUALLY APPLY. Applying edits format/code — that stays a foreground/human action; this tool never applies. 'dismiss' — duplicate of another suggestion, superseded, or stale → status='dismissed', dropped from the pending queue. `reason`: one line (esp. which #id it duplica…
evolve_formatPropose a change to the brief format itself. The format is not fixed — this is how it adapts. Examples: 'field X unused this session, drop it'; 'add field failed_attempts under each open thread'; 'shorten Z to single token'.
evolve_issue_createCreate a reviewer roadmap issue through the mechanical dedup gate. The gate checks open and closed GitHub issues, the local reviewer issue ledger, and already-filed fingerprints before calling `gh issue create`. Duplicate skips and successful files are recorded as events.
evolve_mark_appliedMark a format-evolution suggestion as APPLIED — called by the evolve_applier child after it has opened the PR. Sets applied=1 (so the suggestion drops out of the brief / evolve_review) and records the PR url. `pr_url` is REQUIRED and must be non-empty: this is the PR gate — never mark a suggestion applied without a real pull request. The PR still lands only through branch protection once its checks pass.
evolve_mark_curator_report_appliedMark a Curator report as processed by the evolve_applier child. The report must live under `THREADKEEPER_CURATOR_REPORTS_DIR`, match `REPORT-*.md`, contain `CURATOR_PASS_COMPLETE`, and still match the parent-verified content hash. The hash and applied event prevent a swapped report or replay from being accepted.
evolve_mark_roadmap_issue_appliedMark a roadmap issue as handed off — called by evolve_applier only after it has opened a real pull request for that issue.
evolve_prune_managed_venvFree the default managed checkout's `.venv` after explicit confirmation. Pass `confirm=True` to delete only that auto-managed virtualenv. Its clone remains intact and the next Evolve pass rebuilds the environment. This refuses `THREADKEEPER_EVOLVE_REPO_ROOT` and auto-clone-disabled setups, so it never prunes an operator-selected checkout.
evolve_research_handoffSubmit one bounded digest for an assigned Evolve research pass. This tool deliberately has no destination argument. Only the spawned ``evolve_researcher`` that owns the parent-authorized ``pass_id`` can make one atomic submission; malformed, oversized, stale, replayed, or unowned submissions are refused and recorded as handoff telemetry.
evolve_reviewList pending (or all) format-evolution suggestions for review.
expand_conceptFull description + triangulation_notes for one concept.
export_distillatesWrite distillates with vote_sum >= min_vote to a jsonl bucket. Marks them exported_at so the same item isn't re-exported next call. Default output: ~/.threadkeeper/tasks/distillates.jsonl.
extract_recentScan recent dialog_messages and enqueue heuristic candidates.
find_invariantsFind recurring assistant-side patterns that survive prompt variance. Algorithm: 1. Pull recent assistant messages from dialog_messages (with embeddings). 2. Greedy cluster by response embedding cosine ≥ response_cohesion. 3. For each cluster (size ≥ min_cluster_size), find each response's immediately-preceding user prompt in the same conversation. 4. Score = avg_response_similarity × (1 - avg_prompt_similarity). High = my response stays the same shape while prompts vary widely. Returns top_n clusters with sample response, scores, and counts. Requires semantic embeddings (se…
find_missed_spawnsFind assistant responses that decomposed into independent blocks but were answered linearly (no spawn() call nearby). Algorithm: 1. Pull recent assistant messages (last `window_days` days, length ≥ `min_response_len`, excluding subagent jsonls). 2. For each, count top-level numbered items and H2/H3 headers. 3. Mark as `decomposable` if numbered ≥ `min_numbered` OR headers ≥ `min_headers`. 4. For each decomposable response, check whether any tasks row with parent_cid = response's session_id has started_at within ±10 min of the response. If none → missed_spawn. 5. …
forgetForget one session/cid/thread/dialog UUID. Defaults to dry-run and reports affected rows per store. Set ``dry_run=False`` to delete dialog rows, FTS/vector sidecars, directly sourced dialectic/verbatim/extract/task records, and matching task spool files. Lessons and skills that cite the selector are listed for manual re-review instead of silently retained.
idle_threadMark thread idle (paused, may return). Auto-revives to active on next note().
inboxRead signals addressed to me (whispers + broadcasts). `unread_only=True` (default) returns only what hasn't been seen yet, and if `mark_read=True` marks them read on this call. Set both False to re-read history.
ingestIngest new transcripts. Initial and periodic passes run asynchronously in the daemon host; call manually for backfill or after a long absence. `max_msgs` bounds the new messages taken from each CLI.
lesson_appendMaterialize a class-level lesson into ~/.threadkeeper/lessons.md. `title` is sluggified to a stable key — repeated calls with the same title overwrite the existing section (idempotent). `body` is markdown; goes verbatim into the section body. `summary` is an optional one-liner rendered as a blockquote right after the header. Use when the body is long and a TL;DR helps the next agent decide whether to read further. `source` is a provenance tag — typically a thread id ("Tabc123") when written by review_thread, or "shadow" when written by the shadow_review observer. Empty is fine. Every new …
lesson_getReturn the full body of one lesson by slug. Useful when `lesson_list` surfaced something you want to read in full.
lesson_listCompact listing of materialized lessons. Without `query`, newest first. With `query` (for example the user's opening request), the lessons most relevant to it, best first, with a relevance score — use this to find what applies to the task at hand, since the newest lessons are rarely the relevant ones. Format per line: `<age> <slug> src=<src> [score=<s>] <summary>`
lesson_neighborsSuggest nearby existing lessons before creating a new one. Pass the prospective title, summary, and body before ``lesson_append``. The result is a ranked, read-only list of semantic neighbors. Read a relevant slug and either patch/consolidate it or add a ``[[slug]]`` link to the new lesson while it is still being authored.
lesson_patchReplace one unique substring in a materialized lesson. ``old_string`` must occur exactly once within the lesson's markdown body. The operation preserves the lesson's heading, summary, provenance, and timestamps, unlike a wholesale ``lesson_append`` replacement.
lesson_removeRemove one materialized lesson section by slug. Refuses protected lessons unless `force=True` is called from a foreground writer. Curator/evolve cleanup may pass force accidentally or maliciously; non-foreground force is ignored. Pass ``replacement_slug`` when this is a consolidation to redirect every inbound ``[[wikilink]]`` to the umbrella lesson; without it, the successful response lists all dangling sources.
lesson_restoreRestore the latest trashed lesson section for `slug`. Refuses to overwrite an existing lesson with the same slug.
lesson_violationRecord that an EXISTING lesson's rule was broken again (#228). Call this instead of appending a duplicate lesson when the dialog shows the user correcting behavior that `slug` already covers. `evidence` is a one-line description of the repeat (no secrets or transcript dumps). One conversation counts once per lesson per day. At LESSON_VIOLATION_THRESHOLD violations in the window the lesson is memory-insufficient and should become an active guard (a PreToolUse-style hook) rather than more memory.
linkCreate a typed edge between two entities. Kinds: thread, note, concept, distill, task, signal, probe. Relations (suggested, free-form ok): refines, contradicts, exemplifies, depends_on, mentions, elaborates, supersedes. Existing edge with same (from, to, relation) is replaced (re-linking means updating weight/timestamp, not duplicating).
list_conceptsList registered concepts, filtered by minimum confidence.
live_statusSee what OTHER concurrent Claude sessions did since this session last polled. Call when brief() shows live=N where N>0, or proactively when you suspect a parallel instance is working on something relevant. Advances this session's cursor by default; pass advance_cursor=False to peek without consuming.
mark_skill_materializedClose the Learning loop: record that a closed thread's insights were written into a skill. Stops the brief()'s `skill_hint` nudge from firing for this thread. Also appends a `move` note pointing at the skill path so future briefs surface the link. Pass the absolute path to the SKILL.md (or skill directory) when known; leave empty if you only want to silence the hint without recording a path. When a path is provided, thread-keeper also mirrors that skill directory into every configured native skills root (Claude, Codex, Antigravity, shared agents, and ~/.threadkeeper/skills) on a best-effort …
memory_authorize_actionCheck the authority gate before a consequential memory-driven action. Low-authority memory is denied unless it has an independent trusted root or the caller explicitly records confirmation with ``confirmed=True``.
memory_guard_checkRun one memory-guard pass now. Defaults to dry-run and no desktop notification. Pass dry_run=False to SIGTERM thread-keeper server processes over the kill threshold.
memory_guard_reclaimUnload thread-keeper model/caches now. `scope`: `self` trims this MCP process immediately. `all` also queues trim requests for peer thread-keeper server processes; peers handle the request on their next guard tick.
memory_guard_statusShow memory-guard thresholds and current thread-keeper RSS rows.
memory_scope_statusShow the current path-free namespace and legacy migration accounting. Unresolved rows are excluded from automatic recall until an operator classifies them, so this gives a visible audit surface after upgrading.
model_route_writeRecord the model router's decision for every role in this pass. Only the spawned router child carrying the parent-issued pass id may call this. `decisions` is a list (or a JSON-encoded list) with one object per role: {"role", "cli", "model", "effort", "reason"}. Every decision is checked against the local model catalog; any problem rejects the whole call and lists every error so the router can fix them and call again.
model_router_runRun one model-router tick now. force=True starts a pass even when none is due (a pass that is already running is never duplicated).
model_router_statusModel-router config, last pass, and the current route of each auto role.
mp_cleanupKill orphaned thread-keeper processes (parent gone AND heartbeat stale for > 5 minutes). Defaults to dry-run — pass dry_run=False to actually send signals. force=True uses SIGKILL instead of SIGTERM. Never touches the current process or processes whose parent is still alive. Safe to run repeatedly.
mp_dashboardOne-call rollup of the whole thread-keeper system: store sizes, how often each autonomous loop fired (in the last `window_days` and 30d), and what those loops actually produced (skills materialized, candidates accepted vs rejected, tier promotions). Read-only; no spawn, no mutate. Use to see system health at a glance, spot loops that fire but produce nothing (e.g. shadow_review passes >> skills materialized), or a backlog building up (e.g. extract_candidates pending climbing).
mp_healthDiagnostic snapshot of every running thread-keeper server process on this machine. Shows pid, parent status, RSS, heartbeat age, and whether each is classified as orphaned (parent gone + no fresh heartbeat from its session). Self (the process answering this call) is always marked is_self=true and never flagged as orphan. The text view also includes each registered daemon thread's liveness verdict. Returns structuredContent (MpHealth) plus the legacy text block.
neighborsBFS the graph from a starting node up to `depth` hops away. Returns each visited node with its kind, id, and a short content snippet pulled from its native table. Both directions of edges traversed.
noteAdd a note to a thread. Write terse, optimized for future-Claude. `kind`: 'move' (we tried/decided X), 'failed' (tried X, broke because Y), 'insight' (crystallized observation), 'open_q' (something to come back to). Reopens the thread: a note on an `idle` OR `closed` thread revives it to `active`. Closed is not terminal — returning to a topic (adding a note) brings it back. This is what makes aggressive auto-close safe: the thread-janitor can close idle threads to harvest skills, and you just note() to pick any of them back up.
open_dashboardOpen ThreadKeeper dashboardOpen the portable, display-only status dashboard when the host supports MCP Apps.
open_dialog_windowOpen a Terminal window that tails the live cross-session signal log. Every broadcast/whisper/question/answer is appended to the log in real time; this lets the user see the dialog between concurrent claude sessions as it happens. The window stays open until you close it (it's a `tail -F`, no exit). Title: 'thread-keeper-dialog'.
open_threadOpen a thread. `question` should be terse (5-15 words, the open question). `parent_id` optional — pass an existing ID like 'T7f3' for a child. Returns new ID.
peersList concurrent claude conversations active in the last `window_min`. Activity inferred from dialog_messages (ingested live). For each peer returns: cid, last user message snippet, age, message count. Self is marked with `*`. Empty if you're alone.
pending_distillatesList distillates with vote_sum >= min_vote, not yet exported.
pickup_candidatesSurface unresolved threads that are stale and unclaimed — candidates for self-initiated pickup when context is free. Ranks by oldest last_touched_at among active+idle threads with no current claim. Adds a one-line summary so caller can decide which to claim.
presenceList concurrent Claude sessions with heartbeats within threshold (default 5 min). Excludes self. Useful for understanding who else is currently active before making changes.
record_attemptRecord a self-test outcome. Updates reliability aggregates. Use for both registered probes (pass `probe_id`) and ad-hoc self- observations — e.g. you noticed yourself miscounting items in this very turn → record_attempt('count_long_context', false, note='said 32, actual 47').
register_conceptRegister a concept that lacks a precise human name. `description` should describe the phenomenon through EXAMPLES, not with a canonical label — naming it locks it back into a human discipline. `triangulation_notes` (optional): the paraphrase runs that surfaced the invariant. `confidence` ∈ {low, medium, high}.
register_probeRegister a self-test probe: a known weak-spot task with a verifier. `grader`: 'regex' (pattern match in response), 'exact' (substring), or 'manual' (claude self-grades — always counts as failure unless caller explicitly confirms success via record_attempt). `expected_pattern` optional for 'manual'. Categories should be claude-shape: 'count_long_context', 'date_arithmetic', 'recall_verbatim_block', 'detect_contradiction', 'follow_negative_instruction', 'preserve_list_order', 'respect_length_limit', 'needle_mid_context', 'fact_vs_inference', 'notice_absence', 'strict_format_compliance', 'uncer…
reject_candidateMark rejected. Reason appended to rationale for heuristic tuning.
release_pickupRelease a claim. The claimant or its spawned child can release.
reliability_forReliability stats for one category over a window.
respondAnswer a specific question (signals.id) with a directed whisper. Use after seeing a `+question` entry in inbox()/wait(). Marks the original question as read and inserts an `answer` whisper to the asker.
review_candidatesstatus ∈ {pending, accepted, rejected, all}. Newest first.
review_threadSpawn a background review of a closed thread to extract memory/skills. Spawns a separate Claude process that reads the thread's notes and writes back via memory/skill tools. `focus`: 'memory' | 'skills' | 'combined' (default). Picks the review prompt. `mode`: 'auto' — spawn an invisible background child with the review prompt + thread notes. Returns the spawn task_id. Child's write-origin is set to 'background_review' so curator can later prune what it produces. 'inline' — return the full prompt + notes context as a string; the …
run_probeSurface a registered probe for self-attempt. Returns the prompt and the grader hint. After attempting, call record_attempt(category, success=true/false, probe_id=...) — the harness doesn't auto-grade because attempting and judging are the same model.
searchSearch current-project notes plus global/shared memory. Set ``cross_project=True`` only for an intentional cross-project recall; output marks every result's scope and an audit event is recorded.
search_via_parentDelegate a semantic search to the parent process (or any peer with embeddings loaded). For light children spawned with THREADKEEPER_NO_EMBEDDINGS=1, this is how you reach into the shared DB's semantic index without loading PyTorch yourself. Mechanism: posts a 'search_request' signal addressed to the parent's cid (auto-resolved via tasks.parent_cid; falls back to broadcast if none). The parent's search_proxy daemon answers with a 'search_response' signal. This tool blocks until reply or timeout_s. `scope`: 'notes' (default) or 'dialog'. `mode`: 'hybrid'|'semantic'|'fts' (dialog scope only). …
session_endMark current session ended with optional terse summary.
shadow_review_runFire one shadow-review pass. `force=True` runs even when the daemon is disabled (interval=0). Used by tests and one-shot triage. `dry_run=True` short-circuits before the spawn — returns the dialog dump that WOULD be evaluated, plus n_chars and high-water cursor. No spawn. No cursor advance. Use this to inspect candidate windows before paying for an evaluator child.
shadow_review_snapshotWrite the current shadow-review telemetry as a markdown snapshot.
shadow_review_statusShow shadow-review config, recent passes, and production telemetry. Snapshot for sanity-checking that the daemon is alive and advancing its cursor, PLUS the production-validation rollup (issue #6): for the 24h and 7d windows it aggregates how often the daemon fired, the outcome mix (no_window / too_short / spawned / deferred / error), the MATERIALIZED-vs-SKIP hit rate of spawned evaluator children, durable skill writes attributable to shadow_review, and the total Claude-spawn time spent — so you can tell whether the loop earns its Opus minutes or just emits SKIPs. Use ``shadow_review_snapsho…
skill_listList skills with telemetry. Format: <name> tier=<hypothesis|observed|validated> origin=<...> state=<active|stale|archived> uses=N fg_uses=N views=N patches=N wrong=N pinned=0/1 last_active=<age> Listing is not consultation: it never touches ``view_count``, ``last_viewed_at`` or the stale state. Autonomous loops list every skill on each pass, so counting a listing would make every skill look recently consulted and nothing could ever go stale.
skill_manageCreate, edit, patch, or delete skills under the primary skills root. Atomic primary write with frontmatter validation before disk hits, then best-effort mirror into every configured skill root. Actions: create — write a brand-new skill. Requires `name` + `description` + `content` (the body markdown WITHOUT frontmatter; the tool prepends a valid frontmatter block). Pass full `content` starting with '---' to skip the auto-frontmatter and supply your own. edit — overwrite SKILL.md wholesale. Requires `name` + `conte…
skill_recordRecord usage telemetry for a mirrored skill. `kind`: 'use' | 'view' | 'patch' | 'create'. Bumps the corresponding counter + timestamp in skill_usage. The curator reads these to decide what to archive. `outcome` (optional, meaningful with kind='use'): 'helped' | 'partial' | 'wrong'. When set, also emits an `events.kind='skill_outcome'` row so the curator can identify skills that fire often but consistently give 'wrong' verdicts — those are false-positive candidates to PRUNE. The 'wrong' outcome is the primary signal an agent has to say "I consulted this skill, it didn't actually apply / was …
skill_validateValidate ThreadKeeper-managed skills across supported CLI consumers. With `name`, returns the complete deterministic record for one logical skill, including ThreadKeeper/Claude Code/Codex/Agent Skills validation, mirror hashes, local-link findings, exact duplicates, and semantic candidates involving that skill. Curator must call this after every skill mutation. Without `name`, returns a compact complete numbered inventory. Semantic candidates are leads, never automatic delete decisions.
spawnLaunch a new child session in parallel. This is the public MCP surface. `role` selects a cognitive stance and `write_origin` labels ordinary child provenance; neither grants elevated permissions. Privileged Evolve children use private server-owned launchers. Watchdog continuation retries use `_spawn_impl` so retry lineage/config fields do not leak into the normal tool contract.
spawn_budget_setOverride the spawn-budget cap for this process (in MB). Set 0 to disable enforcement. Does NOT persist across restarts — set THREADKEEPER_SPAWN_BUDGET_MB env for persistence. Useful when a heavy task needs a higher temporary ceiling, or to drop the cap mid-session if you notice the laptop struggling.
spawn_budget_statusReport current spawn-budget usage: cap, used, free, plus per-running-task RSS. Used to decide whether another spawn() will be admitted. Values come from the budget daemon (refreshes every SPAWN_BUDGET_POLL_S seconds via `ps`). Just-spawned tasks show their initial estimate until the daemon catches up. Visible (pid=0, Terminal-launched) spawns are tracked too: the daemon resolves their live pid from the forced session-id and measures real RSS, and reaps a row whose cid never resolves past SPAWN_VISIBLE_TTL_S (#64). Returns structuredContent (SpawnBudgetStatus) plus the legacy text block.
spawn_statusShow which CLI thread-keeper detected as its host, and which CLI each spawn role resolves to (after env + file overrides). Use to sanity-check spawn config when you want loops to fire through a specific agent. Resolution priority (highest first), all in ~/.threadkeeper/.env: • THREADKEEPER_SPAWN__LOOP__<ROLE>=<cli> • THREADKEEPER_SPAWN__DEFAULT=<cli> • active CLI detected at startup • final fallback: claude Manual model pinning: • THREADKEEPER_SPAWN__MODEL__<CLI-or-ROLE>=<model> Manual reasoning effort: • THREADKEEPER_SPAWN__EFFORT__<CLI-or-ROLE>=<level> Returns structuredConte…
style_setSet a stylistic running rule. Examples: lang=ru | prose=lean | allow=half-baked,weird | deny=sycophancy,headers
sync_nowReconcile with every configured peer right now (bidirectional). Returns per-peer (pulled, pushed) counts or an error marker.
sync_peersList the configured sync peers (THREADKEEPER_SYNC_PEERS).
sync_statusCross-machine sync status: migrated?, this node id, peer count, listen address, oplog size, and how many origin nodes this DB has seen.
tag_signalManually attach a signal to a task. Useful when retroactively building a task-thread (auto-tagging happens at signal-emit time when the cid matches a known spawned_cid).
task_logsRead tail of a spawned task's captured stdout/stderr log. Only works for tasks spawned with `capture_output=True` (default). Returns the last `tail_lines` lines or 'no_log' if the task ran with capture_output=False or the log file is missing.
task_threadReplay a spawned task as a chronological thread: every signal tagged with the task_id (or to/from the task's spawned_cid), plus optionally notes added during the task window.
tasksList spawned tasks: id, pid, status, elapsed, spawned_cid (if linked), prompt prefix from the last persisted reconciliation.
tasks_refreshReconcile tracked task lifecycle and spawned-session links now. This is the explicit write action for process reaping and lazy child CID linking. Read-only task/status surfaces only show the persisted cache.
tournamentSpawn N children with different roles on the same prompt, then collect their answers via a tagged broadcast and return a comparison. `roles`: comma-separated role names. Predefined: skeptic, generator, critic, archivist, synthesizer, explorer, executor. Custom names allowed (child gets generic instruction). Each role gets a distinct system prompt addendum encoding its mindset. Each child is told to broadcast its final output as exactly: [<tournament_id>] [<role>] <answer> Parent polls signals every 2s for matching prefixes until all answered or timeout. Returns: a per-role digest. Child…
unlinkRemove an edge by id.
validate_threadsHeuristic triage of active threads — propose (dry_run=True, default) or apply (dry_run=False) close/idle actions per category. Categories (first match wins): no_notes_old no notes + age ≥ no_notes_days → close shipped last-note shipped-marker + settled → close (outcome=last_move) dropped_open_q last note open_q, unfollowed → close stale_idle no touch ≥ stale_days → idle (not close) Idle threads are never touched. shipped_markers is a comma-separated list of extra tokens to OR into the default English+Russian regex.
verbatim_userCapture a user quote worth surfacing in future briefs. Use when the user's exact phrasing matters (sharp reframes, decisions, pushback).
vote_distillVote on a distillate, weight ∈ [-1, +1]. One vote per cid; re-voting overwrites your previous vote. Updates aggregate vote_sum/vote_count.
waitBlock until a new signal arrives for me or `timeout_s` elapses. Returns immediately if there are unread signals. Otherwise polls the signals table every 250ms. Use this for realtime turn-based exchange with peers: one side waits, the other side broadcasts/whispers/responds. `kinds`: comma-separated filter ('whisper,question,answer,broadcast'); empty = any. `timeout_s` is clamped to [1, 120] (mcp tool call has its own deadline; don't oversleep).
weak_spotsList categories ranked by recent failure rate (min 3 attempts in 30d), plus registered probe categories with no attempts yet (= unknown, equally important to test).
whisperPost a message visible only to the specified conversation_id. Use peers() to discover available cids. The 8-char prefix shown there is enough — it'll be matched as prefix. Use whoami() to get your own cid (rarely needed; messages from self to self are dropped).
whoamiReturn this conversation's detected conversation_id + how we know. Resolution order: - 'forced': THREADKEEPER_FORCE_CID env (set by spawn() for children) - 'ppid': walk up process tree → claude --resume/--session-id <uuid> - 'mtime': fallback heuristic (latest jsonl mtime; flaps under concurrent peer activity)
wikilink_healthList unresolved ``[[slug]]`` links in all lesson and skill bodies. This detector is read-only. It reports each dead target with the lesson or skill that references it; repair remains a separate curator action.
workflow_retention_previewPreview terminal Curator/Evolve artifact compaction without deleting. The retention daemon runs the same policy on its next enabled tick. Use this dry-run-first view to inspect candidate rows, files, bytes, and the oldest retained Curator pass.
Compare and alternatives
Featured in
Signals
- Stars
- 13
- Forks
- 4
- Open issues
- 21
- Weekly downloads
- 339
- Last commit
- Oct 23, 2026 (5 days ago)
- Last release
- Oct 23, 2026 (5 days ago)
- Last package publish
- Oct 23, 2026 (5 days ago)
From GitHub (fetched Oct 24, 2026) and the package registry.
Details
- Registry name
io.github.po4erk91/thread-keeper- Version
- 0.13.1
- Auth
- No auth
- Packages
- pypi threadkeeper
- License
- MIT
- Repository
- github.com/po4erk91/thread-keeper
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
Cite this page
thread-keeper MCP server. Agent Mart. https://agentmart.dev/connectors/po4erk91-thread-keeper (last updated 2026-10-24)