eagle-mem 1.4.7 → 1.5.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/README.md +28 -40
- package/db/008_summary_upsert.sql +57 -0
- package/db/migrate.sh +10 -2
- package/hooks/post-tool-use.sh +21 -10
- package/hooks/session-end.sh +9 -7
- package/hooks/session-start.sh +15 -14
- package/hooks/stop.sh +27 -20
- package/lib/common.sh +7 -0
- package/lib/db.sh +21 -32
- package/package.json +1 -1
- package/scripts/help.sh +7 -3
- package/scripts/index.sh +12 -4
- package/scripts/install.sh +50 -1
- package/scripts/overview.sh +20 -34
- package/scripts/statusline-em.sh +34 -0
- package/scripts/style.sh +2 -23
- package/scripts/tasks.sh +22 -36
- package/scripts/uninstall.sh +4 -9
- package/skills/eagle-mem-index/SKILL.md +49 -0
- package/skills/eagle-mem-memories/SKILL.md +75 -0
- package/skills/eagle-mem-prune/SKILL.md +63 -0
- package/skills/eagle-mem-scan/SKILL.md +48 -0
package/README.md
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
```
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
| \o/|'-.
|
|
5
|
-
| / ,\
|
|
6
|
-
| ('--./
|
|
7
|
-
/ \
|
|
8
|
-
/ , , , \
|
|
9
|
-
`--'--'--'--'
|
|
10
|
-
|
|
11
|
-
███████╗░█████╗░░██████╗░██╗░░░░░███████╗ ███╗░░░███╗███████╗███╗░░░███╗
|
|
12
|
-
██╔════╝██╔══██╗██╔════╝░██║░░░░░██╔════╝ ████╗░████║██╔════╝████╗░████║
|
|
13
|
-
█████╗░░███████║██║░░██╗░██║░░░░░█████╗░░ ██╔████╔██║█████╗░░██╔████╔██║
|
|
14
|
-
██╔══╝░░██╔══██║██║░░╚██╗██║░░░░░██╔══╝░░ ██║╚██╔╝██║██╔══╝░░██║╚██╔╝██║
|
|
15
|
-
███████╗██║░░██║╚██████╔╝███████╗███████╗ ██║░╚═╝░██║███████╗██║░╚═╝░██║
|
|
16
|
-
╚══════╝╚═╝░░╚═╝░╚═════╝░╚══════╝╚══════╝ ╚═╝░░░░░╚═╝╚══════╝╚═╝░░░░░╚═╝
|
|
2
|
+
█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
3
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
|
|
17
4
|
```
|
|
18
5
|
|
|
19
6
|
# Eagle Mem
|
|
@@ -32,14 +19,8 @@ eagle-mem install
|
|
|
32
19
|
The installer checks prerequisites and offers to install missing ones:
|
|
33
20
|
|
|
34
21
|
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| \o/|'-.
|
|
38
|
-
| / ,\
|
|
39
|
-
| ('--./
|
|
40
|
-
/ \
|
|
41
|
-
/ , , , \
|
|
42
|
-
`--'--'--'--'
|
|
22
|
+
█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
23
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
|
|
43
24
|
|
|
44
25
|
Eagle Mem Install
|
|
45
26
|
─────────────────────────────────────
|
|
@@ -64,14 +45,12 @@ The installer checks prerequisites and offers to install missing ones:
|
|
|
64
45
|
Start a new Claude Code session — Eagle Mem activates automatically and shows:
|
|
65
46
|
|
|
66
47
|
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/ , , , \
|
|
74
|
-
`--'--'--'--'
|
|
48
|
+
█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
49
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
|
|
50
|
+
|
|
51
|
+
Project: my-app
|
|
52
|
+
Sessions: 5 recent | Memories: 3 | Tasks: 2 pending
|
|
53
|
+
Last: Added auth middleware with JWT validation
|
|
75
54
|
```
|
|
76
55
|
|
|
77
56
|
## Commands
|
|
@@ -213,11 +192,15 @@ Single shared SQLite database at `~/.eagle-mem/memory.db` with a `project` colum
|
|
|
213
192
|
|
|
214
193
|
## Skills
|
|
215
194
|
|
|
216
|
-
Eagle Mem ships with
|
|
195
|
+
Eagle Mem ships with seven skills for use inside Claude Code sessions:
|
|
217
196
|
|
|
218
197
|
- **eagle-mem-search** — 3-layer search: compact FTS5 search, timeline view, full observations
|
|
219
198
|
- **eagle-mem-tasks** — TaskAware Compact Loop: create, view, complete, and manage subtasks
|
|
220
199
|
- **eagle-mem-overview** — Generate and update a persistent project overview
|
|
200
|
+
- **eagle-mem-index** — Index source files for FTS5 code-level search
|
|
201
|
+
- **eagle-mem-scan** — Scan and analyze a project to generate an overview
|
|
202
|
+
- **eagle-mem-memories** — Browse and search Claude Code memories, plans, and tasks
|
|
203
|
+
- **eagle-mem-prune** — Clean up old observations and orphaned chunks
|
|
221
204
|
|
|
222
205
|
## Architecture
|
|
223
206
|
|
|
@@ -236,19 +219,24 @@ Package (npm) Runtime (~/.eagle-mem/)
|
|
|
236
219
|
│ ├── overview.sh │ └── db.sh
|
|
237
220
|
│ ├── memories.sh └── db/
|
|
238
221
|
│ ├── prune.sh ├── migrate.sh
|
|
239
|
-
│
|
|
240
|
-
|
|
241
|
-
├──
|
|
242
|
-
|
|
243
|
-
│
|
|
244
|
-
|
|
245
|
-
|
|
222
|
+
│ ├── statusline-em.sh ├── schema.sql
|
|
223
|
+
│ └── help.sh ├── 002_overviews.sql
|
|
224
|
+
├── hooks/ Source ├── 003_code_chunks.sql
|
|
225
|
+
├── lib/ Source ├── 004_observation_indexes.sql
|
|
226
|
+
│ ├── common.sh ├── 005_claude_memories.sql
|
|
227
|
+
│ └── db.sh ├── 006_claude_plans.sql
|
|
228
|
+
├── db/ Source └── 007_claude_tasks.sql
|
|
229
|
+
│ ├── migrate.sh
|
|
246
230
|
│ ├── schema.sql
|
|
247
231
|
│ └── migrations
|
|
248
232
|
└── skills/ Symlinked → ~/.claude/skills/
|
|
249
233
|
├── eagle-mem-search/
|
|
250
234
|
├── eagle-mem-tasks/
|
|
251
|
-
|
|
235
|
+
├── eagle-mem-overview/
|
|
236
|
+
├── eagle-mem-index/
|
|
237
|
+
├── eagle-mem-scan/
|
|
238
|
+
├── eagle-mem-memories/
|
|
239
|
+
└── eagle-mem-prune/
|
|
252
240
|
```
|
|
253
241
|
|
|
254
242
|
## Uninstall
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
-- Migration 008: Enforce one summary per session
|
|
2
|
+
-- Removes duplicate summaries (keeps the latest) and adds UNIQUE constraint.
|
|
3
|
+
-- Recreates FTS triggers since DROP TABLE removes them.
|
|
4
|
+
|
|
5
|
+
-- Delete duplicates, keeping only the row with the highest id per session
|
|
6
|
+
DELETE FROM summaries WHERE id NOT IN (
|
|
7
|
+
SELECT MAX(id) FROM summaries GROUP BY session_id
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
-- Rebuild FTS index to match cleaned data
|
|
11
|
+
INSERT INTO summaries_fts(summaries_fts) VALUES('rebuild');
|
|
12
|
+
|
|
13
|
+
-- Drop old triggers (they'll be gone after table rebuild anyway)
|
|
14
|
+
DROP TRIGGER IF EXISTS summaries_ai;
|
|
15
|
+
DROP TRIGGER IF EXISTS summaries_ad;
|
|
16
|
+
DROP TRIGGER IF EXISTS summaries_au;
|
|
17
|
+
|
|
18
|
+
-- Recreate table with UNIQUE(session_id)
|
|
19
|
+
CREATE TABLE summaries_new (
|
|
20
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
21
|
+
session_id TEXT NOT NULL UNIQUE REFERENCES sessions(id),
|
|
22
|
+
project TEXT NOT NULL,
|
|
23
|
+
request TEXT,
|
|
24
|
+
investigated TEXT,
|
|
25
|
+
learned TEXT,
|
|
26
|
+
completed TEXT,
|
|
27
|
+
next_steps TEXT,
|
|
28
|
+
files_read TEXT DEFAULT '[]',
|
|
29
|
+
files_modified TEXT DEFAULT '[]',
|
|
30
|
+
notes TEXT,
|
|
31
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
INSERT INTO summaries_new SELECT * FROM summaries;
|
|
35
|
+
DROP TABLE summaries;
|
|
36
|
+
ALTER TABLE summaries_new RENAME TO summaries;
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_summaries_session ON summaries(session_id);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_summaries_project ON summaries(project);
|
|
40
|
+
|
|
41
|
+
-- Recreate FTS content-sync triggers
|
|
42
|
+
CREATE TRIGGER summaries_ai AFTER INSERT ON summaries BEGIN
|
|
43
|
+
INSERT INTO summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
44
|
+
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
45
|
+
END;
|
|
46
|
+
|
|
47
|
+
CREATE TRIGGER summaries_ad AFTER DELETE ON summaries BEGIN
|
|
48
|
+
INSERT INTO summaries_fts(summaries_fts, rowid, request, investigated, learned, completed, next_steps, notes)
|
|
49
|
+
VALUES ('delete', old.id, old.request, old.investigated, old.learned, old.completed, old.next_steps, old.notes);
|
|
50
|
+
END;
|
|
51
|
+
|
|
52
|
+
CREATE TRIGGER summaries_au AFTER UPDATE ON summaries BEGIN
|
|
53
|
+
INSERT INTO summaries_fts(summaries_fts, rowid, request, investigated, learned, completed, next_steps, notes)
|
|
54
|
+
VALUES ('delete', old.id, old.request, old.investigated, old.learned, old.completed, old.next_steps, old.notes);
|
|
55
|
+
INSERT INTO summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
56
|
+
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
57
|
+
END;
|
package/db/migrate.sh
CHANGED
|
@@ -19,8 +19,13 @@ run_migration() {
|
|
|
19
19
|
already_applied=$(sqlite3 "$DB" "SELECT COUNT(*) FROM _migrations WHERE name = '$name';" 2>/dev/null || echo "0")
|
|
20
20
|
|
|
21
21
|
if [ "$already_applied" = "0" ]; then
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# Strip PRAGMAs from migration body (they can't run inside transactions
|
|
23
|
+
# and are already set on every connection via lib/db.sh EAGLE_DB_SETUP)
|
|
24
|
+
local body
|
|
25
|
+
body=$(grep -v -E '^[[:space:]]*PRAGMA ' "$file")
|
|
26
|
+
|
|
27
|
+
# Set connection PRAGMAs, then run migration body + tracking insert atomically
|
|
28
|
+
{ echo "PRAGMA trusted_schema=ON;"; echo "PRAGMA foreign_keys=ON;"; echo "PRAGMA busy_timeout=5000;"; echo "BEGIN;"; echo "$body"; echo "INSERT INTO _migrations (name) VALUES ('$name');"; echo "COMMIT;"; } | sqlite3 "$DB"
|
|
24
29
|
echo " applied: $name"
|
|
25
30
|
fi
|
|
26
31
|
}
|
|
@@ -56,4 +61,7 @@ run_migration "006_claude_plans" "$SCRIPT_DIR/006_claude_plans.sql"
|
|
|
56
61
|
# ─── Migration 007: Claude Code task mirror ──────────────
|
|
57
62
|
run_migration "007_claude_tasks" "$SCRIPT_DIR/007_claude_tasks.sql"
|
|
58
63
|
|
|
64
|
+
# ─── Migration 008: Summary UPSERT (unique session_id) ───
|
|
65
|
+
run_migration "008_summary_upsert" "$SCRIPT_DIR/008_summary_upsert.sql"
|
|
66
|
+
|
|
59
67
|
echo " Eagle Mem database ready: $DB"
|
package/hooks/post-tool-use.sh
CHANGED
|
@@ -60,7 +60,16 @@ case "$tool_name" in
|
|
|
60
60
|
-e 's/(password[= :])[^ ]*/\1[REDACTED]/gi' \
|
|
61
61
|
-e 's/(secret[= :])[^ ]*/\1[REDACTED]/gi' \
|
|
62
62
|
-e 's/(token[= :])[^ ]*/\1[REDACTED]/gi' \
|
|
63
|
-
-e 's/(Authorization: )[^ ]*/\1[REDACTED]/gi'
|
|
63
|
+
-e 's/(Authorization: )[^ ]*/\1[REDACTED]/gi' \
|
|
64
|
+
-e 's/sk_live_[A-Za-z0-9]+/[REDACTED]/g' \
|
|
65
|
+
-e 's/sk_test_[A-Za-z0-9]+/[REDACTED]/g' \
|
|
66
|
+
-e 's/AKIA[A-Z0-9]{16}/[REDACTED]/g' \
|
|
67
|
+
-e 's/ghp_[A-Za-z0-9]{36}/[REDACTED]/g' \
|
|
68
|
+
-e 's/gho_[A-Za-z0-9]{36}/[REDACTED]/g' \
|
|
69
|
+
-e 's/sk-ant-[A-Za-z0-9_-]+/[REDACTED]/g' \
|
|
70
|
+
-e 's/sk-[A-Za-z0-9]{20,}/[REDACTED]/g' \
|
|
71
|
+
-e 's/(ANTHROPIC_API_KEY[= :])[^ ]*/\1[REDACTED]/g' \
|
|
72
|
+
-e 's/(OPENAI_API_KEY[= :])[^ ]*/\1[REDACTED]/g')
|
|
64
73
|
tool_summary="Bash: $cmd"
|
|
65
74
|
;;
|
|
66
75
|
TaskCreate|TaskUpdate)
|
|
@@ -95,15 +104,17 @@ esac
|
|
|
95
104
|
# Intercept TaskCreate/TaskUpdate and capture the resulting JSON files
|
|
96
105
|
case "$tool_name" in
|
|
97
106
|
TaskCreate|TaskUpdate)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
if eagle_validate_session_id "$session_id"; then
|
|
108
|
+
task_dir="$HOME/.claude/tasks/$session_id"
|
|
109
|
+
if [ -d "$task_dir" ]; then
|
|
110
|
+
task_id=$(echo "$input" | jq -r '.tool_input.id // empty')
|
|
111
|
+
if [ -z "$task_id" ]; then
|
|
112
|
+
newest=$(ls -t "$task_dir"/*.json 2>/dev/null | head -1)
|
|
113
|
+
[ -n "$newest" ] && [ -f "$newest" ] && eagle_capture_claude_task "$newest" "$session_id" "$project"
|
|
114
|
+
elif eagle_validate_session_id "$task_id"; then
|
|
115
|
+
task_json="$task_dir/$task_id.json"
|
|
116
|
+
[ -f "$task_json" ] && eagle_capture_claude_task "$task_json" "$session_id" "$project"
|
|
117
|
+
fi
|
|
107
118
|
fi
|
|
108
119
|
fi
|
|
109
120
|
;;
|
package/hooks/session-end.sh
CHANGED
|
@@ -24,13 +24,15 @@ project=$(eagle_project_from_cwd "$cwd")
|
|
|
24
24
|
|
|
25
25
|
# Final sweep: re-capture all task files to catch status changes
|
|
26
26
|
# Claude Code may update task status without triggering PostToolUse
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
if eagle_validate_session_id "$session_id"; then
|
|
28
|
+
task_dir="$HOME/.claude/tasks/$session_id"
|
|
29
|
+
if [ -d "$task_dir" ]; then
|
|
30
|
+
for task_file in "$task_dir"/*.json; do
|
|
31
|
+
[ ! -f "$task_file" ] && continue
|
|
32
|
+
eagle_capture_claude_task "$task_file" "$session_id" "$project"
|
|
33
|
+
done
|
|
34
|
+
eagle_log "INFO" "SessionEnd: re-synced tasks from $task_dir"
|
|
35
|
+
fi
|
|
34
36
|
fi
|
|
35
37
|
|
|
36
38
|
eagle_end_session "$session_id"
|
package/hooks/session-start.sh
CHANGED
|
@@ -30,14 +30,15 @@ eagle_log "INFO" "SessionStart: session=$session_id project=$project source=$sou
|
|
|
30
30
|
|
|
31
31
|
eagle_upsert_session "$session_id" "$project" "$cwd" "$model" "$source_type"
|
|
32
32
|
|
|
33
|
+
# ─── Sweep stuck sessions (older than 4 hours) ─────────────
|
|
34
|
+
eagle_db "UPDATE sessions SET status = 'abandoned'
|
|
35
|
+
WHERE status = 'active'
|
|
36
|
+
AND started_at < strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-4 hours');"
|
|
37
|
+
|
|
33
38
|
# ─── Build context injection ────────────────────────────────
|
|
34
39
|
|
|
35
|
-
eagle_logo="
|
|
36
|
-
|
|
37
|
-
█████╗░░███████║██║░░██╗░██║░░░░░█████╗░░ ██╔████╔██║█████╗░░██╔████╔██║
|
|
38
|
-
██╔══╝░░██╔══██║██║░░╚██╗██║░░░░░██╔══╝░░ ██║╚██╔╝██║██╔══╝░░██║╚██╔╝██║
|
|
39
|
-
███████╗██║░░██║╚██████╔╝███████╗███████╗ ██║░╚═╝░██║███████╗██║░╚═╝░██║
|
|
40
|
-
╚══════╝╚═╝░░╚═╝░╚═════╝░╚══════╝╚══════╝ ╚═╝░░░░░╚═╝╚══════╝╚═╝░░░░░╚═╝"
|
|
40
|
+
eagle_logo="█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
41
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █"
|
|
41
42
|
|
|
42
43
|
context="$eagle_logo
|
|
43
44
|
|
|
@@ -107,8 +108,12 @@ Pending tasks for '$project':
|
|
|
107
108
|
active_task=$(eagle_get_active_task "$project")
|
|
108
109
|
|
|
109
110
|
if [ -z "$active_task" ] && [ -n "$first_pending" ]; then
|
|
110
|
-
# Auto-activate the next pending task
|
|
111
|
-
|
|
111
|
+
# Auto-activate the next pending task (atomic to prevent races
|
|
112
|
+
# when multiple sessions start simultaneously)
|
|
113
|
+
eagle_db "UPDATE tasks SET status = 'active', started_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
114
|
+
WHERE id = $first_pending
|
|
115
|
+
AND status = 'pending'
|
|
116
|
+
AND NOT EXISTS (SELECT 1 FROM tasks WHERE project = '$(eagle_sql_escape "$project")' AND status = 'active');"
|
|
112
117
|
active_task=$(eagle_get_active_task "$project")
|
|
113
118
|
fi
|
|
114
119
|
|
|
@@ -183,12 +188,8 @@ You have persistent memory powered by Eagle Mem. When you recall context from a
|
|
|
183
188
|
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:
|
|
184
189
|
|
|
185
190
|
\`\`\`
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
█████╗░░███████║██║░░██╗░██║░░░░░█████╗░░ ██╔████╔██║█████╗░░██╔████╔██║
|
|
189
|
-
██╔══╝░░██╔══██║██║░░╚██╗██║░░░░░██╔══╝░░ ██║╚██╔╝██║██╔══╝░░██║╚██╔╝██║
|
|
190
|
-
███████╗██║░░██║╚██████╔╝███████╗███████╗ ██║░╚═╝░██║███████╗██║░╚═╝░██║
|
|
191
|
-
╚══════╝╚═╝░░╚═╝░╚═════╝░╚══════╝╚══════╝ ╚═╝░░░░░╚═╝╚══════╝╚═╝░░░░░╚═╝
|
|
191
|
+
█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
192
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
|
|
192
193
|
|
|
193
194
|
Project: <project name>
|
|
194
195
|
Sessions: N recent | Memories: N | Tasks: N pending
|
package/hooks/stop.sh
CHANGED
|
@@ -48,8 +48,8 @@ if [ -n "$transcript_path" ] && [ -f "$transcript_path" ]; then
|
|
|
48
48
|
else "" end
|
|
49
49
|
' "$transcript_path" 2>/dev/null)
|
|
50
50
|
|
|
51
|
-
# Strip <private>...</private> blocks before processing
|
|
52
|
-
text_content=$(echo "$text_content" | sed '/<
|
|
51
|
+
# Strip <private>...</private> blocks before processing (case-insensitive, tolerates attributes/whitespace)
|
|
52
|
+
text_content=$(echo "$text_content" | sed -E '/<[Pp][Rr][Ii][Vv][Aa][Tt][Ee][^>]*>/,/<\/[Pp][Rr][Ii][Vv][Aa][Tt][Ee][[:space:]]*>/d')
|
|
53
53
|
|
|
54
54
|
# Parse <eagle-summary> block
|
|
55
55
|
if [ -n "$text_content" ] && echo "$text_content" | grep -q '<eagle-summary>' 2>/dev/null; then
|
|
@@ -108,23 +108,30 @@ fi
|
|
|
108
108
|
# ─── Heuristic fallback: extract from tool calls ───────────
|
|
109
109
|
|
|
110
110
|
if [ -z "$request" ] && [ -n "$transcript_path" ] && [ -f "$transcript_path" ]; then
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
# Skip heuristic if we already have a summary for this session.
|
|
112
|
+
# Stop fires every turn -- without this guard, each turn creates a duplicate row.
|
|
113
|
+
existing_count=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE session_id = '$(eagle_sql_escape "$session_id")';")
|
|
114
|
+
if [ "${existing_count:-0}" -gt 0 ]; then
|
|
115
|
+
eagle_log "INFO" "Stop: skipping heuristic — summary already exists for session=$session_id (count=$existing_count)"
|
|
116
|
+
else
|
|
117
|
+
eagle_log "INFO" "Stop: no eagle-summary found, using heuristic fallback"
|
|
118
|
+
|
|
119
|
+
# Extract first user prompt as "request"
|
|
120
|
+
request=$(jq -r 'select(.type == "user") | .message.content | if type == "string" then . elif type == "array" then [.[] | select(.type == "text") | .text] | join(" ") else "" end' "$transcript_path" 2>/dev/null | head -1 | cut -c1-500)
|
|
121
|
+
|
|
122
|
+
# Extract files from Read/Write/Edit tool calls
|
|
123
|
+
heuristic_reads=$(jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | select(.name == "Read") | .input.file_path // empty' "$transcript_path" 2>/dev/null | sort -u | head -20)
|
|
124
|
+
heuristic_writes=$(jq -r 'select(.type == "assistant") | .message.content[]? | select(.type == "tool_use") | select(.name == "Write" or .name == "Edit") | .input.file_path // empty' "$transcript_path" 2>/dev/null | sort -u | head -20)
|
|
125
|
+
|
|
126
|
+
if [ -n "$heuristic_reads" ]; then
|
|
127
|
+
files_read=$(echo "$heuristic_reads" | jq -Rsc 'split("\n") | map(select(. != ""))')
|
|
128
|
+
fi
|
|
129
|
+
if [ -n "$heuristic_writes" ]; then
|
|
130
|
+
files_modified=$(echo "$heuristic_writes" | jq -Rsc 'split("\n") | map(select(. != ""))')
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
completed="(auto-captured from tool usage)"
|
|
122
134
|
fi
|
|
123
|
-
if [ -n "$heuristic_writes" ]; then
|
|
124
|
-
files_modified=$(echo "$heuristic_writes" | jq -Rsc 'split("\n") | map(select(. != ""))')
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
completed="(auto-captured from tool usage)"
|
|
128
135
|
fi
|
|
129
136
|
|
|
130
137
|
# ─── Write to database ─────────────────────────────────────
|
|
@@ -134,8 +141,8 @@ if [ -n "$request" ] || [ -n "$completed" ] || [ -n "$learned" ]; then
|
|
|
134
141
|
eagle_log "INFO" "Stop: summary saved for session=$session_id"
|
|
135
142
|
fi
|
|
136
143
|
|
|
137
|
-
# Mark active task as done
|
|
138
|
-
if [ -n "$completed" ]; then
|
|
144
|
+
# Mark active task as done only when Claude explicitly provided a summary
|
|
145
|
+
if [ -n "$summary_block" ] && [ -n "$completed" ]; then
|
|
139
146
|
completed_task_id=$(eagle_complete_active_task "$project")
|
|
140
147
|
if [ -n "$completed_task_id" ]; then
|
|
141
148
|
eagle_log "INFO" "Stop: marked task #$completed_task_id as done"
|
package/lib/common.sh
CHANGED
|
@@ -42,6 +42,13 @@ eagle_fts_sanitize() {
|
|
|
42
42
|
printf '%s' "$1" | sed 's/[*"(){}^~:]/ /g' | sed 's/ */ /g; s/^ //; s/ $//'
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
# Validate a session ID is safe for use in file paths (no traversal).
|
|
46
|
+
# Claude Code session IDs are UUIDs or hex strings — reject anything else.
|
|
47
|
+
eagle_validate_session_id() {
|
|
48
|
+
local sid="$1"
|
|
49
|
+
[[ "$sid" =~ ^[A-Za-z0-9_-]+$ ]]
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
eagle_read_stdin() {
|
|
46
53
|
local input=""
|
|
47
54
|
if [ ! -t 0 ]; then
|
package/lib/db.sh
CHANGED
|
@@ -14,15 +14,15 @@ PRAGMA trusted_schema=ON;
|
|
|
14
14
|
.output stdout"
|
|
15
15
|
|
|
16
16
|
eagle_db() {
|
|
17
|
-
{ echo "$EAGLE_DB_SETUP"; echo "$*"; } | sqlite3 "$EAGLE_MEM_DB" 2
|
|
17
|
+
{ echo "$EAGLE_DB_SETUP"; echo "$*"; } | sqlite3 "$EAGLE_MEM_DB" 2>>"$EAGLE_MEM_LOG"
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
eagle_db_pipe() {
|
|
21
|
-
{ echo "$EAGLE_DB_SETUP"; cat; } | sqlite3 "$EAGLE_MEM_DB" 2
|
|
21
|
+
{ echo "$EAGLE_DB_SETUP"; cat; } | sqlite3 "$EAGLE_MEM_DB" 2>>"$EAGLE_MEM_LOG"
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
eagle_db_json() {
|
|
25
|
-
{ echo "$EAGLE_DB_SETUP"; echo ".mode json"; echo "$*"; } | sqlite3 "$EAGLE_MEM_DB" 2
|
|
25
|
+
{ echo "$EAGLE_DB_SETUP"; echo ".mode json"; echo "$*"; } | sqlite3 "$EAGLE_MEM_DB" 2>>"$EAGLE_MEM_LOG"
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
eagle_ensure_db() {
|
|
@@ -78,7 +78,7 @@ eagle_insert_summary() {
|
|
|
78
78
|
local notes; notes=$(eagle_sql_escape "${10:-}")
|
|
79
79
|
|
|
80
80
|
eagle_db_pipe <<SQL
|
|
81
|
-
INSERT INTO summaries (session_id, project, request, investigated, learned, completed, next_steps, files_read, files_modified, notes)
|
|
81
|
+
INSERT OR REPLACE INTO summaries (session_id, project, request, investigated, learned, completed, next_steps, files_read, files_modified, notes)
|
|
82
82
|
VALUES (
|
|
83
83
|
'$session_id',
|
|
84
84
|
'$project',
|
|
@@ -145,19 +145,6 @@ eagle_get_next_task() {
|
|
|
145
145
|
LIMIT 1;"
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
eagle_get_active_files() {
|
|
149
|
-
local project; project=$(eagle_sql_escape "$1")
|
|
150
|
-
local limit; limit=$(eagle_sql_int "${2:-20}")
|
|
151
|
-
|
|
152
|
-
eagle_db "SELECT json_each.value
|
|
153
|
-
FROM observations, json_each(observations.files_modified)
|
|
154
|
-
WHERE observations.project = '$project'
|
|
155
|
-
AND observations.created_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-30 days')
|
|
156
|
-
GROUP BY json_each.value
|
|
157
|
-
ORDER BY MAX(observations.created_at) DESC
|
|
158
|
-
LIMIT $limit;"
|
|
159
|
-
}
|
|
160
|
-
|
|
161
148
|
eagle_observation_exists() {
|
|
162
149
|
local session_id; session_id=$(eagle_sql_escape "$1")
|
|
163
150
|
local tool_name; tool_name=$(eagle_sql_escape "$2")
|
|
@@ -329,13 +316,6 @@ eagle_list_claude_memories() {
|
|
|
329
316
|
LIMIT $limit;"
|
|
330
317
|
}
|
|
331
318
|
|
|
332
|
-
eagle_get_claude_memory() {
|
|
333
|
-
local file_path; file_path=$(eagle_sql_escape "$1")
|
|
334
|
-
eagle_db "SELECT memory_name, memory_type, description, content, file_path, updated_at, origin_session_id
|
|
335
|
-
FROM claude_memories
|
|
336
|
-
WHERE file_path = '$file_path';"
|
|
337
|
-
}
|
|
338
|
-
|
|
339
319
|
eagle_capture_claude_plan() {
|
|
340
320
|
local file_path="$1"
|
|
341
321
|
local session_id="${2:-}"
|
|
@@ -546,16 +526,25 @@ eagle_backfill_projects() {
|
|
|
546
526
|
sid_sql=$(eagle_sql_escape "$sid")
|
|
547
527
|
proj_sql=$(eagle_sql_escape "$project")
|
|
548
528
|
|
|
549
|
-
local
|
|
550
|
-
|
|
529
|
+
local ch
|
|
530
|
+
ch=$(eagle_db "UPDATE sessions SET project = '$proj_sql' WHERE id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
531
|
+
SELECT changes();")
|
|
532
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
533
|
+
ch=$(eagle_db "UPDATE claude_tasks SET project = '$proj_sql' WHERE source_session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
534
|
+
SELECT changes();")
|
|
535
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
536
|
+
ch=$(eagle_db "UPDATE claude_memories SET project = '$proj_sql' WHERE origin_session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
537
|
+
SELECT changes();")
|
|
538
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
539
|
+
ch=$(eagle_db "UPDATE claude_plans SET project = '$proj_sql' WHERE origin_session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
540
|
+
SELECT changes();")
|
|
541
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
542
|
+
ch=$(eagle_db "UPDATE summaries SET project = '$proj_sql' WHERE session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
551
543
|
SELECT changes();")
|
|
552
|
-
|
|
544
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
545
|
+
ch=$(eagle_db "UPDATE observations SET project = '$proj_sql' WHERE session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');
|
|
553
546
|
SELECT changes();")
|
|
554
|
-
[ "${
|
|
555
|
-
eagle_db "UPDATE claude_memories SET project = '$proj_sql' WHERE origin_session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');"
|
|
556
|
-
eagle_db "UPDATE claude_plans SET project = '$proj_sql' WHERE origin_session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');"
|
|
557
|
-
eagle_db "UPDATE summaries SET project = '$proj_sql' WHERE session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');"
|
|
558
|
-
eagle_db "UPDATE observations SET project = '$proj_sql' WHERE session_id = '$sid_sql' AND (project = '' OR project != '$proj_sql');"
|
|
547
|
+
[ "${ch:-0}" -gt 0 ] && updated=$((updated + ch))
|
|
559
548
|
done <<< "$map"
|
|
560
549
|
|
|
561
550
|
echo "$updated"
|
package/package.json
CHANGED
package/scripts/help.sh
CHANGED
|
@@ -56,9 +56,13 @@ echo -e " ${DOT} Mirrors Claude Code memories, plans, and tasks into FTS5-sea
|
|
|
56
56
|
echo -e " ${DOT} Provides task management for complex multi-step work"
|
|
57
57
|
echo ""
|
|
58
58
|
echo -e " ${BOLD}Skills${RESET} ${DIM}(available inside Claude Code):${RESET}"
|
|
59
|
-
echo -e " ${CYAN}/eagle-mem-search${RESET}
|
|
60
|
-
echo -e " ${CYAN}/eagle-mem-tasks${RESET}
|
|
61
|
-
echo -e " ${CYAN}/eagle-mem-overview${RESET}
|
|
59
|
+
echo -e " ${CYAN}/eagle-mem-search${RESET} Search past sessions and observations"
|
|
60
|
+
echo -e " ${CYAN}/eagle-mem-tasks${RESET} Break work into tracked subtasks"
|
|
61
|
+
echo -e " ${CYAN}/eagle-mem-overview${RESET} Generate a persistent project summary"
|
|
62
|
+
echo -e " ${CYAN}/eagle-mem-index${RESET} Index source files for code search"
|
|
63
|
+
echo -e " ${CYAN}/eagle-mem-scan${RESET} Scan and analyze a project"
|
|
64
|
+
echo -e " ${CYAN}/eagle-mem-memories${RESET} Browse Claude Code memories, plans, tasks"
|
|
65
|
+
echo -e " ${CYAN}/eagle-mem-prune${RESET} Clean up old observations and chunks"
|
|
62
66
|
echo ""
|
|
63
67
|
echo -e " ${DIM}Skills use these CLI commands under the hood — no raw SQL.${RESET}"
|
|
64
68
|
echo ""
|
package/scripts/index.sh
CHANGED
|
@@ -151,11 +151,13 @@ while IFS= read -r file; do
|
|
|
151
151
|
file_sql=$(eagle_sql_escape "$file")
|
|
152
152
|
lang_sql=$(eagle_sql_escape "$lang")
|
|
153
153
|
|
|
154
|
-
eagle_db "DELETE FROM code_chunks WHERE project = '$project_sql' AND file_path = '$file_sql';"
|
|
155
|
-
|
|
156
154
|
total_lines=$(wc -l < "$full_path" 2>/dev/null | tr -d ' ')
|
|
157
155
|
[ "$total_lines" -eq 0 ] && continue
|
|
158
156
|
|
|
157
|
+
# Build all INSERTs for this file, then run as a single atomic transaction
|
|
158
|
+
txn_sql="BEGIN;
|
|
159
|
+
DELETE FROM code_chunks WHERE project = '$project_sql' AND file_path = '$file_sql';"
|
|
160
|
+
|
|
159
161
|
start=1
|
|
160
162
|
while [ "$start" -le "$total_lines" ]; do
|
|
161
163
|
end=$((start + CHUNK_SIZE - 1))
|
|
@@ -164,13 +166,19 @@ while IFS= read -r file; do
|
|
|
164
166
|
content=$(sed -n "${start},${end}p" "$full_path")
|
|
165
167
|
content_sql=$(eagle_sql_escape "$content")
|
|
166
168
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
txn_sql+="
|
|
170
|
+
INSERT INTO code_chunks (project, file_path, language, start_line, end_line, content, mtime)
|
|
171
|
+
VALUES ('$project_sql', '$file_sql', '$lang_sql', $start, $end, '$content_sql', $current_mtime);"
|
|
169
172
|
|
|
170
173
|
chunk_count=$((chunk_count + 1))
|
|
171
174
|
start=$((end + 1))
|
|
172
175
|
done
|
|
173
176
|
|
|
177
|
+
txn_sql+="
|
|
178
|
+
COMMIT;"
|
|
179
|
+
|
|
180
|
+
eagle_db_pipe <<< "$txn_sql"
|
|
181
|
+
|
|
174
182
|
file_count=$((file_count + 1))
|
|
175
183
|
|
|
176
184
|
if [ $((file_count % 10)) -eq 0 ]; then
|
package/scripts/install.sh
CHANGED
|
@@ -135,15 +135,17 @@ echo ""
|
|
|
135
135
|
echo -e " ${BOLD}Installing Eagle Mem...${RESET}"
|
|
136
136
|
echo ""
|
|
137
137
|
|
|
138
|
-
mkdir -p "$EAGLE_MEM_DIR"/{hooks,lib,db}
|
|
138
|
+
mkdir -p "$EAGLE_MEM_DIR"/{hooks,lib,db,scripts}
|
|
139
139
|
|
|
140
140
|
cp "$PACKAGE_DIR"/hooks/*.sh "$EAGLE_MEM_DIR/hooks/"
|
|
141
141
|
cp "$PACKAGE_DIR"/lib/*.sh "$EAGLE_MEM_DIR/lib/"
|
|
142
142
|
cp "$PACKAGE_DIR"/db/*.sh "$EAGLE_MEM_DIR/db/"
|
|
143
143
|
cp "$PACKAGE_DIR"/db/*.sql "$EAGLE_MEM_DIR/db/"
|
|
144
|
+
cp "$PACKAGE_DIR"/scripts/statusline-em.sh "$EAGLE_MEM_DIR/scripts/" 2>/dev/null
|
|
144
145
|
|
|
145
146
|
chmod +x "$EAGLE_MEM_DIR"/hooks/*.sh
|
|
146
147
|
chmod +x "$EAGLE_MEM_DIR"/db/migrate.sh
|
|
148
|
+
chmod +x "$EAGLE_MEM_DIR"/scripts/*.sh 2>/dev/null
|
|
147
149
|
|
|
148
150
|
eagle_ok "Files copied to $EAGLE_MEM_DIR"
|
|
149
151
|
|
|
@@ -216,6 +218,53 @@ if [ -d "$PACKAGE_DIR/skills" ]; then
|
|
|
216
218
|
done
|
|
217
219
|
fi
|
|
218
220
|
|
|
221
|
+
# ─── Statusline integration ───────────────────────────────
|
|
222
|
+
|
|
223
|
+
EM_STATUSLINE="$EAGLE_MEM_DIR/scripts/statusline-em.sh"
|
|
224
|
+
existing_sl=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null)
|
|
225
|
+
|
|
226
|
+
if [ -z "$existing_sl" ]; then
|
|
227
|
+
# No statusline configured — set up a minimal one that shows Eagle Mem
|
|
228
|
+
wrapper="$EAGLE_MEM_DIR/scripts/statusline-wrapper.sh"
|
|
229
|
+
cat > "$wrapper" << 'WRAPPER'
|
|
230
|
+
#!/usr/bin/env bash
|
|
231
|
+
input=$(cat)
|
|
232
|
+
project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // ""' 2>/dev/null)
|
|
233
|
+
source "$HOME/.eagle-mem/scripts/statusline-em.sh"
|
|
234
|
+
eagle_mem_statusline "$project_dir"
|
|
235
|
+
WRAPPER
|
|
236
|
+
chmod +x "$wrapper"
|
|
237
|
+
tmp=$(mktemp)
|
|
238
|
+
jq --arg cmd "sh $wrapper" '.statusLine = {"type": "command", "command": $cmd, "refreshInterval": 30}' "$SETTINGS" > "$tmp" && mv "$tmp" "$SETTINGS"
|
|
239
|
+
eagle_ok "Statusline ${DIM}(new — Eagle Mem indicator)${RESET}"
|
|
240
|
+
elif echo "$existing_sl" | grep -q "eagle-mem"; then
|
|
241
|
+
eagle_ok "Statusline ${DIM}(already has Eagle Mem)${RESET}"
|
|
242
|
+
else
|
|
243
|
+
# Existing statusline — check if it's a .sh file we can patch
|
|
244
|
+
sl_file=$(echo "$existing_sl" | sed 's/^sh //')
|
|
245
|
+
if [ -f "$sl_file" ] && ! grep -q "eagle-mem" "$sl_file"; then
|
|
246
|
+
eagle_dim " Statusline detected: $sl_file"
|
|
247
|
+
eagle_dim " To add Eagle Mem, add this snippet before your ASSEMBLE section:"
|
|
248
|
+
echo ""
|
|
249
|
+
eagle_dim " # ── EAGLE MEM ──"
|
|
250
|
+
eagle_dim " em_section=\"\""
|
|
251
|
+
eagle_dim " em_db=\"\$HOME/.eagle-mem/memory.db\""
|
|
252
|
+
eagle_dim " if [ -f \"\$em_db\" ]; then"
|
|
253
|
+
eagle_dim " em_proj=\$(basename \"\$project_dir\" | sed \"s/'/''/g\")"
|
|
254
|
+
eagle_dim " em_cnt=\$(echo \".headers off"
|
|
255
|
+
eagle_dim " SELECT COUNT(*) FROM sessions WHERE project = '\${em_proj}';\" | sqlite3 \"\$em_db\" 2>/dev/null | tr -d '[:space:]')"
|
|
256
|
+
eagle_dim " em_mem=\$(echo \".headers off"
|
|
257
|
+
eagle_dim " SELECT COUNT(*) FROM claude_memories WHERE project = '\${em_proj}';\" | sqlite3 \"\$em_db\" 2>/dev/null | tr -d '[:space:]')"
|
|
258
|
+
eagle_dim " em_cnt=\${em_cnt:-0}; em_mem=\${em_mem:-0}"
|
|
259
|
+
eagle_dim " em_section=\$(printf \"%bEagle Mem%b %b%s%b ses %b%s%b mem\" \"\$CYAN\" \"\$R\" \"\$WHT\" \"\$em_cnt\" \"\$DIM\" \"\$WHT\" \"\$em_mem\" \"\$R\")"
|
|
260
|
+
eagle_dim " fi"
|
|
261
|
+
echo ""
|
|
262
|
+
eagle_ok "Statusline ${DIM}(manual patch needed — instructions above)${RESET}"
|
|
263
|
+
else
|
|
264
|
+
eagle_ok "Statusline ${DIM}(already has Eagle Mem)${RESET}"
|
|
265
|
+
fi
|
|
266
|
+
fi
|
|
267
|
+
|
|
219
268
|
# ─── Summary ───────────────────────────────────────────────
|
|
220
269
|
|
|
221
270
|
eagle_footer "Eagle Mem installed successfully."
|
package/scripts/overview.sh
CHANGED
|
@@ -23,27 +23,29 @@ project=""
|
|
|
23
23
|
json_output=false
|
|
24
24
|
args=()
|
|
25
25
|
|
|
26
|
+
show_help() {
|
|
27
|
+
echo -e " ${BOLD}eagle-mem overview${RESET} — Manage project overviews"
|
|
28
|
+
echo ""
|
|
29
|
+
echo -e " ${BOLD}Usage:${RESET}"
|
|
30
|
+
echo -e " eagle-mem overview ${DIM}# show current overview${RESET}"
|
|
31
|
+
echo -e " eagle-mem overview ${CYAN}set${RESET} <text> ${DIM}# set/update overview${RESET}"
|
|
32
|
+
echo -e " eagle-mem overview ${CYAN}delete${RESET} ${DIM}# delete overview${RESET}"
|
|
33
|
+
echo -e " eagle-mem overview ${CYAN}list${RESET} ${DIM}# list all overviews${RESET}"
|
|
34
|
+
echo ""
|
|
35
|
+
echo -e " ${BOLD}Options:${RESET}"
|
|
36
|
+
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
37
|
+
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
38
|
+
echo ""
|
|
39
|
+
echo -e " ${BOLD}Tip:${RESET} Use ${CYAN}eagle-mem scan${RESET} to auto-generate an overview from code."
|
|
40
|
+
echo ""
|
|
41
|
+
exit 0
|
|
42
|
+
}
|
|
43
|
+
|
|
26
44
|
while [ $# -gt 0 ]; do
|
|
27
45
|
case "$1" in
|
|
28
46
|
--project|-p) project="$2"; shift 2 ;;
|
|
29
47
|
--json|-j) json_output=true; shift ;;
|
|
30
|
-
--help|-h)
|
|
31
|
-
echo -e " ${BOLD}eagle-mem overview${RESET} — Manage project overviews"
|
|
32
|
-
echo ""
|
|
33
|
-
echo -e " ${BOLD}Usage:${RESET}"
|
|
34
|
-
echo -e " eagle-mem overview ${DIM}# show current overview${RESET}"
|
|
35
|
-
echo -e " eagle-mem overview ${CYAN}set${RESET} <text> ${DIM}# set/update overview${RESET}"
|
|
36
|
-
echo -e " eagle-mem overview ${CYAN}delete${RESET} ${DIM}# delete overview${RESET}"
|
|
37
|
-
echo -e " eagle-mem overview ${CYAN}list${RESET} ${DIM}# list all overviews${RESET}"
|
|
38
|
-
echo ""
|
|
39
|
-
echo -e " ${BOLD}Options:${RESET}"
|
|
40
|
-
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
41
|
-
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
42
|
-
echo ""
|
|
43
|
-
echo -e " ${BOLD}Tip:${RESET} Use ${CYAN}eagle-mem scan${RESET} to auto-generate an overview from code."
|
|
44
|
-
echo ""
|
|
45
|
-
exit 0
|
|
46
|
-
;;
|
|
48
|
+
--help|-h) show_help ;;
|
|
47
49
|
*) args+=("$1"); shift ;;
|
|
48
50
|
esac
|
|
49
51
|
done
|
|
@@ -145,23 +147,7 @@ case "$action" in
|
|
|
145
147
|
set|update) overview_set ;;
|
|
146
148
|
delete|rm) overview_delete ;;
|
|
147
149
|
list|ls) overview_list ;;
|
|
148
|
-
--help|-h)
|
|
149
|
-
echo -e " ${BOLD}eagle-mem overview${RESET} — Manage project overviews"
|
|
150
|
-
echo ""
|
|
151
|
-
echo -e " ${BOLD}Usage:${RESET}"
|
|
152
|
-
echo -e " eagle-mem overview ${DIM}# show current overview${RESET}"
|
|
153
|
-
echo -e " eagle-mem overview ${CYAN}set${RESET} <text> ${DIM}# set/update overview${RESET}"
|
|
154
|
-
echo -e " eagle-mem overview ${CYAN}delete${RESET} ${DIM}# delete overview${RESET}"
|
|
155
|
-
echo -e " eagle-mem overview ${CYAN}list${RESET} ${DIM}# list all overviews${RESET}"
|
|
156
|
-
echo ""
|
|
157
|
-
echo -e " ${BOLD}Options:${RESET}"
|
|
158
|
-
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
159
|
-
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
160
|
-
echo ""
|
|
161
|
-
echo -e " ${BOLD}Tip:${RESET} Use ${CYAN}eagle-mem scan${RESET} to auto-generate an overview from code."
|
|
162
|
-
echo ""
|
|
163
|
-
exit 0
|
|
164
|
-
;;
|
|
150
|
+
--help|-h) show_help ;;
|
|
165
151
|
*)
|
|
166
152
|
eagle_err "Unknown action: $action"
|
|
167
153
|
eagle_dim " Run 'eagle-mem overview --help' for options"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Eagle Mem statusline section — outputs a single formatted section
|
|
3
|
+
# Called by the user's statusline command to append Eagle Mem stats.
|
|
4
|
+
# Usage: source this script OR call eagle_mem_statusline "$project_dir"
|
|
5
|
+
|
|
6
|
+
eagle_mem_statusline() {
|
|
7
|
+
local project_dir="${1:-}"
|
|
8
|
+
local em_db="$HOME/.eagle-mem/memory.db"
|
|
9
|
+
[ -f "$em_db" ] || return
|
|
10
|
+
|
|
11
|
+
local proj
|
|
12
|
+
proj=$(basename "$project_dir")
|
|
13
|
+
[ -z "$proj" ] && return
|
|
14
|
+
|
|
15
|
+
# Escape single quotes for safe SQL interpolation
|
|
16
|
+
proj=$(printf '%s' "$proj" | sed "s/'/''/g")
|
|
17
|
+
|
|
18
|
+
local cnt mem
|
|
19
|
+
cnt=$(echo ".headers off
|
|
20
|
+
SELECT COUNT(*) FROM sessions WHERE project = '${proj}';" | sqlite3 "$em_db" 2>/dev/null | tr -d '[:space:]')
|
|
21
|
+
mem=$(echo ".headers off
|
|
22
|
+
SELECT COUNT(*) FROM claude_memories WHERE project = '${proj}';" | sqlite3 "$em_db" 2>/dev/null | tr -d '[:space:]')
|
|
23
|
+
cnt=${cnt:-0}; mem=${mem:-0}
|
|
24
|
+
|
|
25
|
+
local R='\033[0m' CYAN='\033[96m' WHT='\033[97m' DIM='\033[2m'
|
|
26
|
+
printf "%bEagle Mem%b %b%s%b ses %b%s%b mem" "$CYAN" "$R" "$WHT" "$cnt" "$DIM" "$WHT" "$mem" "$R"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# When run directly, read project_dir from stdin JSON (statusline format)
|
|
30
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
31
|
+
input=$(cat)
|
|
32
|
+
project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // ""' 2>/dev/null)
|
|
33
|
+
eagle_mem_statusline "$project_dir"
|
|
34
|
+
fi
|
package/scripts/style.sh
CHANGED
|
@@ -32,10 +32,6 @@ eagle_warn() { echo -e " ${YELLOW}!${RESET} $1"; }
|
|
|
32
32
|
eagle_err() { echo -e " ${RED}✗${RESET} $1" >&2; }
|
|
33
33
|
eagle_dim() { echo -e " ${DIM}$1${RESET}"; }
|
|
34
34
|
|
|
35
|
-
eagle_step() {
|
|
36
|
-
echo -e " ${CYAN}$1${RESET} $2"
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
eagle_kv() {
|
|
40
36
|
printf " ${DIM}%-12s${RESET} %s\n" "$1" "$2"
|
|
41
37
|
}
|
|
@@ -46,28 +42,11 @@ eagle_footer() {
|
|
|
46
42
|
echo ""
|
|
47
43
|
}
|
|
48
44
|
|
|
49
|
-
eagle_art() {
|
|
50
|
-
cat << 'ART'
|
|
51
|
-
.~~~~-.
|
|
52
|
-
/ ,__`)
|
|
53
|
-
| \o/|'-.
|
|
54
|
-
| / ,\
|
|
55
|
-
| ('--./
|
|
56
|
-
/ \
|
|
57
|
-
/ , , , \
|
|
58
|
-
`--'--'--'--'
|
|
59
|
-
ART
|
|
60
|
-
}
|
|
61
|
-
|
|
62
45
|
eagle_banner() {
|
|
63
46
|
echo -e "${CYAN}"
|
|
64
47
|
cat << 'BANNER'
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
█████╗░░███████║██║░░██╗░██║░░░░░█████╗░░ ██╔████╔██║█████╗░░██╔████╔██║
|
|
68
|
-
██╔══╝░░██╔══██║██║░░╚██╗██║░░░░░██╔══╝░░ ██║╚██╔╝██║██╔══╝░░██║╚██╔╝██║
|
|
69
|
-
███████╗██║░░██║╚██████╔╝███████╗███████╗ ██║░╚═╝░██║███████╗██║░╚═╝░██║
|
|
70
|
-
╚══════╝╚═╝░░╚═╝░╚═════╝░╚══════╝╚══════╝ ╚═╝░░░░░╚═╝╚══════╝╚═╝░░░░░╚═╝
|
|
48
|
+
█▀▀ ▄▀█ █▀▀ █ █▀▀ █▀▄▀█ █▀▀ █▀▄▀█
|
|
49
|
+
██▄ █▀█ █▄█ █▄▄ ██▄ █ ▀ █ ██▄ █ ▀ █
|
|
71
50
|
BANNER
|
|
72
51
|
echo -e "${RESET}"
|
|
73
52
|
}
|
package/scripts/tasks.sh
CHANGED
|
@@ -24,28 +24,31 @@ json_output=false
|
|
|
24
24
|
|
|
25
25
|
# Extract global options from remaining args
|
|
26
26
|
args=()
|
|
27
|
+
|
|
28
|
+
show_help() {
|
|
29
|
+
echo -e " ${BOLD}eagle-mem tasks${RESET} — Manage tracked tasks"
|
|
30
|
+
echo ""
|
|
31
|
+
echo -e " ${BOLD}Usage:${RESET}"
|
|
32
|
+
echo -e " eagle-mem tasks ${DIM}# list pending tasks${RESET}"
|
|
33
|
+
echo -e " eagle-mem tasks ${CYAN}list${RESET} ${DIM}# list all tasks${RESET}"
|
|
34
|
+
echo -e " eagle-mem tasks ${CYAN}add${RESET} <title> [instructions] ${DIM}# add a task${RESET}"
|
|
35
|
+
echo -e " eagle-mem tasks ${CYAN}done${RESET} <id> ${DIM}# mark task complete${RESET}"
|
|
36
|
+
echo -e " eagle-mem tasks ${CYAN}block${RESET} <id> ${DIM}# mark task blocked${RESET}"
|
|
37
|
+
echo -e " eagle-mem tasks ${CYAN}context${RESET} <id> <snapshot> ${DIM}# set task context${RESET}"
|
|
38
|
+
echo -e " eagle-mem tasks ${CYAN}clear${RESET} ${DIM}# remove all done tasks${RESET}"
|
|
39
|
+
echo ""
|
|
40
|
+
echo -e " ${BOLD}Options:${RESET}"
|
|
41
|
+
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
42
|
+
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
43
|
+
echo ""
|
|
44
|
+
exit 0
|
|
45
|
+
}
|
|
46
|
+
|
|
27
47
|
while [ $# -gt 0 ]; do
|
|
28
48
|
case "$1" in
|
|
29
49
|
--project|-p) project="$2"; shift 2 ;;
|
|
30
50
|
--json|-j) json_output=true; shift ;;
|
|
31
|
-
--help|-h)
|
|
32
|
-
echo -e " ${BOLD}eagle-mem tasks${RESET} — Manage tracked tasks"
|
|
33
|
-
echo ""
|
|
34
|
-
echo -e " ${BOLD}Usage:${RESET}"
|
|
35
|
-
echo -e " eagle-mem tasks ${DIM}# list pending tasks${RESET}"
|
|
36
|
-
echo -e " eagle-mem tasks ${CYAN}list${RESET} ${DIM}# list all tasks${RESET}"
|
|
37
|
-
echo -e " eagle-mem tasks ${CYAN}add${RESET} <title> [instructions] ${DIM}# add a task${RESET}"
|
|
38
|
-
echo -e " eagle-mem tasks ${CYAN}done${RESET} <id> ${DIM}# mark task complete${RESET}"
|
|
39
|
-
echo -e " eagle-mem tasks ${CYAN}block${RESET} <id> ${DIM}# mark task blocked${RESET}"
|
|
40
|
-
echo -e " eagle-mem tasks ${CYAN}context${RESET} <id> <snapshot> ${DIM}# set task context${RESET}"
|
|
41
|
-
echo -e " eagle-mem tasks ${CYAN}clear${RESET} ${DIM}# remove all done tasks${RESET}"
|
|
42
|
-
echo ""
|
|
43
|
-
echo -e " ${BOLD}Options:${RESET}"
|
|
44
|
-
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
45
|
-
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
46
|
-
echo ""
|
|
47
|
-
exit 0
|
|
48
|
-
;;
|
|
51
|
+
--help|-h) show_help ;;
|
|
49
52
|
*) args+=("$1"); shift ;;
|
|
50
53
|
esac
|
|
51
54
|
done
|
|
@@ -265,24 +268,7 @@ case "$action" in
|
|
|
265
268
|
block) tasks_block ;;
|
|
266
269
|
context) tasks_context ;;
|
|
267
270
|
clear) tasks_clear ;;
|
|
268
|
-
--help|-h)
|
|
269
|
-
echo -e " ${BOLD}eagle-mem tasks${RESET} — Manage tracked tasks"
|
|
270
|
-
echo ""
|
|
271
|
-
echo -e " ${BOLD}Usage:${RESET}"
|
|
272
|
-
echo -e " eagle-mem tasks ${DIM}# list pending tasks${RESET}"
|
|
273
|
-
echo -e " eagle-mem tasks ${CYAN}list${RESET} ${DIM}# list all tasks${RESET}"
|
|
274
|
-
echo -e " eagle-mem tasks ${CYAN}add${RESET} <title> [instructions] ${DIM}# add a task${RESET}"
|
|
275
|
-
echo -e " eagle-mem tasks ${CYAN}done${RESET} <id> ${DIM}# mark task complete${RESET}"
|
|
276
|
-
echo -e " eagle-mem tasks ${CYAN}block${RESET} <id> ${DIM}# mark task blocked${RESET}"
|
|
277
|
-
echo -e " eagle-mem tasks ${CYAN}context${RESET} <id> <snapshot> ${DIM}# set task context${RESET}"
|
|
278
|
-
echo -e " eagle-mem tasks ${CYAN}clear${RESET} ${DIM}# remove all done tasks${RESET}"
|
|
279
|
-
echo ""
|
|
280
|
-
echo -e " ${BOLD}Options:${RESET}"
|
|
281
|
-
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
282
|
-
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
283
|
-
echo ""
|
|
284
|
-
exit 0
|
|
285
|
-
;;
|
|
271
|
+
--help|-h) show_help ;;
|
|
286
272
|
*)
|
|
287
273
|
eagle_err "Unknown action: $action"
|
|
288
274
|
eagle_dim " Run 'eagle-mem tasks --help' for options"
|
package/scripts/uninstall.sh
CHANGED
|
@@ -36,15 +36,10 @@ fi
|
|
|
36
36
|
# ─── Remove skill symlinks ────────────────────────────────
|
|
37
37
|
|
|
38
38
|
if [ -d "$EAGLE_SKILLS_DIR" ]; then
|
|
39
|
-
for
|
|
40
|
-
target
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
eagle_ok "Skill removed: $skill"
|
|
44
|
-
elif [ -d "$target" ]; then
|
|
45
|
-
rm -rf "$target"
|
|
46
|
-
eagle_ok "Skill removed: $skill"
|
|
47
|
-
fi
|
|
39
|
+
for target in "$EAGLE_SKILLS_DIR"/eagle-mem-*; do
|
|
40
|
+
[ -L "$target" ] || [ -d "$target" ] || continue
|
|
41
|
+
rm -rf "$target"
|
|
42
|
+
eagle_ok "Skill removed: $(basename "$target")"
|
|
48
43
|
done
|
|
49
44
|
fi
|
|
50
45
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eagle-mem-index
|
|
3
|
+
description: >
|
|
4
|
+
Index source files into FTS5-searchable chunks for code-level search. Use when: 'eagle index',
|
|
5
|
+
'index this project', 'index codebase', 'eagle mem index', 'make code searchable',
|
|
6
|
+
'update code index'. Uses the eagle-mem CLI.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Eagle Mem — Index
|
|
10
|
+
|
|
11
|
+
Chunk and index source files into Eagle Mem's FTS5 search index. Enables code-level search across sessions.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
- Walks the project directory for source files
|
|
16
|
+
- Splits each file into chunks (default 80 lines)
|
|
17
|
+
- Stores chunks in the `code_chunks` table with FTS5 indexing
|
|
18
|
+
- Incremental: only re-indexes files modified since the last run (via mtime)
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
### Index current project
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
eagle-mem index .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Index a specific directory
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
eagle-mem index /path/to/project
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## When to use
|
|
35
|
+
|
|
36
|
+
- After initial project setup to make code searchable
|
|
37
|
+
- After pulling significant changes
|
|
38
|
+
- When `/eagle-mem-search` isn't finding code you know exists
|
|
39
|
+
|
|
40
|
+
## How it integrates
|
|
41
|
+
|
|
42
|
+
Once indexed, the UserPromptSubmit hook can surface relevant code chunks when you ask questions. The `/eagle-mem-search` skill also searches indexed code.
|
|
43
|
+
|
|
44
|
+
## Notes
|
|
45
|
+
|
|
46
|
+
- Respects .gitignore — only indexes tracked/untracked source files
|
|
47
|
+
- Skips binary files and files over 1MB
|
|
48
|
+
- Chunk size is configurable via `EAGLE_MEM_CHUNK_SIZE` env var (default: 80 lines)
|
|
49
|
+
- Re-running is safe — unchanged files are skipped automatically
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eagle-mem-memories
|
|
3
|
+
description: >
|
|
4
|
+
View and sync Claude Code auto-memories, plans, and tasks mirrored in Eagle Mem. Use when:
|
|
5
|
+
'eagle memories', 'show memories', 'list memories', 'sync memories', 'eagle mem memories',
|
|
6
|
+
'what does claude remember', 'show plans', 'show tasks'. Uses the eagle-mem CLI.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Eagle Mem — Memories
|
|
10
|
+
|
|
11
|
+
View, search, and sync Claude Code's auto-memories, plans, and tasks that are mirrored into Eagle Mem's SQLite + FTS5 database.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### List mirrored memories
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
eagle-mem memories
|
|
19
|
+
eagle-mem memories list
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Search memories
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
eagle-mem memories search "auth middleware"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Show a specific memory
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
eagle-mem memories show <name>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### List mirrored plans
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
eagle-mem memories plans
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### List mirrored tasks
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
eagle-mem memories tasks
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Sync all from Claude Code
|
|
47
|
+
|
|
48
|
+
Backfill all memories, plans, and tasks from Claude Code's filesystem into Eagle Mem:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
eagle-mem memories sync
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Options
|
|
55
|
+
|
|
56
|
+
| Flag | Description |
|
|
57
|
+
|------|-------------|
|
|
58
|
+
| `-p, --project <name>` | Target a specific project (default: current directory) |
|
|
59
|
+
| `-n, --limit <N>` | Max results (default: 20) |
|
|
60
|
+
| `-j, --json` | Output as JSON |
|
|
61
|
+
|
|
62
|
+
## How it works
|
|
63
|
+
|
|
64
|
+
Eagle Mem automatically mirrors Claude Code writes via the PostToolUse hook:
|
|
65
|
+
- **Memories** from `~/.claude/projects/*/memory/*.md`
|
|
66
|
+
- **Plans** from `~/.claude/plans/*.md`
|
|
67
|
+
- **Tasks** from Claude Code's TaskCreate/TaskUpdate calls
|
|
68
|
+
|
|
69
|
+
The `sync` command does a full backfill for anything the hooks missed.
|
|
70
|
+
|
|
71
|
+
## When to use
|
|
72
|
+
|
|
73
|
+
- To check what Claude Code has auto-saved about this project
|
|
74
|
+
- To search across memories from multiple projects
|
|
75
|
+
- After installing Eagle Mem on an existing project (run `sync` to backfill)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eagle-mem-prune
|
|
3
|
+
description: >
|
|
4
|
+
Clean up old observations and orphaned data to keep Eagle Mem's database lean. Use when:
|
|
5
|
+
'eagle prune', 'clean up memory', 'prune database', 'eagle mem prune', 'database too large',
|
|
6
|
+
'remove old data'. Uses the eagle-mem CLI.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Eagle Mem — Prune
|
|
10
|
+
|
|
11
|
+
Remove old observations, orphaned code chunks, and stale data from Eagle Mem's database.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### Prune with defaults (90 days)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
eagle-mem prune
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Prune older than N days
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
eagle-mem prune --days 30
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Dry run (see what would be removed)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
eagle-mem prune --dry-run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Prune a specific project
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
eagle-mem prune --project my-app
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Options
|
|
40
|
+
|
|
41
|
+
| Flag | Description |
|
|
42
|
+
|------|-------------|
|
|
43
|
+
| `-d, --days <N>` | Remove observations older than N days (default: 90) |
|
|
44
|
+
| `-p, --project <name>` | Target a specific project |
|
|
45
|
+
| `-n, --dry-run` | Show what would be pruned without deleting |
|
|
46
|
+
|
|
47
|
+
## What gets pruned
|
|
48
|
+
|
|
49
|
+
- **Old observations** — tool-use records older than the threshold
|
|
50
|
+
- **Orphaned code chunks** — chunks for files that no longer exist
|
|
51
|
+
|
|
52
|
+
## What is preserved
|
|
53
|
+
|
|
54
|
+
- Session records (never deleted)
|
|
55
|
+
- All summaries
|
|
56
|
+
- Claude Code mirrored memories and plans
|
|
57
|
+
- Task records
|
|
58
|
+
|
|
59
|
+
## When to use
|
|
60
|
+
|
|
61
|
+
- Database feels slow or is growing large
|
|
62
|
+
- After removing a project or major refactor
|
|
63
|
+
- Periodic maintenance (monthly is fine for most users)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eagle-mem-scan
|
|
3
|
+
description: >
|
|
4
|
+
Scan and analyze a project's codebase to generate a persistent overview. Use when: 'eagle scan',
|
|
5
|
+
'scan this project', 'analyze codebase', 'eagle mem scan', 'generate overview from code',
|
|
6
|
+
'what does this project look like'. Uses the eagle-mem CLI.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Eagle Mem — Scan
|
|
10
|
+
|
|
11
|
+
Analyze the current project's codebase and generate a concise overview that Eagle Mem injects at the start of every session.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Scans the project directory to collect:
|
|
16
|
+
- File count, directory structure, languages used
|
|
17
|
+
- Entry points, config files, test presence
|
|
18
|
+
- Framework/library detection from package.json, go.mod, etc.
|
|
19
|
+
|
|
20
|
+
Then saves a compact overview to the database.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
### Scan current project
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
eagle-mem scan .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Scan a specific directory
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
eagle-mem scan /path/to/project
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## When to use
|
|
37
|
+
|
|
38
|
+
- First time opening a project with Eagle Mem
|
|
39
|
+
- After major restructuring (new packages, renamed dirs)
|
|
40
|
+
- When the current overview feels stale or wrong
|
|
41
|
+
|
|
42
|
+
The overview is automatically injected by the SessionStart hook, so every fresh session starts with project context.
|
|
43
|
+
|
|
44
|
+
## Notes
|
|
45
|
+
|
|
46
|
+
- Scans respect .gitignore — only tracked/untracked files are analyzed
|
|
47
|
+
- The overview is stored once per project and updated in place
|
|
48
|
+
- Keep the generated overview factual — it supplements session summaries
|