Does your Claude forget lots of things every time it compacts or starts a new session? Even if you spend a lot of time trying to teach it how to work more effectively? That's —at least partly— fixable.
Shannon (named after Claude Shannon, the founder of information theory) is an MIT-licenced toolkit for improving how Claude agents handle their memories. It includes hooks and seed rules to address common failure modes that recur in practice when working with persistent agent memory.
The specific approach taken here is tailored to Claude Code, but many of the ideas are likely to port to similar agents. This project may well become more general in future. High-quality contributions are welcome.
By default, this project focuses on meta-issues of memory retention and
usage. It is a little opinionated about that, but not about anything
else. You can opt into additional memory categories that make it more
opinionated — for example about code development practices; tips for
how Claude should use the shell, git, or other tools to avoid certain
pitfalls; etc.
TBD: brief background on context vs memory-files, context limits, what compaction is, why compacting can be so lossy, the role of the Claude Code harness, etc.
Memory-augmented agents persist preferences and rules between sessions in a memory corpus. Two failure modes commonly recur:
-
Recall misses. The relevant memory exists, but it isn't loaded into the agent's context at the moment of decision. Compaction reliably drops the bodies of memory files, even when the index of memory titles stays in context. The agent then makes decisions from its training instead of the recorded preference.
-
Trigger misses. The relevant memory is in context, but the agent doesn't fire the rule at the right moment. Training pressure to "act now" can override even a rule the agent has loaded.
These failures look identical from the outside —the recorded preference doesn't apply— but they need different fixes.
-
CLAUDE.mdtemplate — irreducible imperatives that should never be missed.CLAUDE.mdis always loaded into Claude Code's context, so the rules here won't compact away. This helps to address recall misses. -
Hooks — mechanical gates that fire at action time, not at recall time. The shipped set covers synthesis-check before memory writes, full-corpus re-read at session start and post-compaction, transcript snapshots before compaction, and path-class reminders that nudge scratch files away from
/tmp/. Seehooks/for the current set and each script's header for its specific behaviour. Hooks help to address trigger misses. -
Seed memories — a small starter corpus of universal meta-rules: synthesis-check-before-memory-write, no-push-without-explicit-request, attribution requirements, scrub-paths-from-global-memories, recipe-bearing index summaries, hook script factoring, narration discipline. These are the failure modes that show up consistently across users.
-
Opt-in memories — These try to address a wider range of common failure modes of Claude Code. TBD: describe how the opt-in works mechanically.
-
Idempotent installer —
./install.shis non-destructive: existing hook and utility scripts, seed memories, andCLAUDE.mdat the destination are left in place (skipped, with a report).settings.jsonis deep-merged: Shannon-managed entries (tagged with_shannon: truein the snippet) are updated in place, new entries are appended, and any user-customized entries at a matching event/matcher are left untouched with a warning.
Claude Code persists context across sessions in two distinct forms:
memories (declarative rules whose MEMORY.md index summaries sit in
context every session) and skills (task-shaped procedures loaded
lazily, either via slash command or by the harness auto-matching the
skill's description against the current task). They're not
interchangeable, and the right home for a given piece of content depends
on its shape, not its topic.
Shannon's seed corpus is currently entirely memories. That can look surprising — "isn't proficiency with git a skill?" — because human English uses "skill" for what is in fact a bundle of always-active rules plus invokable procedures plus accumulated heuristics. For a memory-augmented agent, the same bundle splits along the always-active / on-demand axis:
- Always-active rules (don't push during security fixes; match the
repo's existing scope-casing;
git reset --hardis destructive; preserveCo-authored-bytrailers across rebases) → memories. Memory summaries are in context every session, so the rules can fire without the agent having to invoke anything first. - Task-shaped procedures (multi-step rebase recovery flows, release workflows, recovery procedures that benefit from executable helpers) → skills. Skills are lazy-loaded and can ship scripts; they cost almost no context until invoked.
Decision rule:
If violating it once is bad, it's a memory. If doing it without guidance is suboptimal but recoverable, it's a skill.
The two layers complement, not substitute. A future Shannon could ship a
git-safety skill alongside the git-cluster memories — the skill
providing end-to-end recovery procedures, the memories carrying the
always-on rules those procedures must obey.
This split also clarifies why skills can't solve the trigger-miss
failure mode for declarative rules: a skill is auto-surfaced when the
harness sees the user's task description match the skill's description,
but the agent's own silent decisions (e.g. about to run git reset --hard without the user explicitly framing it as "git work") don't
trigger that match. For trigger-miss on rules, the right mechanism is
a PreToolUse hook gating on the specific action.
Current mechanisms to limit the scope of what an AI agent can do are relatively weak. Claude Code runs in a harness that is intended to mitigate the most dangerous failure modes, but this is inherently limited:
- The agent acts with the user's permissions.
- It's very easy to accidentally or inadvisedly create a persistent rule allowing it to do dangerous things without any further prompting.
- The commands that it runs are often too long to be seen in full, too complicated to check, or outright obfuscated. (The obfuscation is sometimes for legitimate reasons like working around shell escaping issues, and sometimes really questionable.)
Shannon isn't able to do more than scratch the surface of these issues. Instructions to an AI agent are effectively code. You should be very wary of the potential for supply-chain attacks against both this project, and any project you're working on.
git clone https://github.com/daira/shannon.git
cd shannon
./install.shThe installer prints platform-specific activation instructions when it
finishes. On Linux the new hooks take effect on the next prompt in any
running session; on macOS and Windows you may need to restart Claude
Code or open /hooks and dismiss it.
- Not a memory replacement. Shannon works with Claude Code's existing auto-memory system.
- Not project-specific. No content here ties to any particular codebase or domain.
- Not prescriptive, unless you want it to be. The more opinionated categories of memory are all opt-in.
Add your own memories to ~/.claude/memory/ as you normally would.
Shannon's seed memories sit alongside, not above; you can override any of
them by writing your own with the same filename.
A few principles guide what's in this project:
- Mechanical guarantees over text exhortation. A hook fires regardless of training pressure. This is more reliable than a text instruction that can be skipped.
- Opt-ins for anything that is not universal. The seed memories cover only universal failure modes. Anything that doesn't meet that criterion is opt-in.
- Batteries included. If you do want to opt into more opinionated
memories about code development practices, more reliable ways to use the
shell and
git, etc., those are included. - Friction reduction on the path from noticing to memory-update. When
a generalizable issue surfaces mid-session, the default response should
be to update or synthesize a memory rather than narrate the observation
in conversation that evaporates at compaction. Shannon's mechanisms
—the seed memory encoding this rule, the synthesis-check hook on memory
writes, and the always-loaded
CLAUDE.mdtemplate— aim to keep that path short and low-friction, so memory-update is the structurally easier action.