Use when starting a session, when a hard-gate denial blocks a tool, when making or reversing decisions, when resuming an interrupted session, when PreCompact fires, or when asked about prior sessions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/elephants-never-forget:elephants-never-forgetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Cross-session memory system. Track what happened, what was decided, and what changed — so future sessions start with full context and users can monitor their own patterns.
Cross-session memory system. Track what happened, what was decided, and what changed — so future sessions start with full context and users can monitor their own patterns.
Hooks handle mechanical logging (prompts, tool use, timestamps). Your job is the intelligent layer: structured summaries, decision records, friction tracking, and progressive compression of older sessions.
This skill complements (does not replace) Claude's built-in memory system. Use built-in memory for user preferences and quick facts. Use this system for structured session history, decision tracking, and analytical review.
A hard gate enforces that this session's file exists before any non-creation tool call runs — see The Gate below. Another session's file dated today does not satisfy the gate; matching is done by the session_id frontmatter field.
Do these in order at the start of every session:
.claude-sessions/sessions/YYYY-MM-DD-<slug>.md whose frontmatter session_id matches the current session's id (first 8 chars). Another session's file dated today does NOT count.[a-z0-9-] only, max 40 chars. Same-day collision? Append -<first-4-chars-of-session-id>. Write the required frontmatter — session_id MUST be this session's id (first 8 chars) — plus date, start_time, tags, status: active, summary, and an ## Intent section..claude-sessions/.active/<session-id-prefix>. This is a convention; not required by the gate..claude-sessions/.opt-out/<session-id-prefix> instead. That satisfies the gate and suppresses further updates.If .claude-sessions/ is empty (first-ever session), also create index.md, decisions.md, and topics.md — see First Session Initialization.
The hard gate runs on UserPromptSubmit and PreToolUse hooks. Its rules:
session_id matching the current session's id → silent allow. No output, no overhead..claude-sessions/.opt-out/<session-id> exists) → silent allow.<system-reminder> is injected into your context telling you to create your session file. Another session's file dated today does NOT satisfy the gate.{"decision": "deny", "reason": "…"}, blocking the tool. Exception: Write to a path under .claude-sessions/sessions/ or .claude-sessions/.opt-out/ is allowed, so you can create the session file or opt-out marker without the gate blocking that creation itself.How matching works: The gate scans .md files under sessions/ whose filename starts with today's or yesterday's date prefix, parses each file's YAML frontmatter, and checks whether session_id (first 8 chars) equals the current session's id (first 8 chars). The yesterday window covers sessions that crossed midnight.
How to satisfy the gate: Create your session's file (Session Start Protocol step 3) with session_id: <your-8-char-prefix> in the frontmatter, OR create an opt-out marker at .claude-sessions/.opt-out/<your-8-char-prefix>. Both are Write operations under .claude-sessions/, which the gate allows even before any session file exists.
Denial shape (what you will see blocked):
{"decision": "deny", "reason": "No session file exists for THIS session (id <prefix>) on YYYY-MM-DD. Another session's file dated today does NOT satisfy the Elephants Never Forget gate. Create `.claude-sessions/sessions/YYYY-MM-DD-<slug>.md` with frontmatter `session_id: <prefix>`, OR create `.claude-sessions/.opt-out/<prefix>` to opt out of tracking for this session."}
Fail-open guarantee: If the gate script itself errors (malformed stdin, filesystem hiccup, import failure), it exits 0 silently — it never blocks a user by accident. Likewise, files with missing or malformed frontmatter are skipped (treated as non-matching) rather than crashing the gate.
.claude-sessions/
index.md # One-line per session, newest first
topics.md # Tag-to-session mapping (tags = topics)
decisions.md # Standing decisions (Y-statements)
log.md # Append-only chronological record (hook-written)
sessions/
YYYY-MM-DD-topic.md # Per-session detailed file
raw/
<session-id>.jsonl # Mechanical event log (hook-written)
.active/ # Optional active-session markers
.opt-out/ # Opt-out markers (satisfies the gate)
decisions.md.index.md + topics.md, set status: completed.If the user says "don't track this session" or similar, create .claude-sessions/.opt-out/<session-id-prefix> (empty file) to satisfy the gate, then skip all session file creation and updates. Hooks will still write to raw/ and log.md (mechanical logging cannot be suppressed from the skill layer), but you should not create or update any files in sessions/, index.md, topics.md, or decisions.md.
Update at natural breakpoints — aim for roughly every 5–10 significant interactions, not after every single tool call. Concrete triggers:
A <system-reminder> (the heartbeat) will be injected into your context when 5+ user prompts have been submitted since the session file was last touched. This is a soft reminder, not a deny — but treat it as a strong signal to update the session file before responding to the user.
A decision is significant if it would affect future sessions or is worth remembering:
Track these: Technology choices, architecture decisions, approach changes, dependency selections, API design choices, anything the user explicitly frames as a decision.
Skip these: Which file to read first, variable naming, import ordering, formatting choices — mechanical choices that don't compound.
When in doubt: If you'd mention it in a handoff to another developer, it's significant.
sessions/YYYY-MM-DD-topic-slug.mdFile naming rules:
YYYY-MM-DD — today's datetopic-slug — 2–5 word kebab-case summary derived from the session's primary goal. Max 40 chars for the slug.[a-z0-9-] in the slug. No spaces, underscores, or special characters.2026-04-13-api-refactor-a1b2.mdFrontmatter:
---
session_id: a1b2c3d4
date: 2026-04-13
start_time: "14:30"
tags: [tag1, tag2, tag3]
status: active | completed
summary: "One sentence summary"
---
session_id: First 8 characters of the session ID from Claude Code (provided by hooks in the injected context, or available as $CLAUDE_CODE_SESSION_ID). If unknown, use the first 8 chars of today's date + slug hash.Body sections (write only sections that have content):
## Intent
What the user wanted to accomplish this session.
## Interactions
### [HH:MM] User -> <summarized prompt>
**Claude ->** <what you did and why, not full output>
## Decisions
- [HH:MM] Y: In the context of [X], facing [Y], decided [Z] over [alternatives], to achieve [benefit], accepting [tradeoff]. Confidence: high|medium|low
## Reversals
- [HH:MM] REVERSED [previous decision ref]: Changed from [old] to [new] because [reason]
## Files Touched
- `path/to/file.ts` — role: [created|modified|deleted], what: [brief description]
## Errors & Fixes
- [HH:MM] Error: `exact error message`. Fix: [what resolved it]
## Friction Events
- [HH:MM] User redirected approach: was doing [X], switched to [Y]
- [HH:MM] Abandoned approach: [what was tried and why it failed]
## Open Items
- [ ] What remains unfinished
| Level | When to use |
|---|---|
| high | Clear requirements, proven approach, team consensus, or user explicitly chose this |
| medium | Reasonable choice but alternatives were viable, or requirements may change |
| low | Best guess, limited information, user seemed uncertain, or expedient workaround |
Use Y-statements — single structured sentences:
# Standing Decisions
## [Topic Area]
- [YYYY-MM-DD] Y: In the context of [area], facing [concern], decided [choice] over [rejected], to achieve [benefit], accepting [tradeoff]. Confidence: high|medium|low. Session: [id]
- ~~[YYYY-MM-DD] Previously: [old decision]~~ SUPERSEDED
Rules:
SUPERSEDED label goes outside the strikethrough.decisions-archive.md with a note in the main file.# Session Index
> [Project name] — [total] sessions, [count] active decisions
## Recent
- [YYYY-MM-DD-topic](sessions/YYYY-MM-DD-topic.md): One sentence. Tags: tag1, tag2
## By Topic
See [topics.md](topics.md)
## Standing Decisions
See [decisions.md](decisions.md)
Keep each entry to one line, ~30 tokens. At 100+ sessions, archive older entries to index-archive.md.
Topics are the same as tags. Each tag from a session's frontmatter gets an entry here.
## payments
- [2026-04-13-payment-flow](sessions/2026-04-13-payment-flow.md): Built Stripe checkout integration
## testing
- [2026-04-12-test-setup](sessions/2026-04-12-test-setup.md): Configured test framework and fixtures
When .claude-sessions/ has no index.md, create all three files:
index.md with the header template (fill in project name from context)decisions.md with just # Standing Decisionstopics.md (empty, will be populated at session end)The hooks automatically create the sessions/ and raw/ directories.
When the user asks about past work ("What did we decide about X?", "What happened last week?"):
decisions.md first — decisions survive all compression tiersindex.md — find sessions by date, topic, or tagstopics.md — find all sessions related to a specific topicraw/<session-id>.jsonl — last resort for mechanical log if session file was compressed to Cold tierIf a previous session was interrupted (you see a session file with status: active and no summary):
## Resumed [date] in session [new-id]Three tiers based on age:
| Tier | Age | What stays | What compresses |
|---|---|---|---|
| Hot | Current + last 3 sessions | Full detail | Nothing |
| Warm | 4–30 days | Anchored summary (below) | Interactions, friction details |
| Cold | 30+ days | Frontmatter + summary only. Decisions survive in decisions.md | Everything else removed |
Anchored summary format (warm tier — replaces full body):
## Intent
Add search functionality to the product catalog.
## Changes Made
- Created `src/services/search.ts` with full-text search logic
- Updated `src/routes/products.ts` to expose search endpoint
## Decisions Taken
- [14:10] Y: In context of search engine, decided Elasticsearch over Algolia, to achieve self-hosted control, accepting operational overhead. Confidence: high
## Next Steps
- [ ] Add search result pagination
Note how file paths (src/services/search.ts) survive verbatim in the warm tier.
At session start, if sessions exist older than tier thresholds. Compress one tier at a time, oldest first. If both Cold and Warm compression are needed, do Cold first this session, Warm next session.
For very long sessions, keep the Interactions section manageable:
| Thought | Reality |
|---|---|
| "I'll just read the file first, then create the session log" | Gate will deny the Read. Create the session file first. |
| "This is a quick task; skip logging" | Quick tasks still benefit from the record. Make the file; keep it short. |
| "The SessionStart hook already captured things" | Hooks capture events. The skill captures meaning (intent, decisions). |
| "I'll batch updates at the end" | PreCompact can fire sooner than expected. Update at natural breakpoints. |
| Action | What to do |
|---|---|
| User makes decision | Write Y-statement to session file AND decisions.md |
| Decision reversed | New entry in decisions.md, strikethrough old, log in Reversals |
| Error resolved | Log in Errors & Fixes with exact error message |
| User redirects approach | Log in Friction Events |
| Every 5–10 interactions | Update session file |
| PreCompact warning appears | Immediately update session file |
| Session ends | Write anchored summary, update index.md + topics.md, set status: completed |
| Old sessions exist | Compress per tier thresholds, oldest first, one tier per session start |
| User asks about past work | Check decisions.md → index.md → topics.md → session file → raw/ |
| User says "don't track" | Create .opt-out/<session-id-prefix> marker; skip session file operations |
| Previous session left active | Resume it instead of creating new file |
| Gate blocks a tool call | Create today's session file (or opt-out marker), then retry |
src/services/search.ts to "the search file" — paths must survive compression verbatim.raw/ or log.md: The hooks handle those. You handle sessions/, index.md, topics.md, decisions.md.[a-z0-9-] only. Sanitize non-ASCII and special chars.Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub ritvikctsipl/elephants-never-forget --plugin elephants-never-forget