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