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.1.tar.gz (27.9 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.1-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: claude_scored_memory-0.1.1.tar.gz
  • Upload date:
  • Size: 27.9 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.1.tar.gz
Algorithm Hash digest
SHA256 b6a31979c7f35afe32b8119d65141dbaa565bffdd5b3ed04df3f12d1a5d9d7fb
MD5 4741bce9bda2d3cee710f5d952fd1f16
BLAKE2b-256 9f38f49b67e23c464f3274d86cb3a679798ca5d30d381ee81a9f511652d7774f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for claude_scored_memory-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1b51a8470db3853b0a51e61ba9994e7f8d8780797051a045a09524898a43f2de
MD5 ba6d98c3545953030bf260b7783fdefd
BLAKE2b-256 8b0d5cc3d14c51c626edfe9b6b49ce9744149269160701b1ee774662d465f5e3

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