eagle-mem 2.0.6 → 2.0.7

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ```
2
- █▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
3
- ██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
2
+ ======================================
3
+ Eagle Mem
4
+ ======================================
4
5
  ```
5
6
 
6
7
  # Eagle Mem
@@ -21,12 +22,19 @@ eagle-mem install
21
22
  **2. Open Claude Code** in any project directory. Eagle Mem activates and shows what it loaded:
22
23
 
23
24
  ```
24
- █▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
25
- ██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
26
-
27
- Project: my-app
28
- Sessions: 5 recent | Memories: 3 | Tasks: 2 pending
29
- Last: Added auth middleware with JWT validation
25
+ ======================================
26
+ Eagle Mem Loaded
27
+ ======================================
28
+ Project | my-app
29
+ Sessions | 42 total (18 with summaries)
30
+ Memories | 7 stored
31
+ Plans | 2 saved
32
+ Tasks | 1 in progress, 3 pending, 12 completed
33
+ Code Index | 156 chunks indexed
34
+ Observations | 340 captured
35
+ Last Active | 2026-04-28
36
+ Last Work | Added auth middleware with JWT validation
37
+ ======================================
30
38
  ```
31
39
 
32
40
  From here, everything is automatic. You don't run any commands — Eagle Mem captures session summaries, mirrors Claude's memories and tasks, and re-injects context after every `/compact` or new session.
@@ -0,0 +1,51 @@
1
+ -- Migration 012: Add decisions, gotchas, key_files columns to summaries
2
+ -- These capture WHY choices were made, WHAT went wrong, and WHERE to start reading.
3
+ -- Also adds them to FTS5 so they're searchable across sessions.
4
+
5
+ -- Add new columns
6
+ ALTER TABLE summaries ADD COLUMN decisions TEXT;
7
+ ALTER TABLE summaries ADD COLUMN gotchas TEXT;
8
+ ALTER TABLE summaries ADD COLUMN key_files TEXT;
9
+
10
+ -- Rebuild FTS5 to include new columns
11
+ DROP TRIGGER IF EXISTS summaries_ai;
12
+ DROP TRIGGER IF EXISTS summaries_ad;
13
+ DROP TRIGGER IF EXISTS summaries_au;
14
+
15
+ DROP TABLE IF EXISTS summaries_fts;
16
+
17
+ CREATE VIRTUAL TABLE summaries_fts USING fts5(
18
+ request,
19
+ investigated,
20
+ learned,
21
+ completed,
22
+ next_steps,
23
+ notes,
24
+ decisions,
25
+ gotchas,
26
+ key_files,
27
+ content='summaries',
28
+ content_rowid='id'
29
+ );
30
+
31
+ -- Backfill FTS from existing data
32
+ INSERT INTO summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files)
33
+ SELECT id, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files FROM summaries;
34
+
35
+ -- Recreate content-sync triggers with new columns
36
+ CREATE TRIGGER summaries_ai AFTER INSERT ON summaries BEGIN
37
+ INSERT INTO summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files)
38
+ VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes, new.decisions, new.gotchas, new.key_files);
39
+ END;
40
+
41
+ CREATE TRIGGER summaries_ad AFTER DELETE ON summaries BEGIN
42
+ INSERT INTO summaries_fts(summaries_fts, rowid, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files)
43
+ VALUES ('delete', old.id, old.request, old.investigated, old.learned, old.completed, old.next_steps, old.notes, old.decisions, old.gotchas, old.key_files);
44
+ END;
45
+
46
+ CREATE TRIGGER summaries_au AFTER UPDATE ON summaries BEGIN
47
+ INSERT INTO summaries_fts(summaries_fts, rowid, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files)
48
+ VALUES ('delete', old.id, old.request, old.investigated, old.learned, old.completed, old.next_steps, old.notes, old.decisions, old.gotchas, old.key_files);
49
+ INSERT INTO summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes, decisions, gotchas, key_files)
50
+ VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes, new.decisions, new.gotchas, new.key_files);
51
+ END;
@@ -124,6 +124,40 @@ case "$tool_name" in
124
124
  ;;
