deja secrets lists the sessions whose transcripts still hold an API key, a
private key or a password inside a URL, by kind and file, and never prints the
value. deja recap quotes what the last week settled, deja tests reads the
build and test runs already in the transcripts, and deja stats --year puts a
year of work in one screen. Line-level blame now also answers for lines a
session wrote, not only the ones it replaced, and the written side of an edit is
read from Zed, Antigravity, Copilot Chat, Copilot CLI, Cursor, Kimi and
opencode's diff store. CodeWhale is the thirty-fourth harness, and the Zed
extension is now deja-mcp-server.
Changed
- The stats card leads with what happened to your code.
spans replacedtakes the middle cell from the message count, and the headline stops saying "1 questions". (#3787) - The incremental index line is a sentence:
deja: re-reading 306 changed transcriptsinstead ofincremental index changed_files=306 removed_files=0 sessions=1789, with zero counts left out. (#3769) - The Zed extension is
deja-mcp-serverand carries the context server only. Zed's registry takes an MCP extension under a*-mcp-serverid and no longer takes slash commands, so the/dejaslash command is gone; the server key staysdeja-context-server, so adeja install zedentry and the extension still resolve to one server. - A crowded top of the ranking gets a second pass over the best message. The relevance tier already reranks that way on a large store, where the whole-session total drifts; the gate was store size alone, so on a benchmark haystack or a young store the pass never ran even when the first and second place were a rounding apart. It runs now whenever the gap between them is under 30% of the leader, which is the shape the pass exists for. LongMemEval-S hit@1 85.3% → 86.6% on the 470-question cleaned set, preference questions 36.7% → 43.3%.
- A question that names one day prefers sessions from that day. "What did we decide on Monday", "what broke on the 14th" — the date was a word in the query like any other, so a session that merely said "monday" outranked the one written that Monday. The day is resolved from the question and fused with the word ranking rather than replacing it, and it stands down on three conditions measured into it: a span ("last week") is not a day, a counting question ("how many times since Friday") is not about one day either, and a day outside the candidates' own range is not evidence. Temporal questions 81.1% → 83.5% hit@1, total 86.6% → 87.2%.
Fixed
- opencode 2.0 stores are read. 2.0 renames
sessiontosession_v2and moves a session's turns out ofmessageandpartinto onesession_messagetable, so every query deja ran came backno such table: session: the harness reported unreadable and none of its sessions reached the index — 154 of them on the store in the report. Both layouts are read now, chosen by where the turns are, along with what moved inside a turn:bashisshellandapply_patchispatch, a tool names itself under$.name, what it printed is the block list$.state.content, and the file it opened is$.state.input.path.edit, which is 2.0's editing tool, carries the text it replaced and the text it wrote, sodeja restore,deja filesand line-level blame answer for an opencode 2.0 session — the 1.x reader only ever sawapply_patch. A compaction's summary is indexed under the summary role. Checked against opencode 2.0.12 run in a throwaway home: 4 sessions, 14 records, the shell command with its exit status, the file read, and both sides of the edit. Reported by @yourfriendaaron in #3924. (#3924) - A resumed or forked conversation no longer counts as a question asked twice. A resume copies each message with its original timestamp, so the same question at the same moment in two sessions is now one asking, in the stats headline, the card and the note after the first build. (#3906)
- A relevance answer says how much actually matched. The label meant "nothing matched" but was also put on strict answers with a thin ranking underneath, which was every relevance answer in a 93-query sweep; a quoted query retried without its quotes gets the same correction. (#3816, #3819)
deja doctormeasures freshness from when deja last read the stores. An SSH import rewrote the manifest's build time without opening a local transcript, so a machine syncing on a timer was called up to date over transcripts it had never read. (#3775)deja install --autoon a machine with no agent says what it looked for and what to run next, instead ofno known agent config directories found. (#3835)deja install dshanddsh-autowork. The DeepSeek Harness guide printed those names and the binary only knewdeepseek; a test now checks everydeja install <target>the docs print. (#3869)deja secretsnames the transcript file for Cline, Copilot Chat and DeepSeek Harness sessions too, which write one file per session under.jsonor.zstdrather than.jsonl. (#3874)- An opencode diff file folds into the session it belongs to instead of reading as a second transcript with the same id. (#3800)
- A store the size of a fresh install gets the relevance tail it was built for. A thin strict answer hangs the relevance ranking underneath it so a question whose wording excluded the answer can still reach it — and that was switched off for any store no bigger than the ranking window, which is every new user and every benchmark haystack. It is bounded there instead of absent: a fifth of the store, never more than ten places, and nothing at all below a dozen sessions. LongMemEval-S hit@1 87.2% → 88.1%, hit@5 95.4% → 97.4%; LoCoMo hit@5 85.7% → 90.9%, R@10 → 95.6%.
- The floor under that tail was one session too high for real conversations. At twenty, two LoCoMo conversations of nineteen sessions each — 302 of its 1,982 questions — were answered with the strict hit alone. At twelve: R@10 94.9% → 95.6%, R@20 97.0% → 97.7%, questions the ranking never reaches at all 60 → 45, hit@1 flat either way. LongMemEval,
deja bench prompt|recall|contextand day0bench are unchanged; giving the strict head an absolute lead on a small store was measured instead and is worse (LongMemEval 87.9%), so the tail keeps its bounded promotion. Zed's registry takes an MCP extension under a*-mcp-serverid and no longer takes slash commands, so the/dejaslash command is gone; the server key staysdeja-context-server, so adeja install zedentry and the extension still resolve to one server. - A manifest rewrite is visible to the process that made it. The read-only manifest cache is keyed on
manifest.gob's mtime and size, and its own comment said that is a pair the atomic swap always changes — it is not. A rewrite that keeps the size and lands inside one tick of the filesystem's timestamp resolution leaves both identical, and every surface that reads through the cache — doctor's read state, the session count, friction, the brief — then answers from the manifest before it. It surfaced as a test that failed on CI and passed on every developer machine, which is the honest shape of a clock-resolution bug; the writer now drops the cache entry itself, and the stamp stays as what catches a rewrite by another process. A test reproduces the collision deterministically by putting the second write back on the first one's timestamp, and fails when the invalidation is taken out.
Added
deja secretslists the credentials your agent transcripts are carrying: grouped by session, with the kind (AWS key, GitHub token, private key, URL credentials, bearer token and so on), the project, the date and the file to edit or delete. It never prints a value; deja's own index was already redacted, and the report says so.--jsonand--limit 0for the full list. (#3822)deja testsprints the build and test runs already in the transcripts: runs per week split into failed, passed and no verdict, then the tests that failed on more than one day. Nothing new is captured. (#3831)- Install ends with a question built from your own history and already run, in place of a placeholder search:
what did we decide about <two words from your session titles>?. (#3814) deja blame <path>:<line>answers for lines a session wrote, not only lines it replaced. 71% of commits delete nothing, so the replaced-text rule could not reach most added lines; the answer names which rule found it,replaced:orwrote this line:, and quotes the turn the edit sits in. (#3810, #3817)deja blame <path>:<line> --attributionprints the line answer alone, as one object with--json;--git-noterecords it on the commit underrefs/notes/deja, opt-in and refused when nothing is attributed. (#3812)- The written side of an edit is read from Zed and Antigravity, which keep it on the tool result, and from Copilot Chat, Copilot CLI, Cursor and Kimi, which were dropping it; opencode's per-session diff store under
storage/session_diff/is read too.deja restore,deja filesand blame now have something to answer from there. (#3811, #3818, #3793) deja sync sshnames each phase before it starts, repeats it every ten seconds while it runs and ends with where the time went, so a large push no longer looks hung. The remote's output arrives line by line. (#3813)deja install gjc-autowires auto-recall into gajae-code through the extension directory it loads. (#3859)- The
/dejareply in dsh, and a new/dejacommand in OpenClaw, carry deja's note after the first build and its weekly count, which only reached the model there before.deja hook-context --notesprints just those notes. (#3895) scripts/longmemeval -score <file>scores a ranking another system produced, with the same arithmetic as deja's own runs and no deja in the loop. (#3795)- Roo Code, Kilo Code and the legacy Cline extension record what an edit changed, not only which file it touched. Their editor sends the two sides of a change as a SEARCH/REPLACE block under
diffrather than asold_stringandnew_string, so the three readers kept the path and dropped the change itself:deja restorehad no span to hand back from those stores and line-level blame could not attribute a line to any session in them. The SEARCH body is the replaced span now and the REPLACE body the hashed written lines, withsearch_and_replace's two literal sides and the whole-file writes (write_to_file,insert_content) read the same way. Two things are deliberately not recorded: asearch_and_replacewithuse_regex, since a pattern is not text the file ever held, and a block whose closing marker never arrives, since where it was meant to end is a guess. Both are pinned by tests that fail when the rule is taken out. The shape is Roo's own diff strategy and the task fixture from #3295; no store on hand carries a Roo edit, so this is verified against the format rather than against an index. What the stand did find is that the records these three readers already wrote name a path relative to the workspace, the way Roo's tools take one — so an edit at the root of a checkout was recorded asloop.go, and line-level blame, which matches a record to a file by their last two segments, could never match a one-segment path. The workspace is in each store's own task metadata and the records carry the full path now. In a hermetic stand — one Roo task, its own index directory —deja restorereports the span, and blame on the changed line went from "no indexed session wrote this line" to naming the session and printing the line it wrote. (#595) deja stats --yearis the last twelve months of somebody's own work with agents in one screen. Counts describe a store; this describes a year, over every harness on the machine rather than one report per tool: sessions and agents, the busiest project and day, the longest session, the files and distinct commands the agents worked through, the replaced spansdeja restorestill holds, how many questions came round a second time, and the three errors the machine kept hitting. Two rules it keeps. Every number carries the arithmetic that produced it — "28 of 838 questions were asked in more than one session", not "3% redone", and "20,989 files, deduplicated by path, from 48,053 records naming one" rather than a figure whose unit is a guess. And it is written to be shown to other people, so the project names, the session title and the quoted error lines take the outbound redaction pass on the way out and the screen says what that removed, the same ruledeja recapfollows. The window takes no filters:--harness,--project,--sinceand--roleare refused rather than narrowing the sessions and leaving the record counts whole, which would print a report that does not add up.--jsoncarries the same numbers withwork.recordsbesidework.filesso a consumer can see the deduplication for itself. The record counts come from one pass over the store rather than one per kind, which is where the cost of this screen is. Measured on a 2,437-session year: 20,989 files, 42,031 distinct commands, 17,120 replaced spans in 1,899 files. (#578)deja recapsays what the last week settled, quoted from the sessions and grouped by project, with the harness, date and session id behind every line. It writes no prose of its own. The output is meant for a PR description or a standup message, which is the wrong place for an address or a home path, so a recap takes a second redaction pass on top of the index's and says what that removed.--since,--limit,--json. (#544)- CodeWhale's store, the thirty-fourth harness deja reads. It is the Rust terminal agent that shipped as
deepseek-tuiuntil v0.8.41, not the DeepSeek Harness already here: one pretty-printed JSON file per session under~/.codewhale/sessions, whose content blocks are the Anthropic shape the Cline and Claude readers already take apart — so a call becomes a command or a file record,tool_resultbecomes tool output with the error runs kept, andthinkingis dropped. The pre-rebrand~/.deepseek/sessionsis read too while the harness is still migrating it, unless$CODEWHALE_HOMEsays otherwise, which is an isolation boundary in CodeWhale's own resolver. The file carries no per-message timestamps, so the session's own start is the clock at a millisecond a record and two identical turns stay two.deja resumehands a session back withcodewhale --resume <id>, verified against 0.9.13's own flags. - The privacy page in Chinese, which is the page that decides whether a reader installs anything at all. It carries the whole boundary rather than a summary: what is indexed (the conversation and what the agent did, the compaction packet on two harnesses), that indexing and search have no network path and which three commands are the exceptions, the full redaction list including the prose-password rule from 0.20.2, and every control — exclude a project, exclude a whole store, forget, the redaction report, the injection log, trust scopes. Including the two things a privacy page has to say out loud: pattern matching is not secret detection, and a credential that reached a transcript was already sent to the model provider, so rotate it. The Chinese guide is nine pages now against six this morning.
- A page for deleting Kilo Code task history, which is two stores that know nothing about each other: the VS Code extension writes a directory per task under
kilocode.kilo-code/tasks/<id>/, and the CLI keeps its own SQLite database at~/.local/share/kilo/kilo.db. Clearing one leaves the other, which is how a conversation somebody meant to remove stays on the machine. The page names both, says whereglobalStoragesits on each host — Code, Insiders, VSCodium, Cursor and Windsurf each keep their own, so one extension can have several unrelated task trees — and what a task directory is the only record of. Six problem-shaped pages now, against two this morning. - A page for deleting opencode session history, which is the store shaped least like the others: one SQLite database holds every session, every message and every part, so the unit of deletion is the whole history rather than a conversation. The page names the three tables and their joins, says to delete from the client because the database is live state it owns, and carries the two things people get wrong — removing rows does not shrink a SQLite file, since the freed pages are reused, and there is no archive behind a removed session. That makes five problem-shaped pages in the guide against two this morning.
- Two more pages for the questions search actually asks, and the Claude Code one in Chinese.
Delete Gemini CLI chat historyanswers something no documentation covers: the chats sit under~/.gemini/tmp/<project-id>/chats/in a directory named after an id rather than a path, so the page gives both ways to map it back —~/.gemini/projects.jsonand the.project_rootmarker — names the prompt log beside them that deleting the chats does not touch, and warns that the sametmptree holds Antigravity's store on some installs, which is why deja reads the two apart.Session files on disk, the page that answers how to delete Claude Code sessions and how large~/.claude/projectsgets, now exists in Chinese with its numbers intact — 875 files, 1.6 GB, a 304 KB median against one 586 MB outlier, and the 30-day sweep nobody is told about. The guide's problem-shaped pages went from two to four; 22% of the readers who reach this repository open the Chinese README, and the Chinese guide went from six pages to eight. - A guide page for deleting VS Code Copilot Chat history, which is a question with a real answer and no documentation anywhere. Two pages of that shape existed — "delete Codex sessions", "delete Cursor chat history" — against thirty-three stores. This one carries what the audit for #3637 established: two stores,
chatSessionson older builds andGitHub.copilot-chat/transcriptson newer ones, both present on a machine that has been through the upgrade and holding different chats; theworkspace.jsonbeside them is what turns a hashed directory back into a project name. The numbers are from one real machine — 179 workspace directories, 28 withchatSessions, 5 with transcripts, and on VS Code Server 1.137 nochatSessionsat all with 47 transcripts holding eleven weeks of chats, which is why "my history is gone" after an upgrade is usually "my history moved". What deleting costs is stated too: 11 of those 47 transcripts have no user turn at all, so they are an agent run and the only record that the work happened. - The page that answers "where does my agent keep its history" exists in Chinese. Six of the guide's fifty-four pages were translated, and the store table was not among them. The table is generated from the English page rather than retyped, so the thirty-three paths cannot drift apart and only the format column is translated; the
hreflangpair is declared on both sides, since one side alone is discarded and the two pages then compete as duplicates of each other. Both sitemaps carry it — the text one is the second way in, after Search Console read the XML as "could not be processed" twice. - The page that answers "where does my agent keep its history" lists every store, and the guide stops undercounting. Its table held 25 of the 33 stores: Kilo Code, Kiro, Cherry Studio, Command Code, ZCode, Kimchi Coding, gajae-code and Senpi were missing, so the page whose whole purpose is completeness answered nothing for eight agents. Its lede said "twenty-five agents, one table" — and that sentence is why nothing caught it: the word check pins seven named documents, the digit check reads only numerals, and a count spelled out in prose anywhere else was unchecked. The check now covers every page in the guide, which immediately found twelve more: "twenty-five harnesses" on the find-a-session, lost-context and resume-a-session pages, and "thirty agents" on nine per-agent pages. A relative count is left alone, because two shapes are honest — "and twenty-seven more agents" counts from the ones already named, and Hermes's "the other thirty-two" counts every store but its own — and both move with the total without equalling it. (#3750)
deja blamesays when the line you typed is not a line.a.txt:99has saidthe file has 3 linessince #3726; six other specs said nothing at all and answered about the file as though no line had been asked for. Two shapes, both silent: digits that name no line —a.txt:0, and a number too large forstrconv.Atoi, which fell through to line 0 — and a suffix that is not digits at all, wherea.txt:abc,a.txt:-1,a.txt:+3anda.txt:2.5were taken as the whole filename and answeredno sessions mention a.txt:abc. Each now prints one line before the answer —deja: "abc" is not a line number — answering for the whole file— and the file-level answer follows as before. What gets searched is unchanged, because a colon is legal in a filename: the note fires only when the part before it looks like a filename and the part after holds no separator, sonotes:draftandC:\work\pool.gostay silent. (#3738)deja doctorsays when a store holds a transcript the index has never read. The audit that found this had to be written by hand: the live index on a real machine tracked 1,533 files and had never tracked ten — five senpi sessions written eight weeks earlier and five Copilot Chat transcripts from its second store — with every surface silent about it, because a store's session count of zero reads as "nothing written yet" rather than "five files never opened". None of the ten was unreadable, ignored or forgotten: each parses into a session, and one ordinary pass over a copy of that index adopted all ten in 35 seconds. What kept them out is the shape of the batch — a Copilot Chat transcript is not an appendable kind, and one new file of a kind with no offset parser makes the whole pass replacement-grade, which only a search, a recall ordeja indexperforms. The hooks never index, and that machine is hooks: 101 usage events one day and 50 the next, every one of them a hook, a tool line or a déjà vu moment. The row now reads(2 files, 1 indexed session, 1 transcript never read —deja index)and goes quiet after a pass, so it is a prompt rather than a complaint;--jsoncarriesnever_readfor the same reason it carries the files-against-sessions pair. Why a store can sit unread for weeks is #3747, still open — this is the surface that makes it visible rather than the fix. (#3747)- The one rule deja applies unasked — keep a background agent's own job tree out of recall — reaches a working directory a harness folded into one directory name. omp records a session under
-.claude-jobs-<id>-tmp-dsh-workand calls the projectdsh/work, so neither spelling contains what*/.claude/jobs/*matches: on a real store of 2,721 rows, 317 name a job tree and 12 were served, every one from that shape. What they are is the point — transcripts from a stand a background agent ran inside.claude/jobs, the class #2050 measured at 207 of the 300 most recent sessions, one of which outranked the session that had settled the same question. A directory segment beginning with a dash is now decoded before the literal match, which is the shape every one of these encoders produces because the path it encodes starts with a separator; a name that merely carries dashes (my-jobs-list.jsonl) does not begin with one and cannot be decoded into a match. Measured after the change on the same store: escapes 12 to 0, rows hidden 305 to 317, and nothing hidden whose path and project never say jobs. A rule someone writes themselves reaches the encoded form too, since that is where their work is as well. (#3746) - The index holds everything the stores hold, and that is now a measured claim rather than a slogan. Audited read-only against this machine's own stores: 3,027 sessions on disk across 21 of them, 2,726 in the index, and all 301 of the difference accounted for — 290 forgotten through
deja forget, 11 carrying two messages or fewer, none unexplained. The other direction is clean as well: 0 rows whose session no longer exists on disk, so nothing answers from a transcript that is gone. The audit is what turned up the ignore-rule gap above. - The rule the cross-agent claim rests on has a test naming it. Two agents working in one checkout do not agree on what the project is called: measured over a real store of 2,331 sessions, of 170 pairs of sessions from different harnesses that edited the same absolute file, 26 agreed on the project string and 144 did not — one name contained the other in 84 cases (
src/poolagainstpool), one was a path where the other was a bare name in 52. What carries the claim anyway is the rule that admits a session by the files it touched under this checkout, whatever it was recorded under, and over 515 handovers in that store the session before this one was never missing from the candidate pool: the three the block shows carried it in 496, and 13 of the 19 misses are subagent runs the digest drops on purpose. Nothing covered two harnesses disagreeing, which is 85% of the real pairs, so deleting the rule left the suite green; the test builds that disagreement from both stores and checks its own premise, so it cannot pass for the wrong reason if the harnesses ever agree. No behaviour change — the measurement found nothing to fix, which is the other half of the result. (#3744) - A publish on Windows stops losing to a reader that polls.
internal/atomicfilerenames a temp file into place and retried a flat 20 times, 5 ms apart, which is 100 ms — and a reader callingos.ReadFilein a loop is exactly what these files have: Go's ownos.Openasks forFILE_SHARE_READ|FILE_SHARE_WRITEand notFILE_SHARE_DELETE, so any ordinary Go reader refuses the rename for as long as its handle is open. A constant wait keeps step with a loop, so the writer woke inside the reader's next open on every attempt and spent the whole budget without landing: three of four concurrent writers were denied on the windows leg, which is wheremainwent red. The wait doubles from 2 ms to 40 ms over 30 attempts, about 1.3 seconds, and carries up to half of itself again at random — the jitter is the part that breaks the phase lock, and it is pinned by a test that fails when the wait becomes a constant again. Unix still lands on the first attempt and pays nothing. The file this protects is the warmup status: a failed publish there leaves the previous build's contents in place and a surface reads that no build is running while one is. (#3743) - The harness count is the registry's in every document that spells it, and two of the three ways it can go stale now fail a test. #3649 bumped the word by editing its first half and left the tail behind — "the thirty-three-six coding agents" shipped for three releases in the harnesses page, its three meta tags,
llms-install.mdand this repository's architecture document, and the test that reads those files could not see it, because it removes the wanted word before looking for stale ones andthirty-threeout ofthirty-three-sixleaves-six.docs/llms.txtwas wrong on its own terms and checked by nothing: the word test cannot take that file, since it legitimately says "and twenty-seven more" beside six named agents, and the digit test only reads.htmland.md— so it carried "each of the thirty-two agents" and "each of the thirty-one agents", two counts apart, in one file. The tail and that phrase are both pinned now, each verified by putting the old text back and watching the test fail. The GitHub description said "and 20 more coding agents", which is what search results showed before anyone reached a document at all. (#3741) - The documents that describe the MCP server describe the one it is. Six tools became one
dejatool with amodein #1298, and eight documents went on listing six: the architecture page put them under a heading that saystools/list, the Zed extension promised a table of six entries in the agent panel where a reader sees one, and the guidance deja writes into every harness — the skill file and the session-start block both — namedrecall_contextas a thing to call. The old names still answer a client that has them wired, which is why nothing broke and nothing complained. The modes in the check come from the tool's own schema rather than a second list, so a mode gained or lost reaches the pages: putting six tools back, and adding a seventh mode, each fail it. Two prose claims went with it — the footer on 103 pages said deja was "fully local" where four network paths exist, and the share card quoted a latency of ~1.5 ms that no run produced (the measured pair is 0.7–0.8 ms in process and 0.25 s end to end over 5.7 GB). - The Chinese pages carry the scoped claim too. Their footer said 全部在本地运行 — "runs entirely locally" — on all eleven of them, the same absolute the English footers dropped, and the getting-started page repeated it in its meta description, its og and twitter copies and its structured data. What pinned it was nothing: the privacy rule matched "nothing leaves / is sent / is uploaded" and never the shortest form of the claim. It now reads
fully local,entirely local,completely local,100% local, 全部在本地 and 完全本地 as the same promise, in the claim's own sentence, and putting any of those back into a footer fails it. - Home directories in test data belong to nobody. Fifteen paths carried the account of the machine they were written on, spelled
-Users-<account>-deja-vu— the form a harness makes of a project path — which is invisible to a search for/Users/<account>. The rule that keeps them out asks the passwd entry for the account it is running as, so no real name is written down in order to check for one, and a build account is skipped because/home/runner/work/...stands in an ignore-rule fixture on purpose. - The documentation says what 0.20.2 shipped. The prose-password rule is in the security model, the privacy page and both READMEs, with the gate that keeps it off ordinary sentences; line-level blame has a section on the auditing page with what it answers for and what it deliberately does not print;
deja howanddeja filessay that they answer from the project of the working directory, with--all-projectsfor the machine;deja index --quietis where someone keeping the index warm from a shell profile will read it. The architecture document's source table listed 24 of the 33 stores and its redaction paragraph was four rules behind. The contributing guide now states when the Windows leg runs and why a directory mode bit is not a permission there, which is the trap two pull requests hit this week.
Changelog
Features
- feat(blame): quote the turn an edit sits in, labelled for what it is (#3817)
- feat(ci): a changed docs page is announced to the crawlers that take a ping (#3829)
- feat(docs): a feed of what changed, published to the hub Google reads (#3833)
- feat(doctor): say when a store holds a transcript the index never read; fix(blame): say when the line given is not a line (#3748)
- feat(dsh,openclaw): the /deja reply carries deja's built and weekly notes (#3895)
- feat(hooks): a marketplace install gets the post-proof line with its built note, not a week later (#3908)
- feat(packaging): a directory listing deja links the page for what it lists (#3827)
- feat(roo): read both sides of a SEARCH/REPLACE edit (#3876)
- feat(search): a question that names one day prefers sessions from that day
- feat(stats): --year is your last twelve months in one screen (#3878)
- feat: auto-recall for gajae-code (#3859)
- feat: blame answers for the lines a session wrote, not only the ones it replaced (#3810)
- feat: decode Cursor CLI's second store; append new transcripts of any kind (#3821)
- feat: deja recap says what the week settled, quoted from the sessions (#3832)
- feat: deja secrets says which credentials your transcripts are carrying (#3822)
- feat: deja tests reports your build and test runs from the transcripts (#3831)
- feat: install ends with a prompt from your own history, already run (#575) (#3814)
- feat: read CodeWhale's store, and resume its sessions (#3804)
- feat: read opencode's per-session diff store (#3793)
- feat: read the edits Zed and Antigravity make (#3811)
- feat: read the written side Copilot Chat, Copilot CLI, Cursor and Kimi were dropping (#3818)
- feat: say how much of a relevance answer actually matched (#3816)
- feat: score a ranking another system produced (#3795)
- feat: sync ssh says which phase is running and where the time went (#3813)
- feat: the line answer as JSON, and an opt-in git note for it (#3812)
- feat: the stats card leads with what happened to your code (#3787)
Fixes
- fix(blame): say when a line spec is not a line, instead of ignoring it (#3738) (#3749) (@vaibhav8a)
- fix(day-zero): the command on the page lays down the corpus the page reports (#3848)
- fix(docs): the counts a reader acts on match what deja prints (#3837)
- fix(docs): the sitemap dates a page by when it changed, not by when it was added (#3825)
- fix(index): a manifest rewrite drops this process's cached copy (#3879)
- fix(install): a machine with no agent hears what deja looked for and what to do (#3835)
- fix(install): dsh and dsh-auto resolve, the names the dsh guide prints (#3869)
- fix(opencode): read a 2.0 store — session_v2, session_message, and the renamed tools (#3925)
- fix(policy): reach a working directory folded into one directory name, and name the rule the cross-agent claim rests on (#3745)
- fix(search): a store the size of a fresh install gets its relevance tail
- fix(search): the relevance tail reaches a store of a dozen sessions
- fix(search): two answers that claimed less than they held (#3819)
- fix(secrets): the report names a per-session file whatever its extension (#3874)
- fix(stats): a resumed conversation no longer counts as a question asked twice (#3906)
- fix(zed): the extension is deja-mcp-server and carries only the context server (#3913)
- fix: a diff file is not a clashing transcript with its own session (#3800)
- fix: freshness is measured from when deja read the stores (#3775)
- fix: the extension drift check fails instead of reporting (#3777)
- fix: the incremental pass says what it did in a sentence (#3769)
Performance
- perf: rerank by best message when the top of the ranking is crowded
Documentation
- docs(changelog): the four ranking changes of this batch
- docs(changelog): the recap command and today's corrections are in Unreleased (#3870)
- docs(compare): agentsview replaces the archived session viewer; funes and ctx quote day zero (#3867)
- docs(compare): every project the comparison names links to itself (#3856)
- docs(compare): title the page for what it compares, memory plugins (#3887)
- docs(day-zero): every tool the comparison scores links the repository it scored (#3842)
- docs(day-zero): measure agentsview on the same corpus (#3873)
- docs(day-zero): say the corpus is assistant chat, and connect its 19% to the benchmark's 85.3% (#3862)
- docs(day-zero): state the CASS build time instead of ranking it among three (#3885)
- docs(day-zero): the rows for deja, funes and ctx are the versions you get today (#3858)
- docs(guide): pages for the nine harnesses that had none (#3846)
- docs(guide): the three oldest per-agent pages link their registry entry (#3875)
- docs(llms): the map an assistant reads names the day-zero comparison (#3853)
- docs(privacy): the network list on the privacy page names deja embed too (#3868)
- docs(readme): deja secrets in the privacy section, the CLI table and the FAQ (#3915)
- docs(readme): list deja embed among the commands that use the network (#3922)
- docs(readme): point the images at raw URLs so they render off github.com too (#3838)
- docs(readme): say where to take a bug, a vulnerability and a privacy question (#3807)
- docs(site): the guide sidebar folds into groups and opens only the reader's own (#3889)
- docs: a guide to the credentials coding agents leave in their transcripts, and finding them with deja secrets (#3914)
- docs: a recorded demo for line-level blame (#3759)
- docs: add Cline history deletion guide (#3796) (@Voyagerroc-Lab)
- docs: add Japanese README (#3920) (@eltociear)
- docs: catch up on 0.20.2 and pin the counts that drifted (#3742)
- docs: comments and pages say what the rule is, not what it is worth to us (#3871)
- docs: commit the full-set benchmark run and pin every quote of hit@1 (#3757)
- docs: cut 0.21.0 (#3923)
- docs: give three buried answers their own headings (#3761)
- docs: how to build deja into another tool, and one switch to isolate it (#3809)
- docs: pin the Chinese resume sentence to the registry (#3808)
- docs: regenerate the harness matrix, and check it stays generated (#3782)
- docs: say what the code does — counts, the MCP surface, the privacy claims and the measured numbers (#3881)
- docs: state the blame rate per line, because that is the question (#3771)
- docs: the Chinese README and the plugin and npm pages link back to the repo like the English README (#3909)
- docs: the Chinese pages get an install that works there (#3792)
- docs: the demo caption and the hero line say what is actually behind them (#3866)
- docs: the demo card and the runner-up note quote the current run
- docs: the numbers in the repo docs match the runs and the code (#3863)
- docs: the page search lands on — all 33 stores, in Chinese, plus one more query answered (#3751)
- docs: the resume count comes from the registry now (#3780)
- docs: the site says 33 agents and 0.20.2, and asks for the star (#3806)
- docs: the two pages only the sitemap knew about are now linked from the site (#3843)
Other
- bench(longmemeval): a probe that says where a question's ranking weight went
- bench: record the top-five scores and ask whether a hit's own lines pick it (#3904)
- bench: the same score dump for LoCoMo (#3907)
- chore(deps): bump actions/setup-go from 5.1.0 to 7.0.0 (#3898) (@dependabot[bot])
- chore(deps): bump alpine from 3.20 to 3.24 (#3896) (@dependabot[bot])
- chore(npm): the packages carry the category words npm search matches on (#3891)
- ci(release): publish the OpenClaw plugin to ClawHub with each release (#3911)
- ci: build the Docker image and ask it for a handshake (#3903)
- ci: codeql-action 4.37.9 to 4.38.1, all four pins in one commit (#3902)
- ci: the race legs get a 20m test timeout (#3883)
- ci: the windows leg gets headroom (#3893)
- docs add Chinese guide for finding a session (#3778) (@theluckystrike)
- docs add the Chinese guide for recovering a deleted session (#3788) (@theluckystrike)
- registry: re-verify opencode against live client (2026-09-19) (#3789) (@Haklifesavr)
- test(docs): a documented invocation with a flag names a real command (#3877)
- test(docs): the Japanese README's harness count is checked against the registry (#3921)
- test(usage): the repeats window test stops failing once in a thousand runs (#3850)
Install
curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh
go install github.com/vshulcz/deja-vu/cmd/deja@v0.21.0
brew install deja-vu