返回 CodeWhale
MEMORY.md
根目录 / docs / MEMORY.md
1 # User Memory
2
3 User memory gives the model a small, persistent, local store of
4 preferences and conventions that should survive across sessions —
5 "I prefer pytest over unittest", "this codebase uses 4-space
6 indentation" — without repeating them in every conversation.
7
8 As of v0.9.4 the **native memory store** is the only memory system.
9 It is Markdown files indexed by SQLite FTS5, fully offline, scoped by
10 a hash of the repo's git origin. The legacy single-file
11 (`~/.deepseek/memory.md`) push/inject path and the planned Moraine MCP
12 backend were both removed: no Moraine server ever shipped in-repo,
13 and the native store already provides the same architecture (durable
14 Markdown source of truth plus a rebuildable search index).
15
16 Memory is **opt-in**. When disabled (the default), nothing is loaded,
17 nothing is intercepted, and the `remember` tool isn't surfaced to the
18 model.
19
20 ## Enabling memory
21
22 Either set the env var:
23
24 ```bash
25 export DEEPSEEK_MEMORY=on
26 ```
27
28 Accepted truthy values are `1`, `on`, `true`, `yes`, `y`, and
29 `enabled`.
30
31 …or add to `~/.codewhale/config.toml`:
32
33 ```toml
34 [memory]
35 enabled = true
36 ```
37
38 Restart the TUI after toggling. Disabling is the same in reverse.
39
40 ## Layout
41
42 The store lives under a `memory/` directory next to where the legacy
43 `memory_path` anchor points — by default `memory_path = "~/.codewhale/memory.md"`
44 re-roots to `~/.codewhale/memory/`:
45
46 ```text
47 ~/.codewhale/memory/
48 ├── global/MEMORY.md # user-scoped notes (follow you everywhere)
49 ├── workspace/<id>/MEMORY.md # repo-scoped notes (hash of git origin)
50 └── index.sqlite3 # rebuildable SQLite FTS5 cache
51 ```
52
53 The scope directory is `workspace` (singular) — `MemoryScope::directory`,
54 `crates/tui/src/native_memory.rs:31-36`. The index filename is
55 `index.sqlite3` (`native_memory.rs:175`).
56
57 Markdown is the durable source of truth; `index.sqlite3` is a disposable
58 full-text cache (`/memory native reindex` rebuilds it). A configured
59 `memory_path` is an **anchor only**: the filename is discarded and its
60 parent gains the `memory/global/MEMORY.md` tree. Do not set
61 `memory_path` to the native layout path itself — that double-nests the
62 tree. The shipped example keeps `~/.codewhale/memory.md` so the store
63 lands at `~/.codewhale/memory/global/MEMORY.md`.
64
65 ## What gets injected
66
67 When memory is enabled, the system prompt carries a bounded,
68 provenance-bearing block of memory entries (up to 32 entries /
69 12,000 chars, global plus current-workspace scope). The block is
70 wrapped to mark it as **untrusted user data**, not a second
71 instruction layer. For depth beyond the injected head, the model can
72 call the `memory_search` / `memory_get` tools against the FTS5 index.
73
74 The initial memory snapshot belongs to the session's frozen prompt prefix.
75 Changes discovered during the session are appended as history, as described
76 in [CACHE.md](CACHE.md); neither a native note update nor an external recall
77 may rewrite the system prompt or tool catalog on every turn.
78
79 ## Three ways to add to memory
80
81 ### 1. The `# ` composer prefix (#492)
82
83 Type a single line that starts with `#` (but not `##` or `#!`) in
84 the composer:
85
86 ```
87 # remember to use 4-space indentation in this repo
88 ```
89
90 The TUI intercepts the input and appends the note to the **global**
91 native store via the same `NativeMemoryStore::remember` path the
92 model's tool uses. **No turn fires** — your input is consumed, the
93 status line confirms the file it wrote to, and you can keep typing
94 your real question.
95
96 Multi-`#` prefixes deliberately fall through to normal turn
97 submission so you can paste Markdown headings without surprise.
98
99 ### 2. The `/memory` slash command
100
101 Inspect and maintain the native store:
102
103 `/memory` splits in two. The bare subcommands operate on the single file at
104 `config.memory_path()`; everything about the native store lives behind
105 `/memory native …` (`crates/tui/src/commands/groups/memory/memory.rs:236-268`).
106
107 | Subcommand | Effect |
108 |-----------------|-----------------------------------------------------------|
109 | `/memory` | Print the path and contents of the `memory_path` file |
110 | `/memory show` | Same as bare `/memory` |
111 | `/memory path` | Print the `memory_path` file location |
112 | `/memory clear` | Truncate that file |
113 | `/memory edit` | Print the `$EDITOR` invocation for it |
114 | `/memory help` | Show command-specific help |
115
116 Anything else returns `unknown subcommand`. The native store is reached through
117 the `native` prefix (`memory.rs:221`):
118
119 | Subcommand | Effect |
120 |-----------------------------------------|-------------------------------------|
121 | `/memory native status` | Store root, active source, index |
122 | `/memory native path` | Native store root |
123 | `/memory native remember [global\|workspace] <note>` | Append a note |
124 | `/memory native search <query>` | FTS5 search |
125 | `/memory native get <id>` | Read one entry |
126 | `/memory native reindex` | Rebuild the FTS5 index |
127 | `/memory native import` | Import the legacy single-file store |
128 | `/memory native export` | Dump entries |
129 | `/memory native delete [all\|global\|workspace]` | Delete entries |
130
131 There is no `/memory add` and no bare `/memory reindex`; use
132 `/memory native remember` and `/memory native reindex`.
133
134 ### 3. The `remember` tool (auto-capture, #489)
135
136 When memory is enabled the model gets a `remember` tool:
137
138 ```json
139 {
140 "name": "remember",
141 "input_schema": {
142 "type": "object",
143 "properties": {
144 "note": { "type": "string" },
145 "scope": { "type": "string", "enum": ["global", "workspace"] }
146 },
147 "required": ["note"]
148 }
149 }
150 ```
151
152 The model uses this when it notices a durable preference, convention,
153 or fact worth keeping across sessions. The tool is auto-approved
154 because writes are scoped to the user's own memory files — gating
155 them behind the standard write-approval flow would defeat the point
156 of automatic memory capture. Workspace scope requires a git
157 repository with an `origin` remote (the scope id is a hash of it).
158
159 ## What stays out of memory
160
161 Memory is for **durable** signal. Things that should NOT live there:
162
163 - **Secrets** — no API keys, tokens, passwords. The files are plain
164 text on disk and entries are injected into the system prompt.
165 - **Transient task state** — "I'm currently working on the parser"
166 changes every session; it doesn't belong in cross-session memory.
167 - **Conversation snippets** — quote-style notes belong in the notes
168 tool (`note`), not memory.
169 - **Long instructions** — anything over a few sentences should live
170 in `AGENTS.md` (project-level) or in a skill.
171
172 ## Privacy and scope
173
174 The native store lives on your machine and does not synchronize itself to
175 a cloud memory service. Recalled entries are sent to the selected model
176 provider as prompt context when memory is enabled. Keep secrets out of it.
177 Workspace-scoped memory is keyed by a hash of the repo's git
178 origin, so notes from one repo never leak into another repo's prompt.
179
180 ## External memory services
181
182 Persistent memory already works through the native store. First-class backend
183 selection currently accepts only `native` and `off`; there is no supported
184 `external`, `mem0`, or `memcode` backend setting.
185
186 A third-party memory service can expose tools through the existing
187 [MCP](MCP.md) or [plugin](PLUGINS.md) integration. Those are the service's own
188 tools: they do not replace `remember`, `memory_search`, `/memory native`, or
189 the `#` quick-add path. Review the plugin's permissions and the service's data
190 destination before enabling it. An unavailable external service must report
191 its failure rather than silently send notes to another backend.
192
193 A future first-class backend must cover capture, search, correction, deletion,
194 scope and error reporting across every memory entry point. It must also keep
195 volatile recall in append-only history under the cache contract above. That
196 complete migration is tracked in [#6050](https://github.com/Hmbown/CodeWhale/issues/6050);
197 0.9.13 does not claim that migration or a commercial memory integration.
198
199 ## Configuration reference
200
201 ```toml
202 # ~/.codewhale/config.toml
203 [memory]
204 enabled = true # default false; or set DEEPSEEK_MEMORY=on
205 # Optional explicit backend selection:
206 # backend = "native" # "native" or "off" (default: off)
207 ```
208
209 | Setting | Default | Override |
210 |-----------------------|-------------------------------|---------------------------------------|
211 | Memory enabled | `false` | `[memory] enabled = true` or `DEEPSEEK_MEMORY=on` |
212 | Backend | `off` | `[memory] backend = "native"` |
213 | Store root | `~/.codewhale/memory/` | derived from `memory_path` |
214
215 ## Related
216
217 - `docs/SUBAGENTS.md` — sub-agents inherit memory and can use the
218 `remember` tool too.
219 - `docs/CONFIGURATION.md` — full config reference.
220 - Issue [#489](https://github.com/Hmbown/CodeWhale/issues/489)
221 — phase-1 EPIC tracking the work.
222
222 lines MARKDOWN