I Gave Claude Code a Memory and Now It Judges My Coding Habits (Here’s How)

Claude Code has the memory of a mass-produced robot goldfish. Every session, it wakes up like it's never seen your codebase before. I fixed it with 47 lines of bash and mild frustration.

3 min read

Update (March 2026): Since this article was published, Claude Code shipped auto-memory (v2.1.59+). It now writes notes to itself automatically (build commands, architecture decisions, your code style preferences) and loads them at the start of every session. So... problem solved?

Not exactly. Auto-memory is qualitative: it remembers that you prefer Supabase RLS over custom middleware. My post-mortem tool is quantitative: it tells you that 40% of your prompts are questions, your fix/feature ratio is 10:24, and "authentication" appeared 7 times this week. One is a notebook. The other is an audit.

Auto-memory stops Claude from asking "what's your stack?" every morning. The post-mortem stops you from asking Claude the same question every morning (and shows you exactly what to document so you stop). They're complementary. Use both. Or don't. I'm a bash script, not a cop.

TL;DR Claude Code forgets everything. I made it keep receipts. Now I know exactly what to document and where I'm wasting time.

I Gave Claude Code a Memory and Now It Judges My Coding Habits (Here’s How)
I Gave Claude Code a Memory and Now It Judges My Coding Habits (Here’s How)
curl -sO https://raw.githubusercontent.com/inforeole/claude-code-toolkit/post-mortem/install.sh && bash install.sh

30 seconds to install. Infinite validation (or humiliation, depending on your habits).

The Problem: Groundhog Day, But Make It Painful

You know that feeling when you explain something to Claude Code for the 15th time and it looks at you like you just met?

After weeks on the same project, I noticed a disturbing pattern:

Me: "How do I handle auth with Supabase again?"
Claude: explains like it's our first date
Me: "We literally did this yesterday"
Claude: "New conversation, who dis?"

My CLAUDE.md was supposed to be the solution. Spoiler: it wasn't. Because I had no idea what to put in it. I was basically writing documentation based on vibes and trauma.

Plot twist: What if Claude Code could tell me what it needed to know?

The Solution: Big Brother, But Make It Useful

I built a system that:

  • Logs every prompt I send (yes, even the desperate 2am ones)
  • Analyzes patterns like a therapist with a CS degree
  • Generates a report telling me exactly where I'm failing

Think of it as a Fitbit for your Claude Code sessions. Except instead of judging your steps, it judges your debugging habits.

TL;DR Just Give Me The Script

Don't care about the "why"? I respect that. Run this:

curl -sO https://raw.githubusercontent.com/inforeole/claude-code-toolkit/post-mortem/install.sh && bash install.sh

Boom. Post-mortem system installed. Run npm run postmortem when you're ready to face the truth.

Want to understand what you just installed? Keep reading.

The Architecture (It's Simpler Than Your Last Relationship)

Claude Code supports hooks (scripts that run on specific events). I'm using UserPromptSubmit to capture everything.

.claude/
├── settings.json          # Hook config
├── scripts/
│   ├── log-prompt.sh      # The snitch
│   └── analyze.js         # The therapist
└── logs/
    └── prompts.jsonl      # Your diary (gitignored, don't worry)

Step 1: Setting the Trap

.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/scripts/log-prompt.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

Every message you send now gets intercepted. NSA wants to know your location.

Step 2: The Logging Script (a.k.a. The Snitch)

.claude/scripts/log-prompt.sh:

#!/bin/bash
LOG_DIR="$(dirname "$0")/../logs"
LOG_FILE="$LOG_DIR/prompts.jsonl"
mkdir -p "$LOG_DIR"
INPUT=$(cat)
[ -z "$INPUT" ] && exit 0
PROMPT=$(echo "$INPUT" | python3 -c 'import sys,json; data=json.load(sys.stdin); print(data.get("prompt",""))' 2>/dev/null)
[ -z "$PROMPT" ] && PROMPT="$INPUT"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
GIT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
## JSON escape (because we're professionals)
ESCAPED_PROMPT=$(printf '%s' "$PROMPT" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read())[1:-1])')
echo "{\"timestamp\":\"$TIMESTAMP\",\"branch\":\"$GIT_BRANCH\",\"commit\":\"$GIT_HASH\",\"prompt\":\"$ESCAPED_PROMPT\"}" >> "$LOG_FILE"

JSONL format because we're not savages. One JSON object per line = easy parsing = happy developer = myth.

Step 3: The Analysis Script (a.k.a. The Therapist)

.claude/scripts/analyze.js (the juicy parts):

#!/usr/bin/env node
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { execSync } from 'child_process';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const LOGS_DIR = join(__dirname, '..', 'logs');

// Parse JSONL (it's just JSON with commitment issues)
function parseJsonl(filepath) {
  if (!existsSync(filepath)) return [];
  return readFileSync(filepath, 'utf-8')
    .split('\n')
    .filter(line => line.trim())
    .map(line => { try { return JSON.parse(line); } catch { return null; } })
    .filter(Boolean);
}

// Categorize prompts like a judgmental librarian
function categorizePrompts(prompts) {
  const categories = { bugs: [], features: [], questions: [], refactoring: [], other: [] };
  
  for (const p of prompts) {
    const text = (p.prompt || '').toLowerCase();
    if (/\b(bug|fix|error|crash|broken|wtf|why)\b/.test(text)) categories.bugs.push(p);
    else if (/\b(add|create|implement|build|new)\b/.test(text)) categories.features.push(p);
    else if (/\?|how|what|why|can you/.test(text)) categories.questions.push(p);
    else if (/\b(refactor|clean|improve|optimize)\b/.test(text)) categories.refactoring.push(p);
    else categories.other.push(p);
  }
  return categories;
}

// Find the words you can't stop saying
function findRepeatedPatterns(prompts) {
  const patterns = {};
  for (const p of prompts) {
    const words = (p.prompt || '').toLowerCase()
      .replace(/[^a-z\s]/g, '')
      .split(/\s+/)
      .filter(w => w.length > 4);
    for (const word of words) patterns[word] = (patterns[word] || 0) + 1;
  }
  return Object.entries(patterns)
    .filter(([, count]) => count > 2)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 20);
}

// Generate insights (prepare to feel attacked)
function generateInsights(prompts, git) {
  const insights = [];
  const categories = categorizePrompts(prompts);
  
  if (git.patterns.fixes?.length > git.patterns.features?.length) {
    insights.push({
      type: 'warning',
      message: \`More fixes (\${git.patterns.fixes.length}) than features (\${git.patterns.features.length}). Tech debt is calling. It wants its interest.\`
    });
  }
  
  if (categories.bugs.length > categories.features.length) {
    insights.push({
      type: 'info', 
      message: \`You spent more time debugging (\${categories.bugs.length}) than building (\${categories.features.length}). We've all been there.\`
    });
  }
  
  if (categories.questions.length > prompts.length * 0.4) {
    insights.push({
      type: 'warning',
      message: \`40%+ of your prompts are questions. Your CLAUDE.md is basically empty, isn't it?\`
    });
  }
  
  return insights;
}

The full script generates a Markdown report with stats that will either validate you or trigger an existential crisis.

Step 4: The npm Script (Because We're Lazy)

package.json:

{
  "scripts": {
    "postmortem": "node .claude/scripts/analyze.js",
    "roast-me": "node .claude/scripts/analyze.js"
  }
}

I added an alias because sometimes you need the emotional honesty.

Step 5: Gitignore (Keep Your Shame Private)

.claude/logs/
.claude/report.md
.claude/settings.local.json

What happens in .claude/logs/ stays in .claude/logs/.

The Moment of Truth

After a week of coding, I ran npm run postmortem. The output hit different:

📊 Data loaded:
   - 47 prompts
   - 3 errors  
   - 51 commits
## Post-Mortem Report

| Metric            | Value  |
|-------------------|--------|
| Prompts analyzed  | 47     |
| Errors detected   | 3      |
| Commits (30d)     | 51     |
| Fix/Feature ratio | 10/24  |

## Prompt Distribution
- 🐛 Bugs/Fixes: 12
- ✨ Features: 18
- ❓ Questions: 8
- 🔧 Refactoring: 4

## Most Repeated Keywords
- **supabase**: 7 times
- **authentication**: 5 times
- **error**: 4 times

## Recommendations for CLAUDE.md
1. Document "supabase" (mentioned 7 times - take the hint)
2. Document "authentication" (mentioned 5 times - seriously)

## Insights
⚠️ 40%+ questions detected. Your CLAUDE.md is basically empty, isn't it?

I felt seen. And not in a good way.

What This Actually Reveals

  • High fix/feature ratio → You're not building, you're firefighting. Time for a refactor sprint (or therapy).
  • Repeated keywords → These are literally the things Claude keeps forgetting. Document them. Your future self will thank you.
  • Question percentage → If you're asking Claude the same things repeatedly, your CLAUDE.md is failing you. Fix it or keep suffering. Your choice.

Future Improvements (a.k.a. My TODO List)

  • AI-powered analysis: Send logs to Claude API for semantic analysis. Let AI judge AI interactions. Very meta.
  • Real-time dashboard: Because everything needs a dashboard in 2026.
  • Slack alerts: Get notified when your fix/feature ratio goes full dumpster fire.
  • Cross-project benchmarking: Find out which of your projects is the most cursed.

Now if you'll excuse me, I need to go document "authentication" in my CLAUDE.md for the 8th time.

If this approach resonates (treating AI interactions as engineering problems, not vibes), I wrote a whole book about it. Prompt Contracts applies software architecture principles (SRP, DRY, Open/Closed) to how you prompt Claude Code, so you stop vibe-coding and start shipping production software. Get it on Amazon.

What's your Claude Code coping mechanism? Drop it in the comments. 👇


Want to stop repeating yourself with Claude? I built a post-mortem system that tracks every interaction, revealing exactly what you need to document. No more Groundhog Day debugging.

Get the Production Toolkit