coding-agents
vectorize-io/hindsightHindsight:会学习的 Agent 长期记忆系统,自动召回/保存、知识页、深度反思与按仓库隔离的记忆银行。
主动联想记忆 + Astra 式上下文管理:自动唤回(固定边界注入,前缀缓存友好)/自动沉淀/技能固化/交接账本与 PLAN 白板跨窗口续命/水位感知(窗口自动适配当前模型)。本地 Markdown 存储,模型无关,零依赖;词法 0GB 兜底,可选语义档。
dsh-auto-memory — *She remembers, unbidden.*
EN Now, across windows, too. Context that survives windows, sessions, and tools
中文 该想起的,自己浮现。跨窗口 · 跨会话 · 跨工具 —— Ambient Recall · 「潜藏追忆,如影随形」
🌐 Landing page · 📄 Technical reports · 🧭 Pilot Credits Program
Promo gallery, frame by frame (expand and flip through)
pnpm add @a9i5k4/dsh-auto-memory@latest
📖 User guide · 🎨 Skin guide · 👥 Teamwork guide · Changelog · Contributors & Sponsors · QQ group
New UI 新款 · built by @Minervaowl7
Dark ⇄ Light slider preview · auto-playing loop (GitHub READMEs can't run a real drag widget) — in the app, switch Dark / Light / Follow system from the panel header.
A reference-style memory workbench: nine-page navigation, list & detail views, four settings groups, focus view, dark mode and narrow-screen layouts. Switch to it from the memory panel header button — the classic skin is untouched and always one click away. All 24 real-host screenshots live in the Skin guide.
[!NOTE]
🧭 Getting ready for the official long-term memory
Adaptation and pre-research for DeepSeek Harness's official long-term memory system are underway — when it ships, this plugin will offer semantic recall and cross-window continuation for official memories from day one. Everything here is a toggle: with ample stability and flexibility built in, the plugin will auto-adapt to and flexibly complement the official memory stack. Your memory stays seamless — no migration needed.
Everyone who does real work with AI knows the moment: halfway through, the context window fills, and she "forgets". Not for lack of intelligence — her thinking was compressed into a summary, like burning a whole book and keeping one line of book report. Why that fix failed, why that path dead-ended — all in the fire.
dsh-auto-memory never believed it had to be this way. She keeps memory outside the window: what should resurface, resurfaces unbidden; and everything she recalls has provenance — checkable, editable, deletable.
Now we push this route to its last missing piece — when the context fills, she no longer compresses herself. She closes a notebook filled with margin notes and opens a new page. The notebook stays within reach.
Compression distorts, closed windows reset, tool switches zero out — starting from here, none of that holds.
· Proactive recall, zero instructions · Memory is never fetched by the model — the host watches context and recalls automatically, injected at a fixed boundary, prefix-cache friendly Three-layer memory engine · User rules → project notes → daily logs; injected + on-demand recall Memory writes itself · A subagent quietly evaluates every turn and files topic-grouped entries — you never "remember to log" Every activation is auditable · Each recall decision carries a full evidence chain, gradeable in the Recall review tab; skills crystallize from cross-session evidence Proactive reminders · The AI spots deadlines and promises in conversation, files them into the calendar and reminds you later Everything is a switch · Welcome tour + settings page, every feature individually toggleable (incl. unattended mode) External memory inheritance · Memories from WorkBuddy / CodeBuddy / Claude Code / Codex are scanned, importable, per-source managed Production-grade hygiene · Write gate (mojibake/stutter/JSON-injection blocking) + dirty-token scanner + credentials never enter prompts Astra-style context management · A filling context no longer collapses into one summary — four-part handoff notes carry work across windows, full history stays searchable, the agent retrieves on demand (on by default, threshold 0.75) No cross-talk between workspaces · Open several workspaces or sessions at once and each keeps its own recall decisions and index cache. Clicking into one never disturbs the one that's running Model-agnostic · No vendor lock, no tier lock: any model on DSH works out of the box — lexical 0GB floor, built-in ~130MB semantic tier, advanced 563MB Portable memory · Everything lives on your own disk; memories scan in from other AI tools, every entry has an evidence chain — auditable, deletable. Memory belongs to you, not to any vendor
Four features in this plugin were raised one by one, by hand; everything else — calendar, search, the mind map, unattended mode, memory hygiene — grows around them.
The earliest version of this plugin learned two small things: after every conversation, it wrote down what was worth keeping, unprompted; and when you returned from time away, or in the morning, afternoon, and late-night hours, it greeted you in a fitting tone. Simple — but these two acts set her character: memory is not a database, a greeting is not a notification chime; it is what a colleague who remembers you says when you walk back in. Everything else grew on that character. We call this plugin "she" throughout — not marketing polish, but because from the very first feature, she was doing the things a person does.
Humans use memory two ways: deliberately retracing what was done before — and, far more often, having the right memory surface on its own in the middle of doing. The last major release gave her the second kind. We put a Transformers model next to the memory stores so that, mid-conversation, she judges two things: whether anything is worth recalling right now, and which memory it should be — judging from the very material of the dialogue: what you're thinking, what you said, what she answered. The relevant memory thus walks into place, through a fixed boundary into the next turn, before the model even opens its mouth. It never depends on the model "remembering to look" — forget once, and the memory might as well not exist. She remembers to think for you.
Once a person learns to ride, they never replay the tutorial — muscle memory takes over, and the skill transfers to the next road on its own. She grows that kind of memory too: after watching your corrections a few times, or doing the same kind of thing again and again, a workflow crystallizes into a skill; next time something similar shows up, the checklist attaches itself — no one reminding. What was learned deliberately becomes something done casually — her procedural memory, the part you can review, pin, and watch grow in the Memory Hub tab.
When the context fills, she no longer burns the whole book for a one-line summary; she writes a four-part handoff note — state, goals, dead ends and why, progress and next step — closes this window, and opens the next. The full history stays archived and searchable; details can always be looked back up. The newest of the four, and the last piece of a complete memory — see How she hands off.
In September 2026, GPT-6 Astra shipped Context Management as an experimental flagship feature: notes kept across context windows, earlier history searchable, handoff preferred over compression as the window fills.
Seeing the announcement, we were quietly glad — like someone walking a night road alone who sees a light come on in the distance. Putting memory outside the window: structured notes, searchable archives, handoff over compression — it turns out we are not the only traveler on this road. That a flagship is willing to press the experimental button for it says this idea deserves to be taken seriously by more people.
So we built it as an open plugin: no experimental gate, no subscription tier — install it in DSH, and every model on your machine gets its own.
· GPT-6 Astra / Codex experimental feature · dsh-auto-memory Availability · Single-vendor flagship, experimental · Open plugin, any DSH model, install and go Notes · Keep notes across windows · Four-part handoff ledger, directly readable and editable by you Archive · Earlier windows searchable · Local full archive + lexical/semantic dual-channel retrieval Retrieval · history/_context tools · memory_search / memory_note gated-agent tools Trigger · Token budget + handoff · Water-level awareness + pre-completion interception Ownership · Vendor side · All on the user's disk, governance-style writes, auditable Tiers · Bound to subscription plans · 0GB lexical → 130MB built-in semantic → 563MB Python advanced
One route, two arrivals: it ships with a flagship; ours walks into your machine as a plugin.
*Handoff is on by default — threshold 0.75, just below the host's 0.80 auto-compaction line (see How she hands off).*
Monday, you hand her a research task and shut the laptop halfway through.
Wednesday, you're on a different machine and have switched the default model while you were at it. What she picks up is not "sorry, I don't remember" — it's last week's progress, three dead ends already tried, and the next step. The handoff note is there, the raw record is searchable, and the memory travels with you.
Friday, you ask casually: "Why do you remember this?" She shows you: which message, which tool output, which late-night reflection it came from. You can have her hold onto it tighter — or let it go.
She remembers, unbidden. And if you want her to forget — that's one sentence too.
Handoff-related scenes are on by default.
Memory comes in four layers, each minding its own shelf:
Layer · Location · Content User-level memory · ~/.dsh/memory/MEMORY.md · Cross-project rules & preferences Project notes · ~/.dsh/memory/workspaces/{workspace}/MEMORY.md · Conventions & decisions Daily logs · ~/.dsh/memory/workspaces/{workspace}/YYYY-MM-DD.md · Append-only work log Daily reflections · …/reflections/YYYY-MM-DD.md · Structured review (results / lessons / next)
Static discipline lives in the system prompt — byte-stable, keeps the prefix cache hot, never re-encodes history; dynamic memory rides a runtime snapshot — only the last day of logs plus a reflection digest are injected, everything else fetched on demand via memory_read / memory_recall. Credential/secret sections are always filtered out of prompts.
Memory writes itself. After every turn a small subagent quietly makes one judgment — what's worth keeping: long-term-valuable topics are grouped into today's log (## Topic (HH:MM) + bullets), durable decisions are promoted to project notes, cross-project rules to user-level memory, small talk skipped. Failures don't panic — they queue and retry every 5 minutes, with a 15-second heartbeat file proving the loop is alive. Daily writes have a budget; over budget, the AI merges and dedupes before writing — she remembers restraint, and she remembers not to lose things.
Then, periodically, she looks back: memory_consolidate reads recent logs and distills what deserves long-term promotion into project notes — auto-consolidation handles "log the flow each turn"; this handles "after a while, what's worth keeping".
Never depends on the model "remembering to look". Existing memory solutions either rely on the model calling a retrieval tool, or on you pasting context by hand — skip it once, and the memory might as well not exist. This is host-side associative middleware: while the conversation runs, she watches context and runtime events continuously, and the relevant memories are retrieved, decided, and injected into the next turn before the model opens its mouth. Sent requests can't be rewritten, so injection runs at a fixed boundary — the prefix cache never goes cold, and tokens never pay twice for a memory. Her judging material is the dialogue itself: what you're thinking, what you said, what she answered; whether to recall, and what to recall, is decided live by the semantic model — not "look it up when I remember", but remembering while doing.
Powers are separated too: what to recall belongs to the semantic decision layer; whether and when belongs to the identity/authorization/timing governance layer — every delivery carries an evidence chain. Every page she hands over has also passed inspection: injected content is neutralized for template variables at every exit — a plain {{baseUrl}} in a log can no longer brick an entire turn.
Ask, and she answers: memory_recall returns a layered summary list first (each memory as a ~90-character digest with id, score and match reason), fused across lexical + semantic + time arms — ask for "last week's release trouble" and the memories from that window surface first; expand any id for the full text. Replies are conversational with sources cited. memory_recall is cross-workspace by nature — other projects' logs, notes, and conclusions are one sentence away.
The panel's Workspace tab draws all of this as a mind map: workspaces at the center, memory topics as branches, dashed lines for cross-workspace shares; draggable, zoomable, click a card for details. Your memory has a shape for the first time.
This borrows OpenViking's tiering idea, recalibrated against real corpus measurements in this repo. The rule is descend tier by tier — never all at once:
Tier · Content · Budget · When it appears Tier-0 · Catalog (index layer) · One line per entry = title · conclusion · layer · status · date · ≤ B0 = 800 tokens (resident, ~30 entries) · The norm — only this tier is injected by default Tier-1 · Digests (candidate layer) · ≤ L1 = 140 chars each, top K = 8 · 8 × 140 = 1120 chars · Only when the catalog under-hits Tier-2 · Source chunks (evidence layer) · chunkId = hash(memoryId, digest, index) · ≤ B2 = 2400 chars / call · Only when evidence is needed
Flow: Tier-0 out first → narrow → descend to Tier-1 only if short → fetch Tier-2 only for evidence. Single-turn injection still respects injectBudgetChars (default 8000 chars).
Full vs slim (the 3.2.6 narrowing): the full snapshot goes out at most once per turn — on the first turn of a live human request, and in unattended runs only after fullEverySlims (default 3) slim rounds, i.e. roughly once every 3×3 ≈ 9 steps. A slim refresh carries only the status frame (dates, water level, pending reminders); it never carries the content body. So a turn's injection can be a few hundred chars instead of the full budget.
Why it's built this way (measured, not guessed):
L0 → L1(2k) → L2 middle step can be dropped — jumping from a 140-char digest straight to a ≤2400 source chunk is an acceptable span.project layer's 77 chunks consumed the entire 800-token budget, leaving whiteboard / user / log with zero entries — "tiered" degenerating into single-tier. Hence per-layer quotas (e.g. project ≤ 60% · B0) — a hard rule, not a suggestion.expand output against corpus length — mem_d55f8e8e reported 1499 chars ↔ corpus 1499 ✅, mem_5a7f779a reported 1403 ↔ 1403 ✅.This line started from a sentence: "dsh graph is exactly the Karpathy module I wanted." The problem it solves isn't "is retrieval accurate" — it's the shape of memory. Traditional RAG rediscovers from zero on every query, accumulating nothing; the Karpathy-style answer is to let a model incrementally maintain a persistent wiki (entity pages, concept pages, cross-references, contradiction flags) navigated by index.md + log.md.
What this repo shipped isn't "yet another wiki" — it found an interface that needs zero new machinery: **pages *are* the corpus (S10.1)**.
A whiteboard card carries an anchor, and the anchor is what the Tier-0 catalog slices by. The slicing order is 「anchor → heading → top-level item → whole-file fallback」, so an anchored card becomes its own entry in the guidance layer injected every turn — no new pipeline required.
### Card titleHow the anchor is computed (content-addressed, recomputable): mem_ + first 32 hex chars of sha256(workspaceKey + '\0' + page relative path + '\0' + card title). The whiteboard text is one of five sources (user / project / log / whiteboard / reflection) feeding the Tier-0 catalog, and it holds a reserved floor quota (whiteboard and user each reserve floorRatio·maxTokens) — so the project layer can't swallow the whole 800-token budget and lock the whiteboard out.
⚠️ Implementation boundary (stated plainly, not oversold): the anchor→corpus path is currently wired only for injection (Tier-0 catalog, viaadd('whiteboard', …)inindex.js).
Thememory_recallretrieval corpus still contains only four source classes — daily logs / reflections / project notes / user-level memory — the whiteboard is not yet wired in (see the fourpushL0call sites and the foursemSourcesentries inlib/index.js).
In other words: whiteboard content is injected every turn, but memory_recall still cannot search it. This is a contract-layer item defined but not yet implemented, and it is outside the scope of this change.The payoff cuts both ways: