| observe | Record one observation of a behavioral pattern; increments its confidence counter. Use this to log anything you want the agent to learn over time: a tool
sequence that worked, a user preference, a recurring fix, or a combo
of tools used together. Call once per occurrence — repeated calls on
the same pattern raise its confidence (1=new, 5=mature, 10=rule).
Do NOT use this for one-off notes; those belong in regular memory.
This tool is for patterns that may recur and become reliable.
Idempotent on pattern key: same pattern string merges into one entry.
Args:
pattern: Pattern key following the convention prefix:body.
Examples: "seq:lint->fix->lint" (tool sequence),
"pref:style=black" (user preference),
"fix:missing-import" (recurring fix),
"combo:pytest+coverage" (things used together).
category: Pattern type. One of: "sequence", "preference",
"fix_pattern", "combo". Defaults to "sequence".
source: Originating tool/agent name (e.g. "claude-code",
"cursor"). Empty string means unknown. Useful for filtering.
project: Project fingerprint. Empty string auto-detects from cwd
(recommended). Pass explicitly only for cross-project imports.
explain: One-line human-readable rationale for why this pattern
matters. Surfaces in suggestions and CLAUDE.md exports.
Returns:
Dict with keys: "pattern", "confidence" (int), "level"
("seedling" | "mature" | "rule"), "created" (bool — true on
first observation).
|
| suggest | Retrieve mature patterns (confidence >= 5) to guide your current behavior. Call this at the start of a task to learn how similar work has been
handled before: which tool sequences worked, what the user prefers,
which fixes recur. Results are sorted by confidence descending, so
the most-trusted patterns come first.
Prefer this over list_instincts when you want only validated patterns
(not every observation). Use list_instincts to see seedlings too.
Args:
project: Filter by project fingerprint. Empty string returns the
current project's patterns plus global ones. Pass a specific
fingerprint to audit another project.
category: Filter by pattern type. One of: "sequence", "preference",
"fix_pattern", "combo". Empty string returns all categories.
keyword: Substring match against pattern key, metadata, and
explain text. Case-insensitive. Empty string disables filter.
compact: True (default) returns ~50 tokens per pattern (key +
confidence + level only) — ideal for agent context. False
returns full metadata and explain text (~500 tokens each) —
use for audits or UI display.
Returns:
Dict with keys: "suggestions" (list of patterns, compact or
full depending on flag), "count" (int), and in compact mode a
"hint" pointing to get_instinct for details.
|
| list_instincts | List recorded patterns with optional filters; includes low-confidence observations. Unlike suggest() — which returns mature-only, compact payloads — this
surfaces seedlings too. Useful for audits, pruning noise via gc() or
alias_pattern(), and debugging why a pattern has not promoted.
Read-only; records sorted by confidence descending, then last_seen
descending.
For day-to-day agent guidance prefer suggest(). For keyword search
use search_instincts(). For a single exact-key lookup use
get_instinct().
Args:
min_confidence: Minimum observation count (inclusive). Examples:
1 returns everything including one-offs; 5 returns mature+;
10 returns rules only.
category: Filter by pattern type. One of: "sequence",
"preference", "fix_pattern", "combo". Empty string = all.
project: Filter by project fingerprint (repo hash or path hash).
Empty string returns every project including the global ""
bucket.
limit: Maximum records to return. Default 50; raise for full
dumps, lower for top-N views.
Returns:
{"instincts": [<record>, ...], "count": int, "hint": str}
Each <record> has: "pattern" (str key with prefix),
"category" ("sequence"|"preference"|"fix_pattern"|"combo"),
"confidence" (int observation count),
"promoted" (0=raw, 1=mature, 2=rule, 3=universal),
"level" ("raw"|"mature"|"rule"|"universal" — string form of promoted),
"project" (str fingerprint, "" = global),
"source" (str origin tag), "metadata" (parsed dict),
"explain" (str human-readable note),
"first_seen" and "last_seen" (ISO 8601 timestamps).
"hint" points to suggest() / search_instincts() / get_instinct()
as next-step tools depending on the audit goal.
|
| get_instinct | Fetch the full record for one pattern by its exact key. Exact-match lookup; keys are case-sensitive and must include the
category prefix. Typically called after suggest() returns a compact
entry and you want the full context. Read-only.
For substring or keyword search use search_instincts(). For browsing
by category/project without a key use list_instincts(). For the
confidence timeline of this pattern, pair with history(pattern).
Args:
pattern: Exact pattern key including its category prefix.
Examples: "seq:lint->fix->lint", "pref:style=black",
"fix:null-deref-guard", "combo:eslint+prettier". Case-sensitive.
Returns:
On hit — the full record: {"pattern": str, "category":
"sequence"|"preference"|"fix_pattern"|"combo", "confidence": int,
"promoted": 0|1|2|3, "level": "raw"|"mature"|"rule"|"universal",
"project": str ("" = global), "source": str, "metadata": dict,
"explain": str, "first_seen": iso8601, "last_seen": iso8601}.
On miss — {"error": "Not found: <pattern>"}. Callers must check
for the "error" key before assuming a record was returned.
|
| consolidate | Re-evaluate pattern levels; promote via confidence thresholds and detect chains. Promotes patterns that crossed a level boundary since the last run:
raw -> mature (confidence >= 5), mature -> rule (>= 10), rule ->
universal (observed in 2+ distinct projects). Patterns seen in the
last 7 days get a +1 recency bonus toward the mature threshold.
Side effects: (1) writes new "promoted" values, (2) runs detect_chains()
to discover sequential patterns from the observation log, (3) rebuilds
the FTS5 search index. Idempotent across promotion: already-promoted
patterns are untouched. session_summary() invokes this automatically.
Call after a bulk import_patterns() / import_claude_md() or at the
end of an agent session so downstream queries (suggest,
export_rules, inject_claude_md) see the latest promotions.
Returns:
{"promoted_to_mature": int, "promoted_to_rule": int,
"promoted_to_universal": int, "chains_detected": int,
"chains_created": int, "total": int, "timestamp": iso8601}
"total" is the current row count after promotion. "chains_*"
fields reflect the bundled detect_chains() pass: "detected"
counts candidate pairs above threshold, "created" counts new
seq:A->B records actually inserted.
|
| stats | Summary of the instinct store: totals, level distribution, category breakdown. Use for a quick health check — how many patterns exist, how they
are distributed across promotion levels, which categories dominate,
and the average/peak confidence. Read-only; no side effects; no
params.
For a time-ranged view of what's been observed recently use
trending(days). For end-of-session snapshot that also runs
consolidate use session_summary().
Returns:
{"total": int, "raw": int, "mature": int, "rules": int,
"universal": int, "avg_confidence": float, "max_confidence": int,
"by_category": {<category>: {"count": int,
"avg_confidence": float}}}
Level counts partition "total": raw + mature + rules +
universal == total. "by_category" keys are a subset of
("sequence", "preference", "fix_pattern", "combo") — only
categories actually present appear as keys. Empty store returns
zero counts everywhere, not an error.
|
| search_instincts | Find patterns by keyword across pattern key, metadata, and explain text. Uses SQLite FTS5 for ranked, fast retrieval. Falls back to LIKE
substring matching automatically when the query contains special
characters that FTS5 cannot tokenize. Read-only; no side effects.
FTS5 query syntax:
- Bare word "lint" — matches any record containing the token.
- Multi-word "lint fix" — implicit AND; both tokens must appear.
- Explicit "lint OR format" — either token.
- Phrase '"exact phrase"' — contiguous match (note embedded quotes).
- Prefix "claude*" — any token starting with claude.
- Negation "lint NOT prettier" — excludes matches containing the
second term.
For exact-key lookup use get_instinct(). For unfiltered browsing or
category/project filters without a keyword, use list_instincts().
Args:
query: Search term in FTS5 syntax (see above). Case-insensitive.
Special characters trigger automatic LIKE fallback.
limit: Maximum results to return. Default 20; raise for broad
audits, lower for suggest-like focused views.
Returns:
{"results": [<record>, ...], "count": int, "hint": str}
Each <record> has: "pattern" (str key with prefix),
"category" ("sequence"|"preference"|"fix_pattern"|"combo"),
"confidence" (int observation count),
"promoted" (0=raw, 1=mature, 2=rule, 3=universal),
"level" ("raw"|"mature"|"rule"|"universal"),
"project" (str fingerprint, "" = global),
"source" (str origin tag), "metadata" (parsed dict),
"explain" (str human note),
"first_seen" and "last_seen" (ISO 8601 timestamps).
Ordered by confidence descending. Empty "results" means no match;
the "hint" points to list_instincts() or get_instinct() as
fallback next steps.
|
| export_rules | Export promoted-level patterns (rule + universal) as structured JSON. Filters to patterns with promoted >= 2 — the threshold set by
consolidate() after enough reinforcement. Intended for programmatic
consumption: analytics pipelines, sibling agents, external
dashboards. Read-only; takes no parameters.
For human-readable Markdown use export_claude_md(). For platform-
specific formats use export_platform() (.cursorrules, .windsurf,
AGENTS.md) or export_skill() (anthropics/skills SKILL.md). For
lower-confidence audits use list_instincts(min_confidence=5).
Returns:
{"rules": [<record>, ...], "count": int, "hint": str}
Each <record> has: "pattern" (str key with prefix),
"category" ("sequence"|"preference"|"fix_pattern"|"combo"),
"confidence" (int observation count),
"promoted" (2=rule, 3=universal — lower levels are filtered out),
"level" ("rule"|"universal"),
"project" (str fingerprint, "" = global),
"source" (str origin tag), "metadata" (parsed dict),
"explain" (str human note),
"first_seen" and "last_seen" (ISO 8601 timestamps).
Sorted by promoted descending, then confidence descending.
Empty "rules" means no pattern has reached rule level yet —
the "hint" directs to run consolidate() first, then retry.
|
| alias_pattern | Redirect all future observations of one pattern onto another. Use this to merge duplicates: when the same concept has been recorded
under two keys (e.g. "seq:a->b" and "seq:a -> b" with a space), alias
the stray into the canonical one. Existing confidence is summed into
the target so no learning is lost.
The target must already exist. Use find_duplicates() to discover
merge candidates, then call this to apply them.
Args:
pattern: The key to retire. Future observations of this key will
be rerouted silently.
target: The canonical key to absorb into. Must already exist in
the store.
Returns:
On success: {"aliased": <pattern>, "target": <target>}.
On failure (target missing): {"error": "target pattern '<target>'
not found"} — check for the "error" key.
|
| import_patterns | Bulk-insert many patterns in a single call; faster than looping observe(). Each input row is routed through observe() so existing patterns
have their confidence incremented rather than overwritten, matching
single-call observe() semantics. If an input row specifies a
"confidence" higher than the current stored value, the record is
raised to that target value (never lowered). Rows with missing or
empty "pattern" are skipped.
For importing a CLAUDE.md Markdown file use import_claude_md()
which handles the backtick-wrapped pattern parsing for you. Run
consolidate() after a large import so downstream exports see the
fresh promotions.
Args:
patterns: List of dicts. Each dict requires "pattern" (str key
with category prefix). Optional keys:
- "category": "sequence" | "preference" | "fix_pattern"
| "combo". Defaults to "sequence" if omitted.
- "source": str origin tag (e.g. "codex", "manual").
- "project": str fingerprint. Empty = global.
- "metadata": dict of free-form JSON-serializable data.
- "explain": str human-readable note (truncated at the
store-configured max length).
- "confidence": int starting count. Defaults to 1. If
greater than the current stored confidence for a
pre-existing pattern, the record is raised to this
value.
Returns:
{"imported": int, "updated": int, "errors": int, "hint": str}
"imported" = rows that created a new pattern. "updated" =
rows that reinforced an existing pattern. "errors" = rows
skipped because "pattern" was missing/empty or observe() raised
(count only — see server logs for per-row reasons). "hint"
points to consolidate() as the recommended follow-up.
|
| session_summary | End-of-session snapshot: what was learned, what's mature, and housekeeping. Call this at the end of an agent session to get a one-call overview
suitable for a session log or memory append: recent activity (last
24h), top mature suggestions, and overall store stats.
Side effect: also runs consolidate() and rebuilds the FTS search
index. If you want a pure read-only summary, use stats() + suggest()
separately.
Args:
project: Project fingerprint to scope the summary. Empty string
auto-detects from cwd (recommended).
Returns:
Dict with keys: "session" (patterns_last_24h + recent list of
up to 10), "suggestions" (count + top 5 by confidence),
"stats" (full stats() payload), "consolidation"
(promotion counts from the consolidate() call).
|
| detect_chains | Mine the observation log to auto-create "seq:A->B" patterns for recurring chains. Scans the confidence log for pairs of patterns observed close in
time, and creates a new sequence pattern for any pair seen enough
times. This is how instinct learns tool chains without being told
what to track.
Safe to run periodically. Does not overwrite existing chains; only
appends confidence for new pairs.
Args:
window_minutes: Maximum gap between two observations to consider
them sequential. Smaller (1-2) = tight chains only. Larger
(10+) = loose associations. Default 5 is a good balance.
min_occurrences: Threshold for recording a chain. A pair must
appear at least this many times in the log before it becomes
a pattern. Default 3 filters out one-off coincidences.
Returns:
Dict with keys: "chains_created" (int — new patterns added),
"chains_reinforced" (int — existing patterns whose confidence
rose), "candidates_seen" (int — raw pair count before threshold).
|
| effectiveness | Measure how often suggested patterns were reinforced by a later observe(). Each suggest() call logs the patterns it returned; each observe()
confirms the most recent unconfirmed suggestion for that pattern.
A high confirmation rate means the pattern is genuinely useful
guidance; a low rate means it is noise worth pruning via
alias_pattern() merges or gc() decay. Read-only.
For a raw observation-velocity view use trending(days). For
promotion/level distribution use stats().
Args:
days: Look-back window in days. Default 30. Shorter (7)
surfaces recent drift; longer (90) measures long-term
value.
Returns:
{"patterns": [<row>, ...],
"summary": {"total_suggested": int, "total_confirmed": int,
"overall_rate": float, "period_days": int}}
Each <row>: {"pattern": str, "suggested": int,
"confirmed": int, "rate": float in [0.0, 1.0] rounded to
3 decimals}. Rows ordered by confirmed desc, then suggested
desc. "overall_rate" is total_confirmed / total_suggested
(0.0 when no suggestions in window). Empty "patterns" list
means no suggest() calls happened in the window — not an
error.
|
| trending | Rank patterns by observation velocity (reinforcements per window). Counts entries in the confidence log per pattern within the window
and returns the busiest. A brand-new pattern observed 10 times
today outranks a long-mature pattern idle for weeks. Falls back to
last_seen ordering for patterns with no log entries (pre-history
data). Read-only.
For all-time leaderboards use list_instincts(min_confidence=10).
For the confirmation-rate view of whether trending patterns were
actually useful, pair with effectiveness(days).
Args:
days: Window size in days. Default 7. Smaller (1) = what is
hot right now; larger (30) = what is steady over the
month.
limit: Max patterns to return. Default 10, ordered by window
observation count descending.
Returns:
{"trending": [<record>, ...], "period_days": int}
Each <record> is a full pattern record (see list_instincts
for field list) augmented with an extra field
"observations_in_period": int — the number of reinforcements
counted in this window. When the fallback path runs (no log
history), this field is absent; ordering is then by
"confidence" and "last_seen" descending.
"period_days" echoes the input so callers can cache results
against a window size.
|
| export_claude_md | Render rule-level patterns as Markdown ready to paste into CLAUDE.md. Use this when a Claude client needs a compact Markdown block of learned
rules to include manually in CLAUDE.md. It reads promoted rule-level
patterns only; no files are modified.
Produces one bullet per rule with pattern key, category tag, confidence
count, and explain text. The output is a freestanding Markdown section;
no surrounding headers or context are added.
For idempotent in-place injection into an existing CLAUDE.md (preserving
other content via marker tags), use inject_claude_md() instead.
For multi-platform output (Cursor, Windsurf, Codex), use
export_platform() instead.
Returns:
Dict with keys: "markdown" (str — the rendered block; empty
string if no rules exist), "rule_count" (int).
|
| export_skill | Package rule-level patterns as a SKILL.md file (anthropics/skills format). Builds a complete Skill document: YAML frontmatter (name,
description) followed by a Markdown body grouping each rule-level
pattern by category, with confidence and explain text. The returned
string is ready to write to disk as SKILL.md and install into a
skills-aware agent runtime (e.g. agentskills.io). Read-only.
For human-readable CLAUDE.md output use export_claude_md(). For
editor-specific formats (.cursorrules, AGENTS.md) use
export_platform(target). For raw JSON use export_rules().
Args:
name: Skill identifier written into the YAML frontmatter.
Becomes the Skill's name on disk. Default "instinct-rules".
description: One-sentence description in the frontmatter.
Empty string auto-generates "Learned patterns from N
observations" using the current rule count.
category: Filter rules by type. One of "sequence",
"preference", "fix_pattern", "combo". Empty string (default)
includes every category.
Returns:
On success: {"skill_md": str, "rule_count": int, "hint": str}.
"skill_md" is the full file content ready to write. "rule_count"
is parsed from the rendered body (number of rule bullets).
On empty store: {"skill_md": "", "rule_count": 0, "hint": str}.
"hint" explains the promoted >= 2 prerequisite and directs the
caller to run consolidate() first so mature patterns can cross
the threshold.
|
| inject_claude_md | Idempotently write rule-level patterns into a CLAUDE.md file. Updates only the block between <!-- instinct:start --> and
<!-- instinct:end --> markers; everything else in the file is
preserved. Creates the file (and markers) if they do not exist.
Safe to run on every commit or session end without producing churn.
For one-shot rendering without touching the filesystem, use
export_claude_md() and write the output yourself.
Args:
target: Absolute or relative path to the CLAUDE.md file. Parent
directories must exist; the file itself will be created.
Returns:
Dict with keys: "target" (str — echoed path), "rule_count"
(int), "changed" (bool — false when content matched existing
block, true when the file was actually rewritten).
|
| find_duplicates | Detect near-identical pattern keys that should probably be merged. Compares every pattern against every other using token overlap and
prefix matching. Flags candidate pairs above the threshold so you
can apply alias_pattern() to consolidate them. Read-only — this
tool suggests merges but never performs them.
A common use case: after a bulk import_patterns() or import_claude_md(),
call this to catch formatting drift (spacing, casing, punctuation).
Args:
threshold: Similarity cutoff, 0.0 to 1.0. Default 0.75. Lower
thresholds (0.5) over-suggest; higher (0.9) under-suggest.
Start at default and tune per your noise tolerance.
Returns:
Dict with keys: "duplicates" (list of {pattern_a, pattern_b,
similarity}), "count" (int), "hint" pointing to alias_pattern
as the next step.
|
| import_claude_md | Parse a CLAUDE.md file and ingest its backtick-wrapped patterns. Scans the file for patterns matching the instinct convention
(seq:..., pref:..., fix:..., combo:...) and imports each as an
observation. Extracts confidence counts and explain text when
present on the line.
Use this to bootstrap a fresh instinct store from an existing
project's CLAUDE.md, or to sync rules authored by hand.
Args:
source: Path to the CLAUDE.md file. Read-only — the source
file is not modified.
Returns:
Dict with keys: "imported" (int — new patterns), "merged"
(int — reinforced existing patterns), "skipped" (int — lines
that looked pattern-like but failed validation), "source" (str).
|
| history | Show how one pattern's confidence evolved over a time window. Returns every observation recorded against the pattern in the window,
with timestamps and source projects — useful for spotting growth
velocity, cross-project adoption, or stale patterns that should decay.
For a snapshot of the current state (not the timeline), use
get_instinct() instead.
Args:
pattern: Exact pattern key. Same format as get_instinct() —
case-sensitive, includes prefix (e.g. "seq:lint->fix").
days: Look-back window in days. Default 30.
Returns:
Dict with keys: "pattern" (str — echoed), "history" (list of
{timestamp, source, project, delta}), "data_points" (int),
"projects" (list of distinct project fingerprints seen).
|
| export_platform | Render rule-level patterns in a target editor's config format. Use this when you want rules in a specific platform's rules file —
e.g. Cursor's .cursorrules, Windsurf's .windsurfrules, or Codex's
AGENTS.md — without hand-translating the output of export_rules().
Use fmt="claude-md" for the same Markdown renderer as
export_claude_md(); prefer export_claude_md() when you only need
Claude's CLAUDE.md shape.
For Anthropic-specific outputs (CLAUDE.md, SKILL.md), the dedicated
export_claude_md() and export_skill() tools keep the intent explicit.
Prefer this tool for non-Claude targets like .cursorrules,
.windsurfrules, or AGENTS.md.
Args:
fmt: Target platform. One of: "claude-md" (default),
"cursorrules", "windsurfrules", "codex". Unknown values are
rejected by validation instead of silently guessing.
Returns:
Dict with keys: "content" (str — formatted text ready to write
to disk; empty string when no rules exist), "format" (str —
echoed), "rule_count" (int).
|
| gc | Run all store-maintenance tasks in one call: decay, dedup, orphans, FTS. Combines four housekeeping steps:
1. Decay confidence on patterns idle beyond the staleness threshold.
2. Merge near-duplicates using the given similarity threshold.
3. Remove alias entries whose target no longer exists.
4. Rebuild the SQLite FTS index for accurate search results.
Safe and idempotent — running more than once per day is fine. For
finer control, the individual steps are available as find_duplicates()
+ alias_pattern() + (internal) decay.
Args:
dedup_threshold: Similarity cutoff for step 2, 0.0-1.0. Default
0.75. See find_duplicates() for tuning notes.
Returns:
Dict with keys: "decay" (dict with "decayed" and "deleted"),
"dedup" (dict with "found" and "applied"), "orphans_cleaned"
(int), "fts_rebuilt" (bool).
Prefer housekeep() for discoverability; gc() remains supported for
existing clients.
|
| housekeep | Run cleanup, deduplication, decay, orphan cleanup, and FTS rebuild. Use this when you want to "clean up", "housekeep", "prune stale
patterns", or "rebuild search" after many observations or imports.
This is the natural-language alias for gc(); both tools are identical
and safe to run periodically.
Args:
dedup_threshold: Similarity cutoff for duplicate merging,
0.0-1.0. Default 0.75. See find_duplicates() for tuning notes.
Returns:
Dict with keys: "decay" (dict with "decayed" and "deleted"),
"dedup" (dict with "found" and "applied"), "orphans_cleaned"
(int), "fts_rebuilt" (bool).
|