Back to list
cameronsjo

user-memory

by cameronsjo

3🍴 0📅 Jan 13, 2026

SKILL.md


name: User Memory description: Long-term user profile memory that persists across Claude Code sessions when_to_use: Automatic - runs via hooks, no manual invocation needed version: 4.0.0

User Memory

Persistent user profile memory for Claude Code. Two implementations - pick your flavor:

ModeDepsFeaturesBest for
minimal/jq onlyHook extractionLightweight, portable
mcp/Node + MCP SDKHooks + real-time toolsFull control

Quick Start

Option A: Minimal (Shell-only)

# Add to ~/.claude/settings.json
{
  "hooks": {
    "SessionStart": [{
      "hooks": [{
        "type": "command",
        "command": "~/.claude/skills/user-memory/minimal/session-start.sh"
      }]
    }],
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "~/.claude/skills/user-memory/minimal/stop-memory.sh"
      }]
    }]
  }
}

Done. No npm install needed.

Option B: MCP Server (Full)

cd ~/.claude/skills/user-memory/mcp
npm install
{
  "hooks": {
    "SessionStart": [{
      "hooks": [{
        "type": "command",
        "command": "~/.claude/skills/user-memory/mcp/src/hooks/session-start.sh"
      }]
    }],
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "~/.claude/skills/user-memory/mcp/src/hooks/stop-memory.sh"
      }]
    }]
  },
  "mcpServers": {
    "user-memory": {
      "command": "npx",
      "args": ["tsx", "~/.claude/skills/user-memory/mcp/src/mcp-server.ts"]
    }
  }
}

How It Works

SessionStart hook
    ↓
    Loads ~/.claude/user-memory/profile.json
    ↓
    Injects into session context

Stop hook (after every Claude response)
    ↓
    Reads conversation transcript
    ↓
    Extracts preferences via pattern matching
    ↓
    Deduplicates (skips already-processed turns)
    ↓
    Merges into profile.json

[MCP only] Claude can also call:
    Profile tools:
    - get_user_profile
    - update_user_profile
    - remove_preference
    - clear_user_profile
    - get_changelog
    - get_preference_metadata
    - run_decay

    Session continuity tools:
    - get_session_context
    - update_task
    - log_decision
    - add_session_context
    - set_session_summary
    - get_full_context

What Gets Stored

CategoryTrigger phrases
Tech stack"I prefer Bun", "I'm switching to FastAPI"
Editor"I use neovim", "My editor is VS Code"
Tone"Be more direct", "I prefer concise"
Role"I'm a backend engineer"
Languages"I work mostly in TypeScript"

Storage

~/.claude/user-memory/
├── profile.json         # Your preferences
├── profile-meta.json    # Confidence/decay tracking (MCP only)
├── changelog.jsonl      # Audit trail (auto-pruned)
├── .processed_turns     # Dedup tracker
└── sessions/            # Session continuity (MCP only)
    ├── session-abc123.json
    └── ...

Override location: USER_MEMORY_DIR=/custom/path

Changelog (Audit Trail)

Every profile change is logged to changelog.jsonl:

{"timestamp":"2025-01-15T10:30:00Z","session_id":"abc123","action":"extract","source":"minimal/hook","changes":{"codePreferences":{"preferredStacks":["Bun"]}}}
{"timestamp":"2025-01-15T11:00:00Z","action":"update","source":"mcp/tool","changes":{"tools":{"editor":"neovim"}}}
{"timestamp":"2025-01-16T09:00:00Z","action":"clear","source":"mcp/tool","changes":{"userId":"default"}}
FieldDescription
timestampISO 8601 when change occurred
session_idSession that triggered the change (hooks only)
actionextract, update, clear, remove, decay
sourceminimal/hook, mcp/hook, mcp/tool, system
changesWhat was added/modified
removedPaths that were removed (for remove/decay actions)

MCP only: Use get_changelog tool to query the log.

Auto-pruning: Changelog keeps last 1000 entries and removes entries older than 90 days.

Session Continuity (MCP only)

Track task progress and decisions across sessions. Resume where you left off.

Storage

