github vshulcz/deja-vu v0.22.1

3 hours ago

Reading a session back now shows the code it changed, each edit as the lines
it removed and added, for Claude Code, Codex and every harness whose
transcript holds its edit calls. A Codex session opens in the ChatGPT desktop
app with deja resume <id> --app, and the screen gets find in a session,
filters in the box and cards that lead with the question. Session start takes
0.38 s instead of 1.46 s and the per-prompt hook 0.59 s instead of 1.65 s on a
19k-session index, and an opencode 2.x store no longer stalls a new session's
first request. Secrets that slipped past redaction are masked, and the index
holds up under crashes and concurrent use. The index version is now 70, so the
store rebuilds once on the first run after upgrading.

Added

  • Reading a session back shows the code it changed, each edit as the lines it removed and added. MCP recall_context and the session resource put it ahead of the conversation, deja ctx after the digest. Drafts the session rewrote are folded into their final form, the project's code comes before its tests, and the agent's reproduction scripts and notes are left out. On 48 SWE-ContextBench tasks the session that fixed the same code used to arrive with none of its fix; now 14 show most of it. Read from the transcript when asked, so the index stays the same size and keeps the written side as hashes. Claude Code, Codex and any harness whose transcript holds its edit calls as JSON, one session per file (#4935, #4950, #4955).
  • deja resume <id> --app opens a Codex CLI session in the ChatGPT desktop app on macOS and Windows, and the screen's continue picker offers the app first for a Codex session (#4907).
  • The screen's cards lead with the question asked, the home list is grouped by day, and dates count calendar days. The preview shows how the session went, turn by turn, with the commands and the files it edited. In the reader / finds a word in the session, n and N step through the matches, ] and [ jump between the turns you asked, and t unfolds long messages. The box takes filters: an agent with a colon (codex:), today, yesterday, week, month and in:<project>. A search that finds nothing names the other projects that have it, or the spelling your history uses. The Kept tab is now Deleted, headed "Deleted by their agent, kept by deja", and tab cycles this project, all projects and Deleted. The continue picker preselects and marks the agent used last and folds agents not installed into one line. ^k also copies the session id or project path and forgets a session, after asking, and ? lists every key (#4911).

Changed

  • Reading one session back no longer walks the whole record log: a table beside it says where each session's records are, and the first line of each repeated error is kept at build time. On a 19k-session index session start takes 0.38 s instead of 1.46 s, MCP recall 0.95 s instead of 1.29 s and deja show 17% less, for 0.33% more index. A full rebuild there takes about 3 s longer to write the error lines (#4940).
  • Hooks answer faster on a large history: on a 19k-session index the per-prompt hook takes 0.59 s instead of 1.65 s and a cold session start 0.74 s instead of 1.42 s, with the same output. Worktrees are listed once per hook instead of once per name lookup, projects are scoped once per name, long sessions are scanned on all cores, and repeated errors are read back in one pass over the record log. The session-start hook runs git status without taking the repository's optional lock (#4934).
  • Switching tabs on the screen takes 7 ms instead of 46 for this project and 21 instead of 74 for all projects on 27k sessions, and Deleted is instant: the count of every session is read again only after the index changes, and the newest 60 are picked without sorting all of them (#4915).
  • The screen's first run shows the index being built: the stage, a bar, each agent ticking in with its session count and the seconds so far, and it lets you in once the newest sessions are searchable. The first open after an upgrade shows what the new version brings, leaving for an agent names where you are going, and a command waiting out another deja's rebuild shows a live line with the seconds, then says the index is ready. Resume and continue picked on the screen use that exact session and no longer wait for a rebuild, so an id that prefixed another no longer hands off the wrong one. deja upgrade points at deja update instead of searching for the word (#4898).
  • deja sources takes 2.1 s instead of 28.6 s and a full rebuild 5.7 s instead of 37 s on 27k sessions: a Claude Code folder whose transcripts record no fitting working directory was listed again for every transcript. Everyday commands run about twice as fast, deja last 0.34 s instead of 0.65 s, since they no longer stat the store roots for each file (#4902).
  • deja stats groups its counts (27,262), and deja restore lists the newest 30 replaced spans, --all every one, and says 1 replaced span (#4904).

Fixed

  • A new opencode 2.x session no longer stalls its first request while deja reads its lineage, and a background refresh no longer keeps SQLite busy for over a minute: the session is read by its exact id, and each read names the sessions it wants inside the message query, so SQLite uses the store's index instead of decoding every message. On a 475 MB store one session takes 13 ms instead of 6.3 s and an incremental pass 96 ms instead of 5.3 s. The 2.x plugin also gives a hook 10 s before the turn goes on without memory, and deja doctor reports a plugin without that limit as stale; run deja install opencode-auto again to get it (#4951).
  • The code a session changed, read back with it, leaves out the edits its harness refused: a denied call, a file not read first, a Codex patch that failed to apply. 1.2% of edit calls on one Claude Code history came back as errors and showed as code the session never wrote (#4953).
  • Fix pairs kept up to date pass by pass now match a rebuild: an append mined only the new turns and missed a fix whose error came before them, a promotion could not be taken back when its session was read again, and pairs of sessions no longer indexed stayed. A line an agent's store writes twice is stored and counted once (#4940).
  • Hermes sessions carry who started them: a subagent's run folds under the session that spawned it, and a cron job's run stays searchable but is no longer offered unasked at session start or on a prompt. A Postgres Hermes store now names each session's project from the directory it ran in, as the SQLite one does (#4948).
  • deja doctor reports a dsh plugin written before #4937 as stale, with deja install deepseek-auto to fix it: it still calls deja, so it read as wired while dsh refused its notices (#4944).
  • On dsh (DeepSeek Harness), a turn in which deja injects a notice — the recall block, a file's note before an edit or a failed command's fix — no longer fails with "format v4 message requires a producer-owned source kind" and stops the session log from growing until a restart: the notice carried the retired v3 source wrapper, which DSH v4 refuses while encoding the append. The notice now carries the producer-owned kind DSH's own migration gives an unmapped plugin (plugin:deja), in the extension and the installer template, so an existing install picks the fix up by running deja install deepseek-auto again (#4937).
  • On Hermes, a cron job no longer runs deja recall on every fire: the plugin hook and the memory provider skip automatic recall when Hermes says the platform is cron, and the deja tools still answer when the job calls them. Run deja install hermes-auto again to get it (#4946).
  • --json output matches docs/json-output.md: fix, how and wip give the command as typed, without the $ prompt or the exit status, wip and recap filter bidi and tag characters like search and show, messages_total counts the whole session, blame rows carry source, undated and empty fields are left out instead of printed as year one or zeros, and a full id that starts another id reads its own session in show, with or without --json. A test checks every --json surface against its section (#4934).
  • Titles and how a session settled stay what a rebuild gives them on append and import: a session opened with "hi" or named from the agent's words takes the first real question when it arrives, and a re-import no longer blanks a title. A transcript whose sessions were all forgotten is not kept once deleted. The random-history test now covers Codex, opencode, forget and sync (#4934).
  • deja forget names forks that still hold a copy of the forgotten turns and the command to forget them too. deja handoff no longer hands off a remembered note, deja sources honours DEJA_STORES, stats --card prints no escape codes into a pipe, uninstall keeps the backup of someone else's [mcp_servers.deja] in Codex, Grok and TRAE, and legacy Cline tasks date each turn from its own timestamp (#4934).
  • The docs no longer promise what deja does not do: the quickstart says what to do when ~/.local/bin is not on PATH, search sends the query to the embedding endpoint once a semantic sidecar is set up, the wipe recipe also removes notes and config, deja check covers repeated errors only, q quits from the list, and the agents page counts hook surfaces from the registry (#4934).
  • How a session settled, the line shown under a command an agent is about to run, is updated as the session grows instead of staying at what its first pass saw, and two sessions running a command in the same second no longer name whichever was read last. A test now indexes random histories pass by pass and checks them against a rebuild (#4932).
  • Secrets that slipped past redaction are masked: a token split by color escapes (grep --color, colored loggers) was stored and shown in the clear by show, recall and search --json, sk-proj- and sk-ant- keys kept their tail after the first -, and private keys cut short, indented or written inside JSON, PGP keys with headers, Authorization: Token and Slack and Discord webhook URLs went through. deja share now also masks home paths and emails, and the home path mask catches encoded folder names like -Users-<name>-src, non-ASCII names and names with a space. Sync imports a record re-redacted on the other side once, and counts records it cannot read instead of saying it is up to date (#4930).
  • The index holds up under crashes and concurrent use: a search racing a rebuild could label a hit with another session or report damage that was not there, a hole in the record log dropped every record after it on the next pass, zeroed records or postings searched as empty without flagging damage, and a write of the manifest alone could adopt a half-written tail and store turns twice. A read-only mount answers from the index, a session or warmup stamped in the future no longer stops indexing, and a torn fixes table is mined again rather than emptied. An index a newer deja wrote in the same layout is answered from and left alone instead of rebuilt down, so two installed versions stop rebuilding it back and forth (#4930).
  • Readers no longer lose or repeat turns on resume: goose turns written in the watermark's second, Codex rollouts with a session_meta line over 1 MiB or a tail of events only, Command Code's first prompt, a last line written without its newline, Qwen exit codes and failed apply_patch in OpenClaw and the pi family. Claude sessions started from the home folder keep their project, JSON stores starting with a byte order mark are read (Amp, Cline, Roo, Kilo, Continue, CodeWhale, Grok, Aider), Copilot agent commands are stored once, Continue reports a file it cannot read and Reasonix reads state with a trailing comment (#4930).
  • Uninstall keeps the backup of an MCP server named deja that deja did not write, reinstalling restores the hook launcher's exec bit, opencode and Kilo uninstall no longer add an empty mcp block, status line writers read settings with comments, goose uninstall no longer puts back deja's own recipe and a repeat Grok or TRAE install leaves the config alone. deja doctor names a command that runs, reads CodeWhale and Reasonix without hooks as missing rather than stale, and reports Roo wired only when Roo's own config has deja (#4930).
  • A pasted issue, log or spec used as the query finds the session about the same thing rather than a long session that touches many of its words: searching 362 SWE-ContextBench issues against the same repository's past tasks, the matching task comes first 51.9% of the time instead of 42.5%, and is in the top ten 83.7% instead of 78.2%. Questions rank as before (#4925).
  • The first search after an upgrade no longer drops sessions whose transcript was deleted or turns a harness compacted away: it runs the same rebuild as deja index --rebuild. Sessions appended between rebuilds get the same date tokens and tool ranking a rebuild gives them, a synced session ranks and reads like a local one and its commands and fixes count at once, and a transcript moved by codex archive or a renamed project folder is followed instead of being reported deleted (#4924).
  • On the screen, forgetting a session in Deleted takes its card away, the reader picks up a session that grew while open, a match far along an unwrapped line or past line 400 of a message is shown and found with /, and a long paste in the box no longer slows every frame (#4924).
  • deja show <prefix> --harness resolves within that agent, stats --impact and --redaction refuse the flags they ignore, forget --dry-run lists the ids it would remove, blame path:abc searches the file as it says, deja <words> --help prints help and an unknown flag after a query is refused instead of searched, and log abc and bench --seed abc say what is wrong (#4924).
  • A note stored over MCP is filed under the working directory's project, the word "cursor" in a prompt no longer hands off to a Cursor session, blame of scripts/load no longer matches the word "load", a miss during a refresh no longer says the index is empty, orient no longer denies a project that has sessions, MCP follows JSON-RPC for ids and error codes and returns tool failures as results, and a hook payload starting with a byte order mark is read (#4924).
  • An index kept up to date for weeks no longer grows past what a rebuild of it holds: a pass that rewrote the record log posted every carried record's whole text, hashes of written lines and full build logs included, and dropped the bit that ranks tool output below what people said. Searches here run 21% faster after the rebuild this version triggers, and the buckets went from 81 to 62 MB (#4919).
  • Typing on a large history no longer stalls the screen: it ran one search per letter, and now searches when you pause. A refresh keeps the selected session, a search typed during the first build survives the build ending, a session that grew is read again, a session put back leaves Kept, the reader's ctrl keys no longer edit the list behind it, ? on an empty search box opens help instead of becoming the query, and the wait line no longer draws over the screen (#4900).

Changelog

Features

  • feat(bench): serve deja as the Add/Search memory API the Agent Memory Leaderboard calls (#4928)
  • feat(recall): a Codex session read back shows the code its patches changed (#4952)
  • feat(recall): reading a session back shows the code it changed, ahead of the conversation (#4936)
  • feat(recall): sessions from other harnesses read back with the code their edit calls changed (#4956)
  • feat(resume): open a Codex session in the ChatGPT app with --app or from the continue picker (#4941)
  • feat: screen cards lead with the question, find in a session, filters in the box (#4911)

Fixes

  • fix(docs): date sitemap pages by the UTC day, not the author's (#4922) (@theluckystrike)
  • fix(doctor): report a dsh plugin with the retired notice source as stale (#4945)
  • fix(dsh): injected notices carry a producer-owned v4 source kind (#4938) (@akushonkamen)
  • fix(hermes): a cron job no longer runs deja recall on every fire (#4947)
  • fix(hermes): a subagent run folds under its parent and a cron run is not offered unasked (#4949)
  • fix(index): a rewriting pass posts what a rebuild posts (#4919)
  • fix(opencode): read a 2.x session by exact id and name changed sessions inside the CTE (#4957)
  • fix(recall): leave edits the harness refused out of the code a session changed (#4954)
  • fix(search): a pasted issue finds the same bug before a long session that brushes its words (#4927)
  • fix(sources): a transcript written just after a cwd miss is read again (#4913)
  • fix(tui): no waits after picking a session, live first run, what's new in the screen (#4898)
  • fix(tui): typing stalls, a refresh moves the pick, and smaller screen bugs (#4900)
  • fix: hook latency, JSON contract, docs claims, random histories across stores (#4934)
  • fix: screen, index update paths, CLI flags, hooks and MCP (bug sweep) (#4924)
  • fix: secrets redaction, index crash safety, harness readers, install and doctor (bug sweep 2) (#4930)
  • fix: stats groups its counts, restore lists the newest 30 spans unless --all (#4904)
  • fix: wag the cat's tail while the first index builds (#4623) (#4909) (@theluckystrike)

Performance

  • perf(index): per-session offset table and stored wall lines; fix pairs and repeated lines match a rebuild (#4940)
  • perf(sources): keep a folder's cwd miss for older transcripts, match claude roots as strings (#4902)
  • perf(tui): tab switches stop re-reading and sorting every session (#4915)

Documentation

  • docs(guide): the delete page asks how to delete sessions and leads with the one-session case (#4921)
  • docs: bring README, site, guides and plugin docs up to date for the release (#4959)
  • docs: changelog for 0.22.1 (#4961)
  • docs: the interactive screen across README, site and guides, and a pass over every page for stale or wrong claims (#4906)

Other

  • chore: pin the manifests to 0.22.0 (#4895)
  • test(docs): compare sitemap dates to the commit's UTC day, as genregistry writes them (#4943)
  • test(index): random histories must index the way a rebuild does (#4932)
  • test(tui): wait for the screen's background work before temp dirs go (#4917)

Install

curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh
go install github.com/vshulcz/deja-vu/cmd/deja@v0.22.1
brew install deja-vu

Don't miss a new deja-vu release

NewReleases is sending notifications on new releases.