Skip to content

Months of Claude Code sessions you thought were gone.

Claude Code prunes transcripts after about 30 days. vir reads what's still on disk, filters out the noise, and writes typed markdown notes into a folder you own (your Obsidian vault, if you have one) — retroactively, in one run. Codex sessions too.

See what it writes ↓

Works with Claude CodeCodexObsidianMCPDataviewOllamaWeb Clipper

110 notes from the author's vaultA force-directed graph of 110 of the 167 notes vir wrote, connected by the links it derived between them. The most-connected notes are labelled; each is listed below the graph.multi-area-refactor-orchestrationaudit-first multi-phase deliverysupabase-enforces-db-invariantstrial-credit-atomicityschema-enumeration-stops-dropsautonomous-test-driven-scaffolding-under-uncertainty
  • multi-area-refactor-orchestrationpattern · 26 links
  • audit-first multi-phase deliverypattern · 24 links
  • supabase-enforces-db-invariantsgotcha · 17 links
  • trial-credit-atomicitygotcha · 17 links
  • schema-enumeration-stops-dropspattern · 15 links
  • autonomous-test-driven-scaffolding-under-uncertaintypattern · 6 links
110 of the 167 notes in my vault, linked as vir linked them. Hover one.167 notes · 4 types · 1,183 links
Obsidian graph view of a vault distilled by vir: session notes, articles, PDFs, and topic pages, cross-linked

The problem

Three weeks ago you and Claude spent two hours working out why the Kie.ai endpoint returns 200 with the error in the body. Today it happens again, on a different project. Neither of you remembers. The session that solved it was pruned eleven days ago, and the fix exists nowhere — not in the code, not in a commit message, not in CLAUDE.md.

vir is not a memory layer your agent writes to. It reads what already happened.

How it works

A loop, not a pipeline.

Sessions become notes. Notes feed the next session. The daemon keeps it turning while you work.

Hover or tab through a step.

Why not the alternatives

Two things that don't quite work, and one that does.

  • Falls short:

    Agent memory stores

    Built for the agent, not for you — memory in a format you never open. And they only know what happens after you install them.

  • Falls short:

    The transcripts themselves

    Readable and yours — until Claude Code prunes them at ~30 days. And nobody greps 243 JSONL files.

  • Works:

    vir

    Reads what's already on disk, drops the noise, writes typed notes into a graph you already look at.

The closest project to vir is Basic Memory — markdown, Obsidian, MCP, open source, and good. The difference is direction: Basic Memory has your agent write notes going forward. vir reads the sessions you already ran. They are compatible; the vaults can sit side by side.

What it writes

Anatomy of a note.

Every memory an agent-memory store keeps is for the agent. This is for you — and the agent reads it too.

You won't read four hundred of these, and you're not meant to. The agent reads them, through MCP. You read the three that matter, on the day they matter, because vir query found them or Obsidian's graph put one next to what you were already writing.

---
topic: "kie-200-error-body"
aliases:
  - "kie-200-error-body"
category: gotcha
project: "growthq"
session_id: 4f2a9c31-7d0e-4b8a-9c55-1e2f3a4b5c6d
date: 2026-06-01T09:14:22.000Z
confidence: 0.86
themes:
  - "kie-error-handling"
  - "retry-safety"
branches:
  - "fix/blank-posts"
---
Project: [[growthq]]
Category: [[gotcha]]

## Summary

This session debugged blank posts in growthq's image pipeline. The Kie.ai endpoint answers HTTP 200 even when generation fails: the error is only visible as `{ "code": 422, "msg": "..." }` in the body, so `res.ok` treats every failure as success and the job polls forever.

## What Was Learned

- **Check the body's `code`, not the HTTP status.** The client now throws when `code !== 200` before trusting `res.ok`.
- **Retry only on `code` 5xx.** 422 means the prompt was rejected and will be rejected again.

## Context

The generation queue had been producing blank posts for two days.

## Related

- [[retry-with-backoff-0c91be7a|retry-with-backoff]]
- [[kie-ai-task-polling-loop-a83e21f0|kie-ai-task-polling-loop]]
  1. [[wikilinks]]

    Project and category links, plus the Related section, are why the graph fills in on its own.

  2. confidence

    How sure the classifier was. Low-confidence notes render dimmer in the vir Obsidian plugin.

  3. ## Related

    Rebuilt from embedding neighbors, not from what the LLM guessed it should link to.

  4. session_id · date

    Provenance. Every claim traces back to the exact session that produced it. Open the note, read the id, and you know where the sentence came from.

Inputs

Three inputs, one vault.