125
125
  esac
126
126
 
127
+ # ─── Stale memory hint ──────────────────────────────────
128
+ # After editing a project file, FTS5-search memories for the filename.
129
+ # If a memory mentions this file, remind Claude to check for staleness.
130
+ case "$tool_name" in
131
+ Write|Edit)
132
+ if [ -n "$fp" ]; then
133
+ fname=$(basename "$fp")
134
+ fname_stem="${fname%.*}"
135
+ case "$fp" in
136
+ "$HOME/.claude/"*) ;; # skip Claude config files
137
+ *)
138
+ if [ ${#fname_stem} -ge 3 ]; then
139
+ fts_query=$(eagle_fts_sanitize "$fname_stem")
140
+ if [ -n "$fts_query" ]; then
141
+ fts_esc=$(eagle_sql_escape "$fts_query")
142
+ p_esc=$(eagle_sql_escape "$project")
143
+ stale_hit=$(eagle_db "SELECT m.memory_name
144
+ FROM claude_memories m
145
+ JOIN claude_memories_fts f ON f.rowid = m.id
146
+ WHERE claude_memories_fts MATCH '$fts_esc'
147
+ AND m.project = '$p_esc'
148
+ LIMIT 1;")
149
+ if [ -n "$stale_hit" ]; then
150
+ stale_msg="Eagle Mem: Memory '${stale_hit}' may reference '${fname}'. If your edit contradicts it, update the memory."
151
+ jq -nc --arg ctx "$stale_msg" '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":$ctx}}'
152
+ fi
153
+ fi
154
+ fi
155
+ ;;
156
+ esac
157
+ fi
158
+ ;;
159
+ esac
160
+
127
161
  eagle_insert_observation "$session_id" "$project" "$tool_name" "$tool_summary" "$files_read" "$files_modified"
128
162
 
129
163
  exit 0
@@ -66,12 +66,68 @@ if [ -f "$version_file" ] && [ -s "$version_file" ]; then
66
66
  fi
67
67
  fi
68
68
 
69
- # ─── Build context injection ────────────────────────────────
69
+ # ─── Gather stats ───────────────────────────────────────────
70
+
71
+ p_esc=$(eagle_sql_escape "$project")
72
+
73
+ stat_sessions=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE project = '$p_esc';")
74
+ stat_summaries=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE project = '$p_esc';")
75
+ stat_memories=$(eagle_db "SELECT COUNT(*) FROM claude_memories WHERE project = '$p_esc';")
76
+ stat_tasks_pending=$(eagle_db "SELECT COUNT(*) FROM claude_tasks WHERE project = '$p_esc' AND status = 'pending';")
77
+ stat_tasks_progress=$(eagle_db "SELECT COUNT(*) FROM claude_tasks WHERE project = '$p_esc' AND status = 'in_progress';")
78
+ stat_tasks_done=$(eagle_db "SELECT COUNT(*) FROM claude_tasks WHERE project = '$p_esc' AND status = 'completed';")
79
+ stat_chunks=$(eagle_db "SELECT COUNT(*) FROM code_chunks WHERE project = '$p_esc';")
80
+ stat_observations=$(eagle_db "SELECT COUNT(*) FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE project = '$p_esc');")
81
+ stat_plans=$(eagle_db "SELECT COUNT(*) FROM claude_plans WHERE project = '$p_esc';")
82
+ stat_last_active=$(eagle_db "SELECT COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE project = '$p_esc';")
83
+ stat_last_summary=$(eagle_db "SELECT request FROM summaries WHERE project = '$p_esc' ORDER BY created_at DESC LIMIT 1;")
84
+
85
+ # Trim to defaults
86
+ stat_sessions="${stat_sessions:-0}"
87
+ stat_summaries="${stat_summaries:-0}"
88
+ stat_memories="${stat_memories:-0}"
89
+ stat_tasks_pending="${stat_tasks_pending:-0}"
90
+ stat_tasks_progress="${stat_tasks_progress:-0}"
91
+ stat_tasks_done="${stat_tasks_done:-0}"
92
+ stat_chunks="${stat_chunks:-0}"
93
+ stat_observations="${stat_observations:-0}"
94
+ stat_plans="${stat_plans:-0}"
95
+
96
+ # Build task summary line
97
+ task_parts=""
98
+ [ "$stat_tasks_progress" -gt 0 ] && task_parts="${stat_tasks_progress} in progress"
99
+ if [ "$stat_tasks_pending" -gt 0 ]; then
100
+ [ -n "$task_parts" ] && task_parts+=", "
101
+ task_parts+="${stat_tasks_pending} pending"
102
+ fi
103
+ if [ "$stat_tasks_done" -gt 0 ]; then
104
+ [ -n "$task_parts" ] && task_parts+=", "
105
+ task_parts+="${stat_tasks_done} completed"
106
+ fi
107
+ [ -z "$task_parts" ] && task_parts="none"
108
+
109
+ # Truncate last summary for display
110
+ stat_last_display="${stat_last_summary:0:60}"
111
+ [ ${#stat_last_summary} -gt 60 ] && stat_last_display+="..."
112
+ [ -z "$stat_last_display" ] && stat_last_display="(no sessions yet)"
70
113
 
71
- eagle_logo="█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
72
- ██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █"
114
+ # ─── Build context injection ────────────────────────────────
73
115
 
74
- context="$eagle_logo
116
+ eagle_banner="======================================
117
+ Eagle Mem Loaded
118
+ ======================================
119
+ Project | $project
120
+ Sessions | $stat_sessions total ($stat_summaries with summaries)
121
+ Memories | $stat_memories stored
122
+ Plans | $stat_plans saved
123
+ Tasks | $task_parts
124
+ Code Index | $stat_chunks chunks indexed
125
+ Observations | $stat_observations captured
126
+ Last Active | $stat_last_active
127
+ Last Work | $stat_last_display
128
+ ======================================"
129
+
130
+ context="$eagle_banner
75
131
 
76
132
  === EAGLE MEM — Active (trigger: $source_type) ===
77
133
  Eagle Mem (https://github.com/eagleisbatman/eagle-mem) is providing persistent memory for this session. It tracks summaries, observations, tasks, and code context across sessions via SQLite + FTS5. Mention Eagle Mem by name when referencing recalled context.
@@ -105,7 +161,7 @@ if [ -n "$recent" ]; then
105
161
  context+="=== EAGLE MEM ===
106
162
  Recent sessions for project '$project':
107
163
  "
108
- while IFS='|' read -r request completed learned next_steps created_at; do
164
+ while IFS='|' read -r request completed learned next_steps created_at decisions gotchas key_files; do
109
165
  [ -z "$request" ] && [ -z "$completed" ] && continue
110
166
  context+="
111
167
  --- $created_at ---"
@@ -115,6 +171,12 @@ Request: $request"
115
171
  Completed: $completed"
116
172
  [ -n "$learned" ] && context+="
117
173
  Learned: $learned"
174
+ [ -n "$decisions" ] && context+="
175
+ Decisions: $decisions"
176
+ [ -n "$gotchas" ] && context+="
177
+ Gotchas: $gotchas"
178
+ [ -n "$key_files" ] && context+="
179
+ Key files: $key_files"
118
180
  [ -n "$next_steps" ] && context+="
119
181
  Next steps: $next_steps"
120
182
  done <<< "$recent"
@@ -122,17 +184,32 @@ Next steps: $next_steps"
122
184
  "
123
185
  fi
124
186
 
125
- # ─── Mirrored Claude memories ──────────────────────────────
187
+ # ─── Mirrored Claude memories (with age) ─────────────────
126
188
 
127
- memories=$(eagle_list_claude_memories "$project" 5)
189
+ memories=$(eagle_db "SELECT memory_name, memory_type, description, file_path, updated_at,
190
+ CAST(julianday('now') - julianday(updated_at) AS INTEGER) as days_ago
191
+ FROM claude_memories
192
+ WHERE project = '$p_esc'
193
+ ORDER BY updated_at DESC
194
+ LIMIT 5;")
128
195
  if [ -n "$memories" ]; then
129
196
  context+="
130
197
  === EAGLE MEM — Memories ===
131
198
  Recent memories for '$project':
132
199
  "
133
- while IFS='|' read -r mname mtype mdesc _fpath _updated; do
200
+ while IFS='|' read -r mname mtype mdesc _fpath _updated days_ago; do
134
201
  [ -z "$mname" ] && continue
135
- context+=" - [$mtype] $mname: $mdesc
202
+ age_label=""
203
+ if [ -n "$days_ago" ] && [ "$days_ago" -gt 0 ] 2>/dev/null; then
204
+ if [ "$days_ago" -eq 1 ]; then
205
+ age_label=" (1 day ago)"
206
+ else
207
+ age_label=" (${days_ago} days ago)"
208
+ fi
209
+ else
210
+ age_label=" (today)"
211
+ fi
212
+ context+=" - [$mtype] $mname: $mdesc$age_label
136
213
  "
137
214
  done <<< "$memories"
138
215
  fi
@@ -155,7 +232,7 @@ fi
155
232
  # ─── Claude Code tasks ───────────────────────────────────
156
233
 
157
234
  synced_tasks=$(eagle_db "SELECT subject, status, blocked_by FROM claude_tasks
158
- WHERE project = '$(eagle_sql_escape "$project")'
235
+ WHERE project = '$p_esc'
159
236
  AND status IN ('in_progress', 'pending')
160
237
  AND updated_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-7 days')
161
238
  ORDER BY
@@ -183,29 +260,62 @@ context+="
183
260
  === EAGLE MEM INSTRUCTIONS ===
184
261
  You have persistent memory powered by Eagle Mem. When you recall context from a previous session or use injected memory, attribute it: \"From Eagle Mem:\" or \"Eagle Mem recalls:\". This helps the user understand where the context came from.
185
262
 
186
- IMPORTANT: At the start of your VERY NEXT response (this fires on session start, /clear, AND context compaction — always show this block, even if you think you showed it before, because prior context may have been compressed away). Show the user what Eagle Mem loaded using this exact format:
263
+ IMPORTANT: At the start of your VERY NEXT response (this fires on session start, /clear, AND context compaction — always show this block, even if you think you showed it before, because prior context may have been compressed away). Show the user what Eagle Mem loaded by reproducing this exact banner:
187
264
 
188
265
  \`\`\`
189
- $eagle_logo
190
-
191
- Project: <project name>
192
- Sessions: N recent | Memories: N | Tasks: N pending
193
- Last: [one-line summary of most recent session]
266
+ $eagle_banner
194
267
  \`\`\`
195
268
 
196
- This gives the user visibility into the context you received.
269
+ This gives the user visibility into the full context Eagle Mem loaded for this session.
270
+
271
+ MEMORY FRESHNESS: The memories above include age indicators. If you make a change (edit a file, update a config, change a pattern) that contradicts what a loaded memory says, you MUST update that memory file immediately. Read the memory file, edit it to reflect the new reality, and the PostToolUse hook will sync the update to Eagle Mem. Stale memories mislead future sessions — keeping them current is as important as writing good code.
272
+
273
+ === EAGLE MEM — SESSION SUMMARY (MANDATORY) ===
274
+ You MUST emit an <eagle-summary> block before your FINAL response in this session. This is how Eagle Mem captures what happened — without it, the next session starts blind and wastes tokens rediscovering context.
275
+
276
+ FORMAT — emit this block exactly. Every field is REQUIRED. Do not skip fields, do not leave them empty, do not write \"N/A\".
197
277
 
198
- Before your final response in this session, emit a summary block:
199
278
  <eagle-summary>
200
- request: What the user asked for
201
- investigated: Key files/areas explored
202
- learned: Non-obvious discoveries
203
- completed: What was accomplished
204
- next_steps: What should happen next
205
- files_read: [list of files read]
206
- files_modified: [list of files modified]
279
+ request: [One sentence: what did the user ask for?]
280
+ investigated: [Comma-separated file paths you read or explored]
281
+ learned: [Non-obvious technical discoveries — things a future session could not guess from reading the code]
282
+ completed: [What was accomplished — be specific about what shipped, not what was \"worked on\"]
283
+ next_steps: [Concrete actions for the next session, not vague aspirations]
284
+ decisions:
285
+ - [Choice made] Why: [the reason what constraint or tradeoff drove this choice]
286
+ - [Choice made] Why: [reason]
287
+ gotchas:
288
+ - [What failed, surprised, or does not work the obvious way. Be specific — \"X does not work because Y\" not just \"X was tricky\"]
289
+ key_files:
290
+ - [path/to/file.ext] — [one-line role: what this file does in the context of this work]
291
+ - [path/to/other.ext] — [role]
292
+ files_read: [file1, file2, ...]
293
+ files_modified: [file1, file2, ...]
207
294
  </eagle-summary>
208
- This helps Eagle Mem track what happened for future sessions.
295
+
296
+ EXAMPLE — this is what a well-written summary looks like:
297
+
298
+ <eagle-summary>
299
+ request: Add JWT authentication middleware to the API
300
+ investigated: src/middleware/auth.ts, src/routes/users.ts, package.json, src/config/env.ts
301
+ learned: express-jwt v8 changed its API — req.auth replaces req.user. The error handler must check err.name === 'UnauthorizedError', not err.status === 401.
302
+ completed: JWT middleware deployed on all /api routes. Token validation, role-based guards, and 401/403 error responses all working. Added JWKS endpoint support for key rotation.
303
+ next_steps: Add refresh token rotation; rate-limit the /auth/token endpoint
304
+ decisions:
305
+ - Chose RS256 over HS256 for JWT signing. Why: allows key rotation via JWKS without redeploying; HS256 requires shared secret on every service.
306
+ - Put auth middleware at router level, not app level. Why: healthcheck and public routes must remain unauthenticated; per-router mounting is explicit about what is protected.
307
+ gotchas:
308
+ - express-jwt v8 is ESM-only — require() fails silently and returns undefined. Must use dynamic import().
309
+ - Setting token expiry below 5 min causes refresh storms under load — the refresh endpoint itself requires a valid (but expired) token, creating a chicken-and-egg problem.
310
+ key_files:
311
+ - src/middleware/auth.ts — JWT validation + role guard middleware
312
+ - src/config/env.ts — JWKS_URI and JWT_ISSUER environment config
313
+ - src/routes/users.ts — first route to use the new auth guard (reference implementation)
314
+ files_read: [src/middleware/auth.ts, src/routes/users.ts, package.json, src/config/env.ts]
315
+ files_modified: [src/middleware/auth.ts, src/config/env.ts, src/routes/users.ts, package.json]
316
+ </eagle-summary>
317
+
318
+ WHY THIS MATTERS: Eagle Mem re-injects this summary at the start of future sessions. The 'decisions' field prevents re-debating settled choices. The 'gotchas' field prevents repeating the same mistakes. The 'key_files' field tells the next session exactly where to start reading instead of exploring blindly. Write these fields as if you are briefing a colleague who will pick up your work tomorrow — because that is exactly what happens.
209
319
  "
210
320
 
211
321
  # Output context (plain text stdout = additionalContext for SessionStart)
package/hooks/stop.sh CHANGED
@@ -67,7 +67,7 @@ parse_field() {
67
67
  $0 ~ "^"f":" {
68
68
  sub("^"f":[[:space:]]*", ""); found=1; val=$0; next
69
69
  }
70
- found && /^(request|investigated|learned|completed|next_steps|files_read|files_modified|notes):/ { exit }
70
+ found && /^(request|investigated|learned|completed|next_steps|files_read|files_modified|notes|decisions|gotchas|key_files):/ { exit }
71
71
  found { val = val " " $0 }
72
72
  END { if (found) print val }
73
73
  '
@@ -81,6 +81,9 @@ next_steps=""
81
81
  files_read="[]"
82
82
  files_modified="[]"
83
83
  notes=""
84
+ decisions=""
85
+ gotchas=""
86
+ key_files=""
84
87
 
85
88
  if [ -n "$summary_block" ]; then
86
89
  request=$(parse_field "$summary_block" "request")
@@ -88,6 +91,9 @@ if [ -n "$summary_block" ]; then
88
91
  learned=$(parse_field "$summary_block" "learned")
89
92
  completed=$(parse_field "$summary_block" "completed")
90
93
  next_steps=$(parse_field "$summary_block" "next_steps")
94
+ decisions=$(parse_field "$summary_block" "decisions")
95
+ gotchas=$(parse_field "$summary_block" "gotchas")
96
+ key_files=$(parse_field "$summary_block" "key_files")
91
97
 
92
98
  raw_fr=$(parse_field "$summary_block" "files_read")
93
99
  raw_fm=$(parse_field "$summary_block" "files_modified")
@@ -137,7 +143,7 @@ fi
137
143
  # ─── Write to database ─────────────────────────────────────
138
144
 
139
145
  if [ -n "$request" ] || [ -n "$completed" ] || [ -n "$learned" ]; then
140
- eagle_insert_summary "$session_id" "$project" "$request" "$investigated" "$learned" "$completed" "$next_steps" "$files_read" "$files_modified" "$notes"
146
+ eagle_insert_summary "$session_id" "$project" "$request" "$investigated" "$learned" "$completed" "$next_steps" "$files_read" "$files_modified" "$notes" "$decisions" "$gotchas" "$key_files"
141
147
  eagle_log "INFO" "Stop: summary saved for session=$session_id"
142
148
  fi
143
149
 
@@ -52,12 +52,18 @@ context=""
52
52
  if [ -n "$results" ]; then
53
53
  context+="=== EAGLE MEM — Relevant Memory ===
54
54
  "
55
- while IFS='|' read -r req completed learned _next_steps created_at _proj; do
55
+ while IFS='|' read -r req completed learned _next_steps created_at _proj decisions gotchas key_files; do
56
56
  [ -z "$req" ] && [ -z "$completed" ] && continue
57
57
  context+="[$created_at] "
58
58
  [ -n "$req" ] && context+="$req"
59
59
  [ -n "$completed" ] && context+=" → $completed"
60
60
  [ -n "$learned" ] && context+=" (Learned: $learned)"
61
+ [ -n "$decisions" ] && context+="
62
+ Decisions: $decisions"
63
+ [ -n "$gotchas" ] && context+="
64
+ Gotchas: $gotchas"
65
+ [ -n "$key_files" ] && context+="
66
+ Key files: $key_files"
61
67
  context+="
62
68
  "
63
69
  done <<< "$results"
package/lib/db.sh CHANGED
@@ -85,9 +85,12 @@ eagle_insert_summary() {
85
85
  local files_read; files_read=$(eagle_sql_escape "$8")
86
86
  local files_modified; files_modified=$(eagle_sql_escape "$9")
87
87
  local notes; notes=$(eagle_sql_escape "${10:-}")
88
+ local decisions; decisions=$(eagle_sql_escape "${11:-}")
89
+ local gotchas; gotchas=$(eagle_sql_escape "${12:-}")
90
+ local key_files; key_files=$(eagle_sql_escape "${13:-}")
88
91
 
89
92
  eagle_db_pipe <<SQL
90
- INSERT INTO summaries (session_id, project, request, investigated, learned, completed, next_steps, files_read, files_modified, notes)
93
+ INSERT INTO summaries (session_id, project, request, investigated, learned, completed, next_steps, files_read, files_modified, notes, decisions, gotchas, key_files)
91
94
  VALUES (
92
95
  '$session_id',
93
96
  '$project',
@@ -98,7 +101,10 @@ VALUES (
98
101
  '$next_steps',
99
102
  '$files_read',
100
103
  '$files_modified',
101
- '$notes'
104
+ '$notes',
105
+ '$decisions',
106
+ '$gotchas',
107
+ '$key_files'
102
108
  )
103
109
  ON CONFLICT(session_id) DO UPDATE SET
104
110
  project = excluded.project,
@@ -109,7 +115,10 @@ ON CONFLICT(session_id) DO UPDATE SET
109
115
  next_steps = COALESCE(NULLIF(excluded.next_steps, ''), summaries.next_steps),
110
116
  files_read = COALESCE(NULLIF(excluded.files_read, '[]'), summaries.files_read),
111
117
  files_modified = COALESCE(NULLIF(excluded.files_modified, '[]'), summaries.files_modified),
112
- notes = COALESCE(NULLIF(excluded.notes, ''), summaries.notes);
118
+ notes = COALESCE(NULLIF(excluded.notes, ''), summaries.notes),
119
+ decisions = COALESCE(NULLIF(excluded.decisions, ''), summaries.decisions),
120
+ gotchas = COALESCE(NULLIF(excluded.gotchas, ''), summaries.gotchas),
121
+ key_files = COALESCE(NULLIF(excluded.key_files, ''), summaries.key_files);
113
122
  SQL
114
123
  }
115
124
 
@@ -117,7 +126,7 @@ eagle_get_recent_summaries() {
117
126
  local project; project=$(eagle_sql_escape "$1")
118
127
  local limit; limit=$(eagle_sql_int "${2:-5}")
119
128
 
120
- eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at
129
+ eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.decisions, s.gotchas, s.key_files
121
130
  FROM summaries s
122
131
  WHERE s.project = '$project'
123
132
  AND s.request NOT LIKE '%<local-command-caveat>%'
@@ -137,7 +146,7 @@ eagle_search_summaries() {
137
146
  where_clause="AND s.project = '$project'"
138
147
  fi
139
148
 
140
- eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.project
149
+ eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.project, s.decisions, s.gotchas, s.key_files
141
150
  FROM summaries s
142
151
  JOIN summaries_fts f ON f.rowid = s.id
143
152
  WHERE summaries_fts MATCH '$query'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eagle-mem",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "Persistent memory for Claude Code — SQLite + FTS5, no daemon, no bloat",
5
5
  "bin": {
6
6
  "eagle-mem": "bin/eagle-mem"
package/scripts/style.sh CHANGED
@@ -43,12 +43,10 @@ eagle_footer() {
43
43
  }
44
44
 
45
45
  eagle_banner() {
46
- echo -e "${CYAN}"
47
- cat << 'BANNER'
48
- █▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
49
- ██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
50
- BANNER
51
- echo -e "${RESET}"
46
+ echo -e " ${CYAN}======================================${RESET}"
47
+ echo -e " ${CYAN}${BOLD} Eagle Mem${RESET}"
48
+ echo -e " ${CYAN}======================================${RESET}"
49
+ echo ""
52
50
  }
53
51
 
54
52
  eagle_is_tty() {