Skip to content

houtini-ai/metacog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

metacog

npm version

metacog

So, here's the problem with AI coding agents: they can't feel when they're stuck. They'll retry the same broken fix five times because they can see each individual error but not the pattern of repeated failure. They'll read the same file three times in a session because context compaction wiped their memory of reading it. They'll chase a dependency chain four levels deep and forget what they were originally trying to fix. They have no sense of time, no peripheral vision of how their changes affect other files, and no awareness of whether they're actually validating their work or just admiring it.

Metacog is a pair of Claude Code hooks that gives the agent something like a nervous system. I say "something like" because the signals arrive as text in the agent's context, not as actual sensations. It's closer to a colleague leaving a post-it note than biological proprioception. But that turns out to be enough. One hook fires after every tool call and watches for these patterns. The other fires when you send a message and injects learned rules from past sessions. When everything is fine, both hooks are completely silent, zero tokens, zero cost. When something is off, a short signal appears in the agent's context. At first it's just awareness, and the agent's own reasoning decides what to do about it. But if the agent keeps failing, the signals escalate from gentle nudges to structured interventions that force the agent to stop and rethink. That escalation matters, because if the agent's reasoning was working properly it wouldn't be stuck in the first place.

And when problems do resolve, the system extracts what changed and persists it as a behavioural rule that gets injected into future sessions. This is probably the most interesting part. Most cross-session memory systems use time-decay, so if a rule works and the failure stops happening, the system sees silence and prunes the rule. The agent forgets. The behaviour regresses. Metacog inverts this: if the rule was active and the failure's preconditions were met but the failure didn't happen, that counts as evidence the rule is working. Rules get stronger when they succeed, not stale.

Seven senses. Session retrospectives. User interaction tracking. Zero dependencies. One-command install. Open source.

Quick Navigation

Install | What are hooks? | What it does | The seven senses | The three layers | Memory vs. metacognition | Session retrospectives | User interaction tracking | How the data flows | Configuration | Plugin structure | Design principles


Install

From npm

npx @houtini/metacog --install

This downloads the package and registers both hooks into your global Claude Code settings (~/.claude/settings.json). Metacog runs silently in the background from that point on. You'll only see output when something is abnormal.

For project-scoped install (writes to .claude/settings.json in the current directory):

npx @houtini/metacog --install --project

From source

git clone https://github.com/houtini-ai/metacog
cd metacog && node src/install.js --install

This points the hooks at your local clone, so changes take effect immediately.


What are Claude Code hooks?

Hooks are shell commands that Claude Code runs automatically at specific moments during a session. They're the plugin system's way of letting tools react to what the agent is doing, without the agent having to ask for it.

There are a few hook events that matter here:

Hook event When it fires What it's for
PostToolUse After the agent uses any tool (Read, Write, Bash, etc.) Monitoring, validation, side effects
UserPromptSubmit When you send a message Injecting context, session setup
PreToolUse Before a tool runs Blocking dangerous actions
Stop When the agent finishes responding Cleanup, verification

Hooks communicate back to Claude via JSON on stdout:

{
  "continue": true,
  "suppressOutput": false,
  "systemMessage": "This message appears in the agent's context"
}

If a hook outputs nothing and exits 0, it's invisible. Zero token cost. Zero latency (well, near-zero). This is what makes hooks different from MCP servers - they can be completely silent when there's nothing to say.

Metacog uses two hooks: PostToolUse for the nervous system and UserPromptSubmit for injecting learned rules, session retrospectives, and tracking user interaction patterns.


What it does

Metacog runs as a pair of Claude Code hooks. One fires after every tool call (the nervous system), the other fires on every user message (interaction tracking, digest injection, session retrospectives). When everything is normal, both produce zero output and cost zero tokens. When something is abnormal, a short signal appears in the agent's context. Most of the time this is just awareness, and the agent decides what to do. But when the agent is genuinely stuck, the system escalates to structured interventions that force reflection before the agent can continue.

The seven senses

Sense Signal What it detects
O2 Context trend Token velocity spikes, the agent is consuming context unsustainably
Chronos Temporal awareness Time and step count since last user interaction
Nociception Error friction Repeated similar errors, the agent is stuck
Spatial Blast radius File dependency count after writes
Vestibular Action diversity Repeated identical actions, going in circles
Echo Validation bias Writing code without running tests, or validating against own output instead of the project's test suite
Drift Scope drift Recent actions have diverged from the original task, chasing dependency chains instead of solving the problem

The three layers

Proprioceptive Senses

