Skip to main content

A Claude Code hook that scores and remembers bad responses, then injects them back into future turns

Project description

claude-scored-memory

A Claude Code hook that scores and remembers bad responses, then injects the top offenders back into future turns as system context.

Think of it as a per-user behavioral feedback loop layered on top of vanilla Claude Code. Every time Claude finishes a turn, the Stop hook regex-matches the response against your rules and stores hits in SQLite with frequency + recency + severity scoring. On the next turn, the UserPromptSubmit hook queries the store for violations semantically relevant to the current prompt and injects the top K as an XML block into the conversation. Claude sees its past mistakes before it acts.

This does not adjust temperature, logits, or sampling — Claude Code hooks can't touch those. The "probability weighting" effect comes entirely from contextual prompt injection.

Install

pipx install claude-scored-memory
claude-scored-memory install
claude-scored-memory doctor

The install command:

  1. Creates ~/.claude/scored-memory/ (state dir).
  2. Writes a default config.toml and an empty compliance-rules.yaml.
  3. Initializes compliance.sqlite3 with WAL mode.
  4. Merges hook entries into ~/.claude/settings.json — preserving any existing hooks in the UserPromptSubmit or Stop arrays.

Restart any running Claude Code sessions to pick up the new hooks.

Write some rules

claude-scored-memory ships as a framework, not a rule set. Out of the box it stores and injects nothing because there's nothing to match.

Open ~/.claude/scored-memory/compliance-rules.yaml and author rules in YAML. The docs/example-rules/ directory in the package has copy-paste starting points for common failure modes:

  • behavioral.yaml — pandering, empty promises, answering from memory
  • security.yaml — committing secrets, shell interpolation
  • unverified-claims.yaml — "should work", "probably fine", "I assume"

See docs/writing-rules.md for the full format reference and scoring math.

claude-scored-memory rules validate   # lint your rules file

Observability

claude-scored-memory stats                      # counts by category
claude-scored-memory list --category behavior   # violation table
claude-scored-memory query "<prompt text>"      # dry-run the injection
claude-scored-memory tail                       # live log of hook activity

The log file ~/.claude/scored-memory/logs/bridge.log is one JSON line per hook invocation with event, duration_ms, and hit counts. It's the single source of truth when you want to know whether the hooks are firing.

How it works

user prompt
    │
    ▼
UserPromptSubmit hook ──► bridge build_prompt_context ──► SQLite
    │                                                         │
    │  additionalContext = <compliance-violations>...         │
    ▼                                                         │
Claude processes the turn                                     │
    │                                                         │
    ▼                                                         │
Stop hook ───────────────► bridge check ─────────────────────►┘
                                 (regex match + upsert)

On the next turn, the violations stored by the previous Stop are eligible for injection by UserPromptSubmit.

Scoring

score = min(freq, 10)/10 × 2^(-days_since/7) × severity × cosine(prompt, violation)
  • Frequency caps at 10 so a single obnoxious rule can't dominate forever.
  • Recency decays with a 7-day half-life.
  • Severity is rule-declared. 1.0 is normal; 2.0+ means one occurrence is enough to surface immediately.
  • Semantic relevance (hashed 128-dim cosine) acts as a tiebreaker so rules fire on contextually-relevant turns, not every turn indiscriminately.

Tune top_k, min_score, max_prompt_chars in ~/.claude/scored-memory/config.toml.

Per-project state

By default, the store is global per user (~/.claude/scored-memory/). Behavioral lessons are about the model, not the project, and you want the frequency counters to actually accumulate.

If you want isolated counters per project, set this in the project's .claude/settings.json:

{
  "env": {
    "SCORED_MEMORY_ROOT":  "${CLAUDE_PROJECT_DIR}/.claude/scored-memory",
    "SCORED_MEMORY_RULES": "${CLAUDE_PROJECT_DIR}/.claude/scored-memory/compliance-rules.yaml"
  }
}

Disabling temporarily

SCORED_MEMORY_DISABLE=1 claude

Or remove the hook entries from ~/.claude/settings.json via:

claude-scored-memory uninstall

Uninstall never touches your state dir — the DB, rules, and logs stay put so you can re-enable later or copy them to another machine.

Non-goals

  • Temperature / logit manipulation — not possible via hooks.
  • Curated default rules — rule selection is user-owned, by design.
  • LLM-as-judge scoring — rules are regex-only.
  • Real-time streaming inspection — Stop fires after the response is complete.
  • GUI, dashboard, menu bar app — CLI only.

Provenance

The scoring engine, SQLite schema, and bridge CLI are vendored from Scored-Memory (MIT), with primitives (_embed, _cosine, _iso, _now_utc, _parse_iso) inlined from its clawmemory dependency (MIT, Nattapong) into _vendored/_primitives.py so this package has no hidden runtime dependencies beyond pyyaml. See src/claude_scored_memory/_vendored/ for annotated sources.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

claude_scored_memory-0.1.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

claude_scored_memory-0.1.0-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file claude_scored_memory-0.1.0.tar.gz.

File metadata

  • Download URL: claude_scored_memory-0.1.0.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for claude_scored_memory-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a90fb7e1e186a6061be35e6c2eeb62a8c4a9d5e5824e08107710004cc8eac04d
MD5 6d911f4f0214c8fab01ccc578cff6c79
BLAKE2b-256 5e9f84950e867c9fe7813ff8346b043b7e54b0fcbbc6abb700c0ef6f05fbf7d3

See more details on using hashes here.

File details

Details for the file claude_scored_memory-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for claude_scored_memory-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dcde53a4d2697808f5cb55847a7301cb25236996833fa091d9413929026c086b
MD5 f2401712ae2bd4810709769ae718746d
BLAKE2b-256 eba3d5cdcaa4dd4a1245c836cae26ef6ab442e9ff500d57f16e55bf3309aef2a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page