返回 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:29-33`. The index filename is
55 `index.sqlite3` (`native_memory.rs:173`).
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 ## Three ways to add to memory
75
76 ### 1. The `# ` composer prefix (#492)
77
78 Type a single line that starts with `#` (but not `##` or `#!`) in
79 the composer:
80
81 ```
82 # remember to use 4-space indentation in this repo
83 ```
84
85 The TUI intercepts the input and appends the note to the **global**
86 native store via the same `NativeMemoryStore::remember` path the
87 model's tool uses. **No turn fires** — your input is consumed, the
88 status line confirms the file it wrote to, and you can keep typing
89 your real question.
90
91 Multi-`#` prefixes deliberately fall through to normal turn
92 submission so you can paste Markdown headings without surprise.
93
94 ### 2. The `/memory` slash command
95
96 Inspect and maintain the native store:
97
98 `/memory` splits in two. The bare subcommands operate on the single file at
99 `config.memory_path()`; everything about the native store lives behind
100 `/memory native …` (`crates/tui/src/commands/groups/memory/memory.rs:236-268`).
101
102 | Subcommand | Effect |
103 |-----------------|-----------------------------------------------------------|
104 | `/memory` | Print the path and contents of the `memory_path` file |
105 | `/memory show` | Same as bare `/memory` |
106 | `/memory path` | Print the `memory_path` file location |
107 | `/memory clear` | Truncate that file |
108 | `/memory edit` | Print the `$EDITOR` invocation for it |
109 | `/memory help` | Show command-specific help |
110
111 Anything else returns `unknown subcommand`. The native store is reached through
112 the `native` prefix (`memory.rs:221`):
113
114 | Subcommand | Effect |
115 |-----------------------------------------|-------------------------------------|
116 | `/memory native status` | Store root, active source, index |
117 | `/memory native path` | Native store root |
118 | `/memory native remember [global\|workspace] <note>` | Append a note |
119 | `/memory native search <query>` | FTS5 search |
120 | `/memory native get <id>` | Read one entry |
121 | `/memory native reindex` | Rebuild the FTS5 index |
122 | `/memory native import` | Import the legacy single-file store |
123 | `/memory native export` | Dump entries |
124 | `/memory native delete [all\|global\|workspace]` | Delete entries |
125
126 There is no `/memory add` and no bare `/memory reindex`; use
127 `/memory native remember` and `/memory native reindex`.
128
129 ### 3. The `remember` tool (auto-capture, #489)
130
131 When memory is enabled the model gets a `remember` tool:
132
133 ```json
134 {
135 "name": "remember",
136 "input_schema": {
137 "type": "object",
138 "properties": {
139 "note": { "type": "string" },
140 "scope": { "type": "string", "enum": ["global", "workspace"] }
141 },
142 "required": ["note"]
143 }
144 }
145 ```
146
147 The model uses this when it notices a durable preference, convention,
148 or fact worth keeping across sessions. The tool is auto-approved
149 because writes are scoped to the user's own memory files — gating
150 them behind the standard write-approval flow would defeat the point
151 of automatic memory capture. Workspace scope requires a git
152 repository with an `origin` remote (the scope id is a hash of it).
153
154 ## What stays out of memory
155
156 Memory is for **durable** signal. Things that should NOT live there:
157
158 - **Secrets** — no API keys, tokens, passwords. The files are plain
159 text on disk and entries are injected into the system prompt.
160 - **Transient task state** — "I'm currently working on the parser"
161 changes every session; it doesn't belong in cross-session memory.
162 - **Conversation snippets** — quote-style notes belong in the notes
163 tool (`note`), not memory.
164 - **Long instructions** — anything over a few sentences should live
165 in `AGENTS.md` (project-level) or in a skill.
166
167 ## Privacy and scope
168
169 The store lives entirely on your machine. It is never uploaded to any
170 cloud service — the TUI only ever includes entries inline in the
171 system prompt that the LLM provider receives, and only when memory is
172 enabled. Workspace-scoped memory is keyed by a hash of the repo's git
173 origin, so notes from one repo never leak into another repo's prompt.
174
175 ## Configuration reference
176
177 ```toml
178 # ~/.codewhale/config.toml
179 [memory]
180 enabled = true # default false; or set DEEPSEEK_MEMORY=on
181 # Optional explicit backend selection:
182 # backend = "native" # "native" or "off" (default: off)
183 ```
184
185 | Setting | Default | Override |
186 |-----------------------|-------------------------------|---------------------------------------|
187 | Memory enabled | `false` | `[memory] enabled = true` or `DEEPSEEK_MEMORY=on` |
188 | Backend | `off` | `[memory] backend = "native"` |
189 | Store root | `~/.codewhale/memory/` | derived from `memory_path` |
190
191 ## Related
192
193 - `docs/SUBAGENTS.md` — sub-agents inherit memory and can use the
194 `remember` tool too.
195 - `docs/CONFIGURATION.md` — full config reference.
196 - Issue [#489](https://github.com/Hmbown/CodeWhale/issues/489)
197 — phase-1 EPIC tracking the work.
198
198 lines MARKDOWN