Everything embeds into one vector space (built-in or Ollama, TF-IDF fallback), so vir query searches across all three.

Retrieval

Ask the vault. Or let the agent ask it.

$ vir query "how did we handle kie 200 errors" Kie.ai answers HTTP 200 even whengeneration fails; the failure only showsas code 422 in the body. Parse the bodyfirst, throw on code !== 200, and retryonly on 5xx. ────────────────────────────────────────  · gotchas/kie-200-error-body-4f2a9c31  0.81  · patterns/retry-with-backoff-0c91be7a  0.64────────────────────────────────────────sources 2 · via embedding · searched 460

Mid-session, without you asking

vir mcp exposes the vault to Claude Code or Codex as an MCP server, so the agent consults past decisions instead of rediscovering them. The gotcha above surfaces the next time Claude touches that endpoint — on any project.

Back into CLAUDE.md

vir sync-claude feeds the best notes back into your project's CLAUDE.md (and AGENTS.md), with a diff and your confirmation. Nothing is written without you seeing it first.

Lessons you keep re-learning

vir connect spots a lesson you've written down in three sessions a week or more apart and proposes it as one rule, quoting every note it came from. You review it; it reaches CLAUDE.md only with a yes for that rule. How it decides

Any agent, not just Claude Code

npx skills add djolex999/vir installs a read-only skill that has Codex, Cursor and other skill-aware agents check your notes before they work. What it does

Measured, not scored

There is no benchmark here.

Every tool in this category leads with a score — LongMemEval, LoCoMo, recall@5. None of those measure the thing that matters: whether the notes turned out to be worth reading. So here are the only numbers I have, from one machine.

397
sessions. Claude Code would have pruned these. They now exist nowhere else.
2,012 → 460
transcripts, notes. 1128 were subagent runs, workflow phases, or sidechains — skipped by default. 424 had nothing durable in them. 460 became notes.

Author's machine, September 2026. Yours will differ.

Your numbers

Run this before you install anything.

Mine are one machine's. Yours are the only ones that matter, and you already have them — Claude Code has been writing transcripts to your disk since the day you started.

find ~/.claude/projects -name '*.jsonl' | wc -l
find ~/.claude/projects -name '*.jsonl' -mtime +25 | wc -l
  1. First number

    Every session Claude Code still has on disk. vir reads all of them in one pass.

  2. Second number

    The ones older than 25 days. Claude Code prunes at around 30, so that's roughly what disappears in the next five — whether or not you do anything.

Both commands only count files. They read nothing, send nothing, and change nothing. Not all of the first number becomes notes — most transcripts are subagent runs and workflow phases, and vir skips those.

What it costs you

Time and money, up front.

  1. 60 secondsnpm install -g, then vir init — a wizard: provider, models, vault path.Free.
  2. One runMonths of history become a vault.$25.85 for 297 sessions over six months, on the Anthropic API. On a Claude subscription via the claude-cli provider: no API spend at all.
  3. Ongoingvir schedule install registers a daemon that keeps the vault current.Median $0.004 per session, $0.14 at the 90th percentile.

vir run --dry-run estimates your own history before you commit to a full run; vir cost reports what you actually spent.

Claude Code forgets. Your vault doesn't.

Install.

npm install -g @djolex999/vir-cli
vir init
vir run

vir init is a wizard: provider, models, vault path. vir run does one pass over your sessions and writes notes. When you like the output, vir schedule install registers a daemon that keeps the vault current.

Full setup, configuration, and every command: the docs.

macOS or Linux · Node 20+ · Claude Code or Codex · Obsidian optional — the output is plain markdown either way

What actually leaves your machine

Transcripts are classified and distilled by an LLM, so their content goes to whichever provider you configure — including your Claude subscription via the claude-cli provider. Nothing else leaves the machine: no server, no account, no telemetry. Embeddings are local (built-in or Ollama) or TF-IDF.

Follow along

Solo project, shipping in public.

No mailing list, no account. Three ways to see what changes, all of them ones you already use.

  • Star on GitHub

    15 so far. Where the code, the issues, and the roadmap live.

  • Watch releases

    GitHub → Watch → Custom → Releases. One notification per version, nothing else.

  • Subscribe by RSS

    virwiki.dev/changelog.xml — every release note, in your reader.

Also on npm, and the full history is on the changelog.

The pattern

In April 2026, Andrej Karpathy described a pattern he calls the LLM Wiki: AI work that feeds back into itself through a persistent, curated, structured artifact instead of resetting at the end of every session. He published the idea as a gist and a post.

Several implementations of this pattern exist. vir is the retroactive one, built from your own sessions, and Obsidian-native when you want it.