Layer 1: Proprioception (always on, near-zero cost) Calculates all seven senses after every tool call. Injects a signal only when values deviate from baseline. Most turns: completely silent.

[Metacognition — review and ignore if not relevant]
Context velocity is high (3 large file reads in last 5 actions).
Does your current approach need all this context, or could an Agent subagent handle the remaining exploration?

Layer 2: Nociception (triggered by Layer 1 thresholds) When error friction crosses critical thresholds, escalating interventions kick in - Socratic questioning first, then directive instructions, then flagging the user.

[NOCICEPTIVE INTERRUPT]
You have attempted 4 similar fixes with consecutive similar errors.
Before taking another action:
1. State the assumption you are currently operating on
2. Describe what read-only action would falsify that assumption
3. Execute that investigation before writing any more code

Layer 3: Motor Learning (cross-session) When a nociceptive event resolves, the system extracts what changed. The delta between failure and resolution gets persisted as a behavioural lesson and injected into future sessions.


Memory vs. metacognition

Memory plugins do a real job. They persist what the agent knows across sessions: user preferences, project context, decisions made. Claude Code's built-in memory system does this well.

But memory answers "what happened?" Metacog answers "how am I thinking right now?" It's the difference between a journal and a nervous system. One records the past. The other tells you when your hand is on the stove.

Memory and Metacognition

Metacog doesn't replace memory. It complements it by tracking how the agent reasons, what patterns lead to failure, what changes fix them, and building rules that get more confident over time.

The seesaw problem

Standard time-decay actively punishes success. If the agent learns "don't retry the same error three times" and stops doing it, the decay system sees the rule going stale and prunes it. The agent forgets. The behaviour regresses.

The Seesaw Problem

Metacog inverts this. When a known pattern doesn't fire during a session where its rule was active, that's a suppression - evidence the rule is working. Both detections and suppressions increase confidence. Only truly dormant rules decay.

Reinforcement Tracking

Subagent awareness

When the agent delegates work to a subagent, the subagent's tool calls can inflate turn counts and token velocity, triggering false positives from Chronos and O2. Metacog detects Agent tool calls and suppresses these senses during delegation, so productive delegation isn't penalised.

Session retrospectives

At the start of each session, metacog injects a brief retrospective of the prior session: which senses fired, action distribution, nociceptive events, delegation patterns, and user interaction quality. This gives the agent immediate context about what happened before without needing to search history.

[Metacog — Prior Session Retrospective]
Last session: 57 tool calls over 9 min.
Senses that fired: O2 (context velocity), Chronos (level 2).
1 subagent delegation used.
Action mix: 14 reads, 0 writes, 5 executes
2 user messages, avg 28 tool calls between messages, prompts were mostly broad/exploratory

User interaction tracking

The UserPromptSubmit hook analyses each user message for specificity (file paths, line numbers, identifiers, error text) and tracks interaction patterns across the session. This isn't about judging prompt quality. Vague prompts are appropriate for exploratory work. But when there's a measurable correlation between prompt style and session length in a specific project, that's worth surfacing. The system shows the data and lets you decide what to do with it.

[Metacog — Collaboration Patterns]
Sessions where prompts mentioned specific files averaged 12 tool calls.
Sessions without averaged 38. This project may benefit from targeted prompts.

How the data flows

Session start - the UserPromptSubmit hook compiles all learnings (global + project-scoped) into a digest, builds a retrospective of the prior session, and injects both as a system message. A marker file records which patterns were active.

Every user message - the UserPromptSubmit hook captures a task fingerprint (for scope drift detection) and records interaction metadata (prompt specificity, tool calls between messages, active signals).

During the session - the PostToolUse hook fires after every tool call. It records actions into a rolling 20-item window. Silent when normal. Signals when abnormal.

Session end - when the next session starts, the system:

  1. Reads the active patterns from the previous session
  2. Runs all pattern detectors against the session state
  3. Detections: the failure happened
  4. Suppressions: the rule was active, its preconditions were met, but the failure didn't happen (evidence the rule worked)
  5. Persists both to JSONL - global and project-scoped

Per-project scoping

Learnings are stored at two levels:

  • Global (~/.claude/metacog-learnings.jsonl) - patterns that apply everywhere
  • Project (<project>/.claude/metacog-learnings.jsonl) - patterns specific to this codebase

Project-scoped entries take precedence where they overlap.


Configuration

Metacog works with zero configuration. To tune thresholds, create .claude/metacog.config.json in your project:

{
  "proprioception": {
    "o2": {
      "velocity_multiplier": 3,
      "baseline_window": 10
    },
    "chronos": {
      "time_threshold_minutes": 15,
      "step_threshold": 25
    },
    "nociception": {
      "consecutive_errors": 3,
      "error_similarity": 0.6,
      "window_size": 5
    },
    "spatial": {
      "blast_radius_threshold": 5,
      "enabled": true
    },
    "vestibular": {
      "action_similarity": 0.8,
      "consecutive_similar": 4
    },
    "echo": {
      "write_streak_threshold": 5,
      "cooldown": 8
    },
    "drift": {
      "min_actions": 8,
      "recent_window": 5,
      "drift_threshold": 0.15,
      "cooldown": 10
    }
  },
  "nociception": {
    "escalation_cooldown": 5,
    "reflex_arc_threshold": 8
  }
}
Setting Default What it does
o2.velocity_multiplier 3 Trigger when token velocity exceeds baseline by this factor
chronos.time_threshold_minutes 15 Signal after this many minutes without user interaction
chronos.step_threshold 25 Signal after this many tool calls without user interaction
nociception.consecutive_errors 3 Similar errors before signalling
spatial.blast_radius_threshold 5 File imports before signalling
vestibular.consecutive_similar 4 Identical actions before signalling
echo.write_streak_threshold 5 Consecutive writes without test run before signalling
drift.min_actions 8 Minimum actions before drift detection starts
drift.drift_threshold 0.15 Term overlap ratio below which drift is signalled

Pattern detectors

The cross-session learning detectors are configurable. Tune thresholds or disable individual detectors:

{
  "patterns": {
    "circular_search": { "enabled": true, "consecutive_runs": 2 },
    "repeated_file_read": { "enabled": true, "repeat_threshold": 3 },
    "error_loop": { "enabled": true, "recent_window": 10, "min_errors": 4, "max_unique_sigs": 2 },
    "long_autonomous_run": { "enabled": true, "turn_threshold": 50 },
    "write_heavy_session": { "enabled": true, "min_writes": 10, "read_ratio": 0.5 }
  }
}

Custom pattern detectors

Define your own detectors in JSON:

{
  "custom_patterns_path": ".claude/my-patterns.json"
}
[
  {
    "id": "too_many_bash_calls",
    "category": "Execution Patterns",
    "lesson": "Consider using dedicated tools (Read, Grep) instead of Bash for file operations.",
    "relevant_tools": ["Bash"],
    "condition": {
      "type": "count_exceeds",
      "filter": { "tool_name": "Bash" },
      "threshold": 15
    }
  }
]

Supported condition types: count_exceeds, consecutive_exceeds, ratio_exceeds.


Plugin structure

metacog/
├── .claude-plugin/
│   ├── plugin.json           # Plugin identity
│   └── marketplace.json      # Marketplace distribution
├── hooks/
│   └── hooks.json            # Hook event configuration
├── src/
│   ├── hook.js               # PostToolUse - nervous system
│   ├── digest-inject.js      # UserPromptSubmit - digest + interaction tracking
│   ├── lib/
│   │   ├── config.js         # Configuration + defaults
│   │   ├── learnings.js      # Cross-session pattern detection
│   │   ├── state.js          # Rolling action window + token estimation
│   │   ├── interactions.js   # User interaction analysis
│   │   └── retrospective.js  # Session retrospective generation
│   └── senses/
│       ├── o2.js             # Context trend
│       ├── chronos.js        # Temporal awareness
│       ├── nociception.js    # Error friction + escalation
│       ├── spatial.js        # Blast radius
│       ├── vestibular.js     # Action diversity
│       ├── echo.js           # Validation bias
│       └── drift.js          # Scope drift detection
├── assets/
│   └── icon.png              # Plugin icon
└── docs/                     # Diagrams

Design principles

  • No news is good news - signals only appear when values deviate from baseline
  • Trends over absolutes - measures velocity, not absolute values
  • Invite reflection, don't command - signals are observations the agent can act on or dismiss
  • Graceful degradation - if the hooks fail, the agent is just normal Claude
  • Reinforcement over decay - rules that work get stronger, not stale

Requirements

  • Node.js 18+
  • Claude Code with plugin support

Backstory

See SPEC.md for the full design specification and the research behind the reinforcement model.

Licence

Apache-2.0

About

Metacog isn't memory for LLMs, it gives them a nervous system. Metacognition developed on your unique user experiences. Five proprioceptive senses. Cross-session reinforcement tracking. Two hooks. Zero dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors