Workflow · 2026-05-06

Giving Claude Code Persistent Memory Across Sessions

Anthropic gives you a memory primitive. h5i gives you the layers above it — versioned reasoning, per-commit snapshots, and automatic injection at session start, so the next session always knows what the last one was thinking.

You ship a feature with Claude Code on Friday. Monday morning you start a new session, and Claude has no idea what you were working on. Not because the codebase changed — it didn't — but because everything Claude knew lived inside the prior session's context window, and that window is gone.

The fix everyone reaches for first is a memory file: jot the project state into ~/.claude/memory/<repo>.md and prepend it to every new session. That works for ten lines of project background. It does not work for "what files did I edit yesterday, which milestones are done, where am I uncertain, and what was the trade-off I rejected at 14:22 last Thursday." That information is the reasoning, not the project description, and it has structure. A flat markdown file flattens it.

h5i sits in front of Claude Code's memory primitive and adds three layers — a structured reasoning workspace, automatic per-commit snapshots, and a SessionStart hook that injects the right slice of it into every new session. Once it's installed, you stop re-explaining yourself.

What /clear actually destroys

A Claude Code session has four kinds of state. When the session ends or you run /clear, they evaporate at different rates:

StateLifetimeWhat survives
The conversation transcriptThe sessionJSONL log on disk, mostly unread
The active context windowUntil /clearNothing
Memory files (~/.claude/memory/)Across sessionsWhatever you manually wrote
Hooks & settingsPermanentConfiguration, not knowledge

Memory files are the only thing Claude carries forward by default, and they're a free-form text blob. There is no structure for "milestones," no link from a sentence in the file to the commit it describes, no automatic refresh when you commit code, and no way to branch the memory the way you branch code when you explore an alternative.

So engineers do what engineers do: they invent ad hoc structure inside the markdown file — ## Done, ## TODO, ## Decisions — and update it manually. The first week is fine. By week three the file is stale, contradictory, and nobody trusts it.

The three layers above the memory primitive

h5i treats memory the way Git treats files: as a thing you commit, branch, diff, and push. Concretely, it adds three refs to your repo and three classes of write operation:

All three are git refs, so they push and pull alongside your code. None of them touch your working tree.

The reasoning workspace

Run this once per project (or per major task):

~/my-project
$ h5i context init --goal "Migrate the auth service from Sessions to JWT"
  .h5i-ctx/ workspace initialized
   branch: main · goal recorded

During work, you (or Claude, via the PostToolUse hook) emit trace entries:

~/my-project
$ h5i context trace --kind OBSERVE \
    "session.rs uses tower_sessions; refresh_token belongs in JwtClient"

$ h5i context trace --kind THINK \
    "Issue refresh tokens server-side; access tokens stay client-side. 15-min TTL."

$ h5i context trace --kind ACT \
    "Replaced session middleware with JwtMiddleware in src/api/mod.rs"

And after a logical milestone, you commit the workspace:

~/my-project
$ h5i context commit "JWT middleware in place" \
    --detail "Sessions middleware removed; tests pass; refresh-token path TODO"
  milestone m1 recorded · DAG node 4f7a2bc

The trace and milestones live in refs/h5i/context. Every entry is a DAG node with a parent pointer, so reasoning has a topology — not just a timeline. When you fork an alternative, you h5i context branch experiment/refresh-rotation, work the side path, and either merge it back or abandon it. Either way, the abandoned branch is still there in history; you can always recover the rejected design.

Memory snapshots, pinned to git commits

Every h5i commit auto-snapshots ~/.claude/projects/<repo>/memory/ alongside the code commit. The snapshot is keyed by the git SHA, so memory is a first-class versioned artifact:

~/my-project
$ h5i memory log
9e21b04  2026-05-06 11:45  3 files snapshotted  +12 -3
a3f8c12  2026-05-05 14:02  3 files snapshotted  +5  -1
7216039  2026-05-04 09:18  2 files snapshotted  initial

$ h5i memory diff a3f8c12 9e21b04
+++ ~/.claude/projects/my-project/memory/decisions.md
+ - 2026-05-06: Switched to RS256 keys (HS256 felt fragile for multi-service)
- - 2026-05-04: Considering HS256 with shared secret per service

You can h5i memory restore <sha> to recover the memory file as it stood at any past commit, push it to teammates with h5i push, or simply diff it against last week's version to see how your understanding has shifted.

The SessionStart hook: zero-friction restoration

The previous two sections are the boring infrastructure. The thing that actually changes day-to-day life is the hook that runs every time you open Claude Code:

~/.claude/settings.json
// Generated by `h5i hook setup`
{
  "hooks": {
    "SessionStart": [{
      "hooks": [{ "type": "command", "command": "h5i hook session-start" }]
    }],
    "Stop": [{
      "hooks": [{ "type": "command", "command": "h5i hook stop" }]
    }],
    "PostToolUse": [{
      "matcher": "Read|Edit|Write|Grep|Bash",
      "hooks": [{ "type": "command", "command": "h5i hook post-tool-use" }]
    }]
  }
}

Now every new session begins with a synthetic system message that looks like this:

SessionStart hook output
[h5i] Context workspace active — prior reasoning follows.

  branch=main  goal=Migrate the auth service from Sessions to JWT
  milestones=2  commits=4  trace_lines=89+12

  m0: [x] JWT middleware in place
  m1: [x] Refresh-token endpoint wired up
  m2: [ ] Token rotation across deployments

[h5i] Last decisions & actions:
  THINK: RS256 keys; HS256 felt fragile for multi-service
  ACT:   Replaced session middleware with JwtMiddleware in src/api/mod.rs
  NOTE:  TODO: integration test for refresh during deploy

[h5i] Use `h5i context show` for full details.

The cost is calibrated by the --depth flag. Default is depth 2 — about 2,000-5,000 tokens, the timeline view above. Depth 1 is a compact 800-token index for token-conscious workflows; depth 3 dumps the full OBSERVE/THINK/ACT log. Claude can step up the depth itself when it needs more, by running h5i context show --depth 3.

Why this is better than a markdown file. The hook reads from a structured DAG, not from your hand-edited prose. It's always in sync with the last commit, because it is the last commit. You never edit it; you commit through it.

Branching reasoning

The most underused feature is h5i context branch. Suppose you're halfway through the JWT migration and want to explore using biscuit tokens instead. You don't want to lose your current thread, but you also don't want the side-quest polluting your main reasoning history.

~/my-project
$ h5i context branch experiment/biscuit \
    --purpose "evaluate biscuit tokens as JWT alternative"

# ... Claude explores; you trace the experiment ...

$ h5i context checkout main
$ h5i context merge experiment/biscuit
  Merged 6 trace entries · 1 milestone (rejected → reason recorded)

The rejected branch stays in history. Six months later, when someone says "why didn't we use biscuit?", you have the whole evaluation, with the prompts, the readings, and the reasons — not "I think we tried that once."

Try it on your next task

The minimum useful workflow is three commands once, then nothing:

first time only
$ cargo install --git https://github.com/Koukyosyumei/h5i h5i-core
$ cd your-project && h5i init
$ h5i hook setup  # paste the output into ~/.claude/settings.json

From there, the SessionStart hook does the work. You'll notice it the first time you open a new Claude Code session a week after a hard problem and Claude already knows where you stopped.

Stop re-explaining your project to Claude

h5i is open source, Apache 2.0, and works alongside any git remote.

Star on GitHub Back to docs