@vib795/agent-memory 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install.ps1 ADDED
@@ -0,0 +1,54 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Installs agent-memory and all three skills from a checkout.
4
+
5
+ .DESCRIPTION
6
+ `npm install -g .` does this on its own via the postinstall hook. This script
7
+ exists for two cases: installing straight from a clone without npm, and finishing
8
+ the job when a managed npm config sets ignore-scripts=true and silently skips it.
9
+
10
+ The linking itself lives in src\setup.js, not here. That is deliberate: a PowerShell
11
+ reimplementation could only be tested on Windows, and the machine this was written
12
+ on is not Windows. One implementation, three entry points, no drift.
13
+
14
+ Skills are linked into both agent directories:
15
+ %USERPROFILE%\.agents\skills\<name> -> read by GitHub Copilot in every window
16
+ %USERPROFILE%\.claude\skills\<name> -> read by Claude Code
17
+
18
+ Directory junctions are used, which need neither admin rights nor Developer Mode.
19
+ They fail on a network-backed profile (FSLogix, roaming), and setup falls back to
20
+ copying and says so.
21
+
22
+ .EXAMPLE
23
+ powershell -ExecutionPolicy Bypass -File .\install.ps1
24
+ #>
25
+
26
+ $ErrorActionPreference = 'Stop'
27
+
28
+ $source = $PSScriptRoot
29
+
30
+ $node = Get-Command node -ErrorAction SilentlyContinue
31
+ if (-not $node) {
32
+ Write-Error "node not found on PATH. agent-memory needs Node >= 22.5."
33
+ exit 1
34
+ }
35
+
36
+ & node (Join-Path $source 'src\cli.js') setup
37
+
38
+ Write-Host ""
39
+ Write-Host "Linking the CLI" -ForegroundColor Cyan
40
+ & npm install -g $source 2>&1 | Out-Null
41
+ if ($LASTEXITCODE -eq 0) {
42
+ Write-Host " [npm] agent-memory installed globally" -ForegroundColor Green
43
+ } else {
44
+ # A global install failing on a managed desktop is common and not worth aborting
45
+ # on. The skills are already linked; this one step can be finished by hand.
46
+ Write-Host " [npm] global install failed. Run this yourself:" -ForegroundColor Yellow
47
+ Write-Host " npm install -g `"$source`"" -ForegroundColor Yellow
48
+ }
49
+
50
+ Write-Host ""
51
+ & node (Join-Path $source 'src\cli.js') doctor
52
+
53
+ Write-Host ""
54
+ Write-Host "Installed. Restart VS Code, then try /recall, /remember, or /handoff." -ForegroundColor Cyan
package/install.sh ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env bash
2
+ # Installs agent-memory and all three skills from a checkout, on macOS/Linux.
3
+ #
4
+ # `npm install -g .` does this on its own via the postinstall hook. This script
5
+ # exists for two cases: installing straight from a clone without npm, and finishing
6
+ # the job when a managed npm config sets ignore-scripts=true and silently skips it.
7
+ #
8
+ # The linking itself lives in src/setup.js, not here. One implementation, three entry
9
+ # points, so this script and its PowerShell twin cannot drift from each other.
10
+ set -euo pipefail
11
+
12
+ source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+
14
+ if ! command -v node >/dev/null 2>&1; then
15
+ echo "node not found on PATH. agent-memory needs Node >= 22.5." >&2
16
+ exit 1
17
+ fi
18
+
19
+ node "$source_dir/src/cli.js" setup
20
+
21
+ echo
22
+ echo "Linking the CLI"
23
+ if npm install -g "$source_dir" >/dev/null 2>&1; then
24
+ echo " [npm] agent-memory installed globally"
25
+ else
26
+ # A global install needing sudo is common and is not worth aborting on. The skills
27
+ # are already linked, and the user can finish this one step by hand.
28
+ echo " [npm] global install failed (permissions?). Run this yourself:"
29
+ echo " npm install -g \"$source_dir\""
30
+ fi
31
+
32
+ echo
33
+ node "$source_dir/src/cli.js" doctor || true
34
+
35
+ echo
36
+ echo "Installed. Restart VS Code, then try /recall, /remember, or /handoff."
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@vib795/agent-memory",
3
+ "version": "0.1.0",
4
+ "description": "Durable cross-repo knowledge graph for GitHub Copilot and Claude Code. Markdown source of truth, disposable SQLite index, zero runtime dependencies.",
5
+ "keywords": [
6
+ "github-copilot",
7
+ "claude-code",
8
+ "agent-skills",
9
+ "memory",
10
+ "knowledge-graph",
11
+ "sqlite",
12
+ "zero-dependencies"
13
+ ],
14
+ "homepage": "https://github.com/vib795/agent-memory#readme",
15
+ "bugs": "https://github.com/vib795/agent-memory/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/vib795/agent-memory.git"
19
+ },
20
+ "author": "Utkarsh Singh (https://github.com/vib795)",
21
+ "type": "module",
22
+ "bin": {
23
+ "agent-memory": "src/cli.js"
24
+ },
25
+ "engines": {
26
+ "node": ">=22.5.0"
27
+ },
28
+ "scripts": {
29
+ "test": "node --test",
30
+ "postinstall": "node scripts/postinstall.js",
31
+ "setup": "node src/cli.js setup"
32
+ },
33
+ "files": [
34
+ "src/",
35
+ "scripts/",
36
+ "skills/",
37
+ "install.sh",
38
+ "install.ps1",
39
+ "README.md",
40
+ "HOWTO.md",
41
+ "LICENSE"
42
+ ],
43
+ "license": "MIT",
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Link the skills when the package is installed.
4
+ *
5
+ * This must never fail an install. A missing symlink is a nuisance; an `npm install`
6
+ * that exits non-zero on a managed desktop is the kind of thing that gets a tool
7
+ * banned. Every failure here is reported and swallowed, and `agent-memory setup`
8
+ * remains available to finish the job by hand.
9
+ *
10
+ * Note that managed npm configurations often set `ignore-scripts=true`, in which case
11
+ * this file never runs and nothing warns you. That is precisely why the same work is
12
+ * exposed as a command, and why `doctor` names it.
13
+ */
14
+
15
+ const say = (msg) => process.stdout.write(`${msg}\n`);
16
+
17
+ if (process.env.AGENT_MEMORY_SKIP_POSTINSTALL) {
18
+ process.exit(0);
19
+ }
20
+
21
+ try {
22
+ const [maj, min] = process.versions.node.split('.').map((s) => Number.parseInt(s, 10));
23
+ if (maj < 22 || (maj === 22 && min < 5)) {
24
+ say(`agent-memory: Node ${process.versions.node} is too old; needs >= 22.5 for node:sqlite.`);
25
+ say('agent-memory: skills not linked. Upgrade Node, then run: agent-memory setup');
26
+ process.exit(0);
27
+ }
28
+
29
+ const { setup } = await import('../src/setup.js');
30
+ const { compact } = await import('../src/compact.js');
31
+ const r = setup({ compactFn: () => compact() });
32
+
33
+ const links = r.installed.filter((s) => s.mode === 'link').length;
34
+ const copies = r.copies.length;
35
+ say(`agent-memory: linked ${links} skill${links === 1 ? '' : 's'}${copies ? `, copied ${copies}` : ''}.`);
36
+ say(`agent-memory: ${r.notes} notes indexed. Restart VS Code, then try /recall.`);
37
+ if (copies) {
38
+ say('agent-memory: copies happen on network-backed profiles; re-run `agent-memory setup` after upgrades.');
39
+ }
40
+ } catch (err) {
41
+ say(`agent-memory: automatic setup did not complete (${err.message}).`);
42
+ say('agent-memory: run `agent-memory setup` to finish. Nothing else is affected.');
43
+ }
44
+
45
+ process.exit(0);
@@ -0,0 +1,344 @@
1
+ ---
2
+ name: handoff
3
+ version: 0.1.0
4
+ description: Capture the working state of the current conversation into a portable handoff file, so an agent in a different VS Code window or a different repository can continue the work without the user re-explaining it. Use when the user says handoff, hand this off, save context, wrap this up, or continue this elsewhere.
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ - Write
9
+ - Glob
10
+ triggers:
11
+ - handoff
12
+ - hand this off
13
+ - save context for another window
14
+ - continue this in another repo
15
+ ---
16
+
17
+ # handoff
18
+
19
+ Write one file that lets a different agent, in a different window, on a different
20
+ repo, pick up this thread cold.
21
+
22
+ You are not summarizing the conversation. You are reconstructing **working state**.
23
+ A transcript summary is a failure mode: it reads fine and still leaves the next
24
+ agent asking the questions the user is trying to avoid answering twice.
25
+
26
+ Do the whole job in **one pass**. Gather facts in a single terminal call, then
27
+ write. Do not loop, do not re-read source files, do not interrogate the user.
28
+ Every extra request costs the user credits, which is the reason this skill exists.
29
+
30
+ ---
31
+
32
+ ## Step 0 — Resolve the store path
33
+
34
+ | Platform | Store |
35
+ |---|---|
36
+ | Windows | `$env:USERPROFILE\.agents\handoffs` |
37
+ | macOS / Linux | `$HOME/.agents/handoffs` |
38
+
39
+ The store lives outside every repository on purpose. That is what makes a handoff
40
+ readable from a window opened on a different project.
41
+
42
+ ---
43
+
44
+ ## Step 1 — Gather deterministic facts (ONE terminal call)
45
+
46
+ Run one command that creates the store, reads the index, and collects git state.
47
+ Everything the deterministic layer contributes comes from this single call.
48
+
49
+ **PowerShell (Windows / AVD):**
50
+
51
+ ```powershell
52
+ $store = Join-Path $env:USERPROFILE '.agents\handoffs'
53
+ New-Item -ItemType Directory -Force -Path $store | Out-Null
54
+ Write-Output "STORE=$store"
55
+ Write-Output "--- INDEX ---"
56
+ if (Test-Path (Join-Path $store 'index.md')) { Get-Content (Join-Path $store 'index.md') } else { Write-Output "(no index yet)" }
57
+ Write-Output "--- GIT ---"
58
+ Write-Output "ROOT=$(git rev-parse --show-toplevel 2>$null)"
59
+ Write-Output "BRANCH=$(git branch --show-current 2>$null)"
60
+ Write-Output "HEAD=$(git rev-parse --short HEAD 2>$null)"
61
+ Write-Output "--- STATUS ---"
62
+ git status --porcelain 2>$null
63
+ Write-Output "UTC=$([DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ssZ'))"
64
+ ```
65
+
66
+ **bash (macOS / Linux):**
67
+
68
+ ```bash
69
+ store="$HOME/.agents/handoffs"; mkdir -p "$store"
70
+ echo "STORE=$store"
71
+ echo "--- INDEX ---"; [ -f "$store/index.md" ] && cat "$store/index.md" || echo "(no index yet)"
72
+ echo "--- GIT ---"
73
+ echo "ROOT=$(git rev-parse --show-toplevel 2>/dev/null)"
74
+ echo "BRANCH=$(git branch --show-current 2>/dev/null)"
75
+ echo "HEAD=$(git rev-parse --short HEAD 2>/dev/null)"
76
+ echo "--- STATUS ---"; git status --porcelain 2>/dev/null
77
+ echo "UTC=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
78
+ ```
79
+
80
+ If the directory is not a git repository, `ROOT`/`BRANCH`/`HEAD` come back empty.
81
+ That is not an error. Record the working directory path and omit the git fields.
82
+
83
+ ---
84
+
85
+ ## Step 2 — Identify the thread
86
+
87
+ Read the `--- INDEX ---` output and decide, **by judgment**, whether this
88
+ conversation continues an existing thread or starts a new one. Do not string-match
89
+ titles; a title drifts as work progresses and the thread is still the same thread.
90
+
91
+ - Same goal as an existing row, even under a different name → reuse that `id`.
92
+ - Same repo but a genuinely different goal → new `id`.
93
+ - Nothing close → new `id`.
94
+
95
+ New ids are kebab-case, 3 to 6 words, naming the **goal**, not the topic:
96
+ `migrate-orders-to-result-type`, not `orders-work`.
97
+
98
+ State your choice in the final output: "Updating thread `<id>`" or
99
+ "Creating thread `<id>`". If you guessed wrong the user corrects it in one line,
100
+ which is cheaper than asking.
101
+
102
+ ---
103
+
104
+ ## Step 3 — Compose the handoff
105
+
106
+ Use this exact structure.
107
+
108
+ ```markdown
109
+ ---
110
+ id: <kebab-slug>
111
+ title: <one line, states the goal not the topic>
112
+ status: active | blocked | done
113
+ created: <ISO 8601 UTC>
114
+ updated: <ISO 8601 UTC>
115
+ repos:
116
+ - name: <repo name>
117
+ path: <absolute path>
118
+ branch: <branch>
119
+ head: <short sha>
120
+ agent: copilot | claude-code
121
+ ---
122
+
123
+ ## Orientation
124
+
125
+ 3 to 5 sentences. What this thread is trying to accomplish and where it stands.
126
+ Written for a reader with zero prior context.
127
+
128
+ ## Decisions
129
+
130
+ | # | Decision | Why | Alternatives rejected |
131
+ |---|----------|-----|----------------------|
132
+
133
+ ## Constraints
134
+
135
+ Things not discoverable by reading the code: environment restrictions,
136
+ unavailable tooling, plan limits, deadlines, taste calls already settled.
137
+
138
+ ## Rejected approaches
139
+
140
+ What was tried and why it failed. Mandatory. This is the section that stops the
141
+ next agent re-deriving known dead ends on the user's credits.
142
+
143
+ ## Current task state
144
+
145
+ **Next action:** <one imperative sentence>
146
+ **Blocked on:** <specific blocker, or "nothing">
147
+
148
+ ### Uncommitted work
149
+
150
+ | File | State | What changed |
151
+ |------|-------|--------------|
152
+
153
+ ### Anchors
154
+
155
+ | Path | Why it matters |
156
+ |------|----------------|
157
+
158
+ ## Open questions
159
+
160
+ Numbered. Only questions the user can answer.
161
+ ```
162
+
163
+ `State` in Uncommitted work comes from `git status --porcelain`: `modified`,
164
+ `added`, `deleted`, `untracked`, `renamed`.
165
+
166
+ ### Quality rules
167
+
168
+ These separate a useful handoff from a readable paragraph that still leaves questions.
169
+
170
+ 1. Write for a reader with zero context. No pronoun without a stated antecedent.
171
+ 2. Every decision carries its **why**. Rationale is what never survives
172
+ re-explanation and is the whole reason a handoff beats a transcript.
173
+ 3. Never quote or paraphrase the transcript. Record conclusions, not the path to them.
174
+ 4. Anchor claims to a file path or a decision number. "We refactored the service
175
+ layer" is a failure. "`src/services/order.ts:42` now returns `Result<T>` instead
176
+ of throwing" is not.
177
+ 5. Record only what the conversation actually established. Prefix anything you
178
+ inferred with `inferred:` so the next agent knows to verify it.
179
+ 6. Never inline a diff or a patch. List changed files with one line each.
180
+ 7. Soft target 150 lines. On overflow, move detail into `<id>.detail.md` and
181
+ reference it. Never drop Decisions or Rejected approaches to hit the target.
182
+ 8. Empty sections say `None.` They are never deleted. A missing section reads as
183
+ an oversight; an explicit `None.` reads as a fact.
184
+
185
+ ---
186
+
187
+ ## Step 4 — Redact before writing
188
+
189
+ Scan the drafted body and replace any of these with `<redacted:kind>`:
190
+
191
+ API keys, access tokens, bearer tokens, passwords, connection strings, private
192
+ keys, session cookies, internal hostnames or IPs, and personal email addresses
193
+ that are not the user's own git identity.
194
+
195
+ The store is plaintext on a corporate machine. Never write the raw value, not even
196
+ once, not even to a temp file.
197
+
198
+ ---
199
+
200
+ ## Step 5 — Write the files
201
+
202
+ Prefer your file-write tool targeting the absolute store path. If it refuses to
203
+ write outside the workspace root, fall back to the terminal.
204
+
205
+ Order matters:
206
+
207
+ 1. If `<id>.md` exists, move it to `<id>.prev.md`, overwriting any existing `.prev`.
208
+ Exactly one prior version is kept. There is no version history.
209
+ 2. Write the new body to `<id>.md.tmp`.
210
+ 3. Rename `<id>.md.tmp` to `<id>.md`.
211
+ 4. Only if the soft target overflowed, write `<id>.detail.md` the same way.
212
+
213
+ **PowerShell fallback.** Use a single-quoted here-string so `$` and backticks in
214
+ the content are not expanded:
215
+
216
+ ```powershell
217
+ $store = Join-Path $env:USERPROFILE '.agents\handoffs'
218
+ $id = '<id>'
219
+ $cur = Join-Path $store "$id.md"
220
+ if (Test-Path $cur) { Move-Item -Force $cur (Join-Path $store "$id.prev.md") }
221
+ $body = @'
222
+ <the full handoff body>
223
+ '@
224
+ Set-Content -Path (Join-Path $store "$id.md.tmp") -Value $body -Encoding UTF8
225
+ Move-Item -Force (Join-Path $store "$id.md.tmp") $cur
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Step 6 — Update the index
231
+
232
+ `index.md` is what makes retrieval cheap later. Keep it to one row per thread.
233
+
234
+ ```markdown
235
+ | id | title | status | repos | updated |
236
+ |----|-------|--------|-------|---------|
237
+ ```
238
+
239
+ Replace the row whose `id` matches. Append only when the id is new. Never let two
240
+ rows share an id.
241
+
242
+ ---
243
+
244
+ ## Step 7 — Capture durable knowledge
245
+
246
+ Skip this step entirely if `agent-memory` is not installed. It is optional
247
+ machinery; the handoff above is complete without it.
248
+
249
+ A handoff carries this thread. The graph carries what stays true after the thread
250
+ ends. You already hold the whole conversation, so writing both costs the same single
251
+ request, which is the only reason this step belongs here rather than in its own skill.
252
+
253
+ ### What is durable
254
+
255
+ <!-- extraction-rules:start -->
256
+ - A node is durable only if it will still be true next month. Task state is not
257
+ durable and belongs in a handoff file, not in the graph.
258
+ - Every `decision` node carries its why and its rejected alternatives, or it is not
259
+ written. Rationale is the thing that never survives re-explanation.
260
+ - Anything the conversation did not actually establish is `confidence: inferred`,
261
+ and the body says what would confirm it.
262
+ - Prefer updating an existing node over creating a near-duplicate. `write` returns
263
+ the existing id on a content-hash match.
264
+ - A decision that replaces a known prior sets `supersedes` to that prior's id.
265
+ - Constraints are the highest-value type. An environment restriction, a blocked
266
+ tool, a policy that forbids an approach: write it, because it is what stops a
267
+ future agent burning a retry loop on something that was never going to ship.
268
+ - Zero durable knowledge is a valid outcome. Writing nothing beats writing noise.
269
+ <!-- extraction-rules:end -->
270
+
271
+ Your Decisions table and Constraints section are usually already the durable part.
272
+ The Current task state section never is.
273
+
274
+ ### Write it (ONE terminal call)
275
+
276
+ Types are `system`, `decision`, `convention`, `constraint`. Edge relations are
277
+ `depends-on`, `applies-to`, `supersedes`, `contradicts`, `evidence-for`.
278
+
279
+ ```bash
280
+ tmp="$(mktemp)"
281
+ cat > "$tmp" <<'JSON'
282
+ {"nodes":[
283
+ {"id":"use-sessions","type":"decision",
284
+ "title":"Chose server sessions over JWT",
285
+ "body":"Why: revocation had to take effect immediately.\nRejected: short-TTL JWT, because logout would lag by the TTL.\nImplemented in src/auth/session.js:42.",
286
+ "edges":[{"rel":"evidence-for","dst":"auth-service"}]}
287
+ ]}
288
+ JSON
289
+ agent-memory write --from-json "$tmp" --source handoff
290
+ rm -f "$tmp"
291
+ ```
292
+
293
+ ```powershell
294
+ $tmp = [System.IO.Path]::GetTempFileName()
295
+ @'
296
+ <the JSON>
297
+ '@ | Set-Content -Path $tmp -Encoding UTF8
298
+ agent-memory write --from-json $tmp --source handoff
299
+ Remove-Item -Force $tmp
300
+ ```
301
+
302
+ `write` redacts before anything reaches disk and reports every validation error at
303
+ once. Surface its warnings verbatim; a `title collision` warning means two ids now
304
+ describe the same thing and the user should know.
305
+
306
+ ---
307
+
308
+ ## Step 8 — Print the pickup line
309
+
310
+ End your reply with exactly this, and nothing after it:
311
+
312
+ ```
313
+ Handoff written: <absolute path to id.md>
314
+ Thread: <id> (<created|updated>)
315
+
316
+ Paste this in the other window:
317
+ Read <absolute path to id.md> and continue this work. Follow the Next action.
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Self-check before you write
323
+
324
+ Answer all five. If any is no, fix the file before writing it.
325
+
326
+ 1. Could a fresh agent execute **Next action** from this file alone?
327
+ 2. Does every decision state why, and what was rejected?
328
+ 3. Is Rejected approaches non-empty, or explicitly `None.`?
329
+ 4. Is every claim anchored to a path or a decision number?
330
+ 5. Is there a single secret, token, or connection string left in the body?
331
+
332
+ ---
333
+
334
+ ## Failure handling
335
+
336
+ - **File-write tool refuses paths outside the workspace.** Use the PowerShell or
337
+ bash fallback in Step 5. Expected on some configurations; not an error.
338
+ - **Terminal commands are approval-gated.** Proceed anyway. One approval click is
339
+ worth minutes of re-explanation. Do not ask the user to disable the gate.
340
+ - **Both write paths blocked.** Print the complete handoff body in the chat with
341
+ its intended absolute path and tell the user to save it manually. Never silently
342
+ fail, and never claim you wrote a file you did not write.
343
+ - **Not a git repository.** Omit git fields, record the working directory path,
344
+ continue.
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: recall
3
+ version: 0.1.0
4
+ description: "Durable project knowledge store. This line is regenerated by `agent-memory compact`. Use when you need to know how a system works, why a decision was made, what convention applies, or what the environment forbids."
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ triggers:
9
+ - how does this work
10
+ - why did we
11
+ - what did we decide
12
+ - what is the convention
13
+ - recall
14
+ ---
15
+
16
+ # recall
17
+
18
+ Answer from what this project already knows, before deriving it again.
19
+
20
+ The description line above is regenerated by `agent-memory compact`. It is the only
21
+ part of this system loaded into every conversation, so it stays short on purpose.
22
+ Everything below is read only when you actually invoke the skill.
23
+
24
+ Do the whole job in **one pass**. The routing map and the notes are two terminal
25
+ calls inside a single turn. Do not loop, do not re-read, do not ask the user what
26
+ they already told a previous window.
27
+
28
+ ---
29
+
30
+ ## Step 1 — Load the routing map (ONE terminal call)
31
+
32
+ ```bash
33
+ agent-memory tree
34
+ ```
35
+
36
+ `tree` scopes itself to the current repository and always includes globally scoped
37
+ notes, because a global constraint applies here too.
38
+
39
+ Output is one line per note: type, id, title.
40
+
41
+ ```
42
+ # memory: orders-api — 12 notes
43
+ constraint no-external-db No externally hosted databases
44
+ decision use-sessions Chose sessions over JWT
45
+ system auth-service Auth uses server sessions
46
+ ```
47
+
48
+ If the last line reads `N nodes not shown`, that is a real gap, not decoration.
49
+ Run `agent-memory tree --all` when the answer plausibly lives in what was dropped.
50
+
51
+ If the store is empty, say so in one line and answer from the code instead. Do not
52
+ invent notes and do not apologize at length.
53
+
54
+ ---
55
+
56
+ ## Step 2 — Choose what to load
57
+
58
+ Read the titles and decide, **by judgment**, which notes bear on the question. You
59
+ are the router. There is no keyword matching underneath this and there should not
60
+ be: a title is a sentence, and matching sentences to a question is what you do well
61
+ and what a regex does badly.
62
+
63
+ - Pick 1 to 3 ids. More than 3 means the question is really several questions.
64
+ - Always include a `constraint` that touches the subject, even when the user did not
65
+ ask about limits. Constraints are what stop an approach that cannot ship.
66
+ - Nothing in the tree looks relevant → go to Step 4.
67
+
68
+ ---
69
+
70
+ ## Step 3 — Load them (ONE terminal call)
71
+
72
+ ```bash
73
+ agent-memory get auth-service --depth 1
74
+ agent-memory get no-external-db --depth 1
75
+ ```
76
+
77
+ `--depth 1` returns the note plus everything one edge away. Use `--depth 2` only
78
+ when the question is about how parts fit together rather than about one part.
79
+
80
+ Two things in the output are load-bearing:
81
+
82
+ - `[captured N commits ago — verify before trusting]` means the note was written
83
+ against an older state of this repository. Say so when you use it.
84
+ - `N nodes omitted for budget` means the neighborhood was larger than the return
85
+ budget. The omitted ids are listed; ask for one directly if it matters.
86
+
87
+ ---
88
+
89
+ ## Step 4 — Fall back to search
90
+
91
+ Only when the tree had nothing plausible:
92
+
93
+ ```bash
94
+ agent-memory search "session revocation"
95
+ ```
96
+
97
+ Full text over titles and bodies. If this also misses, the store genuinely does not
98
+ know, and saying so plainly is the correct answer.
99
+
100
+ ---
101
+
102
+ ## Step 5 — Answer
103
+
104
+ Rules that separate a useful recall from a confident wrong one:
105
+
106
+ 1. **Cite the note id** for every claim you take from memory, and the `path:line`
107
+ inside the note when it has one.
108
+ 2. **Repeat the staleness annotation** if the note carried one. A note captured 47
109
+ commits ago may still be right, but the user decides that, not you.
110
+ 3. **The code wins.** If a note contradicts what you can read in the repository
111
+ right now, trust the repository, say which note is wrong, and suggest
112
+ `/remember` to correct it. A store that quietly rots is worse than no store.
113
+ 4. **Never present an `inferred` note as established.** The note says which it is.
114
+ 5. Answer the question. Do not summarize the store.
115
+
116
+ ---
117
+
118
+ ## Failure handling
119
+
120
+ - **`agent-memory: command not found`.** The package is not installed or not on
121
+ PATH. Say so and answer from the code; do not attempt to install it.
122
+ - **Empty store.** Answer from the code, then mention `/remember` once.
123
+ - **`doctor` reports a problem.** Report it in one line and continue. `index.db` is
124
+ a cache; `agent-memory index` rebuilds it from the markdown, which is the source
125
+ of truth and is never lost.