~/.claude/user-memory/sessions/
├── session-abc123.json    # Session with tasks, decisions, context
├── session-def456.json
└── ...

Tools

ToolPurpose
get_session_contextGet resume context from previous sessions
update_taskTrack task progress (pending/in_progress/blocked/completed)
log_decisionRecord important decisions with rationale
add_session_contextStore context notes for future sessions
set_session_summarySet summary shown at next session start
get_full_contextGet full context prompt (profile + session resume)

Auto-pruning

Sessions older than 30 days are automatically removed.

Negation Handling

The extraction system understands when you want to remove preferences:

PhraseEffect
"I no longer use Webpack"Removes Webpack from stacks
"I stopped using React"Removes React from stacks
"Forget that I prefer tabs"Removes that preference
"I switched away from npm"Removes npm from tools

Negation patterns have higher priority than positive patterns, so "I prefer Bun over npm" will add Bun and remove npm atomically.

Decay & Confidence (MCP only)

Preferences decay over time if not reinforced. This prevents stale preferences from persisting forever.

How it works

  1. Each preference has a confidence score (0.0 - 1.0)
  2. Confidence decays exponentially: confidence * 0.5^(days / 30)
  3. When confidence drops below 0.1, preference is auto-removed
  4. Mentioning a preference again reinforces it (+0.3 confidence)

Example timeline

DayEventConfidence
0"I prefer Bun"1.00
30No mention (decay)0.50
60No mention (decay)0.25
75"I'm using Bun" (reinforce)0.55
90No mention (decay)0.39

MCP tools for decay

ToolPurpose
get_preference_metadataView confidence scores, days until decay
run_decayManually trigger decay cycle
remove_preferenceExplicitly remove preferences

Auto-decay on SessionStart

When using MCP mode, decay is automatically checked at session start:

  • Only runs if 24+ hours since last decay
  • Removes preferences below confidence threshold
  • Prunes old changelog entries
  • Zero latency impact (runs async)

Profile Schema

interface UserProfile {
  userId: string;
  schemaVersion: 1;
  lastUpdated: string;

  bio?: string;
  work?: {
    role?: string;
    focusAreas?: string[];
    languages?: string[];
  };
  codePreferences?: {
    tone?: "direct" | "neutral" | "friendly";
    detailLevel?: "high" | "medium" | "low";
    avoidExamples?: string[];
    preferredStacks?: string[];
  };
  tools?: {
    editor?: string;
    infra?: string[];
  };
  interests?: string[];
  custom?: Record<string, unknown>;
}

Swizzling

Switch modes anytime - both use the same profile.json:

# Switch from minimal → mcp
# Just update hooks paths in settings.json and add mcpServers

# Switch from mcp → minimal
# Remove mcpServers, update hook paths

Architecture Notes

Why Stop hook instead of SessionEnd? SessionEnd doesn't fire on Ctrl+C, terminal close, or crashes. Stop hook runs after every response - bulletproof.

Why heuristic extraction?

  • Zero latency
  • No API cost
  • Deterministic
  • MCP tools available for edge cases (mcp/ only)

Minimal vs MCP trade-offs:

MinimalMCP
DependenciesjqNode, tsx, MCP SDK
Real-time updatesNoYes (tool calls)
Cross-tool accessNoYes
Pattern coverageBasicExtended
PortabilityHighMedium

Directory Structure

skills/user-memory/
├── SKILL.md
├── minimal/              # Zero-dep shell scripts
│   ├── session-start.sh
│   └── stop-memory.sh
└── mcp/                  # Full TypeScript MCP
    ├── package.json
    ├── tsconfig.json
    └── src/
        ├── types.ts          # Type definitions
        ├── store.ts          # Profile storage + decay
        ├── context.ts        # Context injection builder
        ├── session.ts        # Session continuity
        ├── prompt.ts         # System prompt builder
        ├── extract-memory.ts # Pattern extraction
        ├── decay-check.ts    # Auto-decay on session start
        ├── mcp-server.ts     # MCP server (13 tools)
        └── hooks/
            ├── session-start.sh
            └── stop-memory.sh

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon