eagle-mem 4.7.0 → 4.8.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 +56 -12
- package/bin/eagle-mem +1 -0
- package/db/028_agent_artifact_tables.sql +124 -0
- package/db/029_orchestration_lanes.sql +45 -0
- package/db/030_orchestration_lane_scope.sql +88 -0
- package/db/031_orchestration_workers.sql +20 -0
- package/db/032_orchestration_run_keys.sql +9 -0
- package/hooks/post-tool-use.sh +2 -1
- package/hooks/pre-tool-use.sh +25 -1
- package/hooks/session-end.sh +2 -1
- package/hooks/session-start.sh +103 -13
- package/hooks/stop.sh +15 -13
- package/hooks/user-prompt-submit.sh +71 -12
- package/lib/common.sh +173 -2
- package/lib/db-backfill.sh +3 -3
- package/lib/db-mirrors.sh +59 -32
- package/lib/db-observations.sh +7 -0
- package/lib/db-sessions.sh +12 -6
- package/lib/db-summaries.sh +9 -5
- package/lib/hooks-posttool.sh +4 -4
- package/lib/provider.sh +224 -4
- package/package.json +3 -1
- package/scripts/config.sh +32 -0
- package/scripts/health.sh +71 -1
- package/scripts/help.sh +18 -7
- package/scripts/install.sh +12 -0
- package/scripts/memories.sh +50 -27
- package/scripts/orchestrate.sh +1268 -0
- package/scripts/refresh.sh +3 -3
- package/scripts/search.sh +21 -19
- package/scripts/statusline-em.sh +1 -1
- package/scripts/tasks.sh +186 -15
- package/scripts/update.sh +20 -1
- package/skills/eagle-mem-memories/SKILL.md +13 -13
- package/skills/eagle-mem-orchestrate/SKILL.md +149 -0
- package/skills/eagle-mem-tasks/SKILL.md +23 -15
package/scripts/refresh.sh
CHANGED
|
@@ -54,7 +54,7 @@ run_step "Index" bash "$SCRIPTS_DIR/index.sh" "$TARGET_DIR"
|
|
|
54
54
|
echo ""
|
|
55
55
|
|
|
56
56
|
# ─── 3. Memory sync ─────────────────────────────────────
|
|
57
|
-
eagle_info "Step 3/4: Syncing
|
|
57
|
+
eagle_info "Step 3/4: Syncing agent memories, plans, and tasks..."
|
|
58
58
|
run_step "Memory sync" bash "$SCRIPTS_DIR/memories.sh" sync
|
|
59
59
|
echo ""
|
|
60
60
|
|
|
@@ -65,8 +65,8 @@ project_sql=$(eagle_sql_escape "$PROJECT")
|
|
|
65
65
|
sessions=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE project = '$project_sql';")
|
|
66
66
|
summaries=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE project = '$project_sql';")
|
|
67
67
|
chunks=$(eagle_db "SELECT COUNT(*) FROM code_chunks WHERE project = '$project_sql';")
|
|
68
|
-
memories=$(eagle_db "SELECT COUNT(*) FROM
|
|
69
|
-
tasks=$(eagle_db "SELECT COUNT(*) FROM
|
|
68
|
+
memories=$(eagle_db "SELECT COUNT(*) FROM agent_memories WHERE project = '$project_sql';")
|
|
69
|
+
tasks=$(eagle_db "SELECT COUNT(*) FROM agent_tasks WHERE project = '$project_sql';")
|
|
70
70
|
|
|
71
71
|
echo ""
|
|
72
72
|
eagle_kv "Sessions:" "${sessions:-0}"
|
package/scripts/search.sh
CHANGED
|
@@ -26,7 +26,7 @@ show_help() {
|
|
|
26
26
|
echo -e " eagle-mem search ${CYAN}--files${RESET} ${DIM}# frequently modified files${RESET}"
|
|
27
27
|
echo -e " eagle-mem search ${CYAN}--stats${RESET} ${DIM}# project statistics${RESET}"
|
|
28
28
|
echo -e " eagle-mem search ${CYAN}--overview${RESET} ${DIM}# project overview${RESET}"
|
|
29
|
-
echo -e " eagle-mem search ${CYAN}--memories${RESET} ${DIM}# mirrored
|
|
29
|
+
echo -e " eagle-mem search ${CYAN}--memories${RESET} ${DIM}# mirrored agent memories${RESET}"
|
|
30
30
|
echo -e " eagle-mem search ${CYAN}--tasks${RESET} ${DIM}# in-flight tasks${RESET}"
|
|
31
31
|
echo ""
|
|
32
32
|
echo -e " ${BOLD}Options:${RESET}"
|
|
@@ -269,7 +269,7 @@ search_stats() {
|
|
|
269
269
|
sessions_codex=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE project = '$p' AND agent = 'codex';")
|
|
270
270
|
summaries=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE project = '$p';")
|
|
271
271
|
observations=$(eagle_db "SELECT COUNT(*) FROM observations o JOIN sessions s ON s.id = o.session_id WHERE s.project = '$p';")
|
|
272
|
-
tasks=$(eagle_db "SELECT COUNT(*) FROM
|
|
272
|
+
tasks=$(eagle_db "SELECT COUNT(*) FROM agent_tasks WHERE project = '$p';")
|
|
273
273
|
local chunks
|
|
274
274
|
chunks=$(eagle_db "SELECT COUNT(*) FROM code_chunks WHERE project = '$p';")
|
|
275
275
|
|
|
@@ -349,15 +349,15 @@ search_memories() {
|
|
|
349
349
|
exit 1
|
|
350
350
|
fi
|
|
351
351
|
local q; q=$(eagle_sql_escape "$sanitized_mq")
|
|
352
|
-
local where_match="WHERE
|
|
352
|
+
local where_match="WHERE agent_memories_fts MATCH '$q'"
|
|
353
353
|
if [ "$cross_project" = false ]; then
|
|
354
354
|
where_match="$where_match AND m.project = '$p'"
|
|
355
355
|
fi
|
|
356
356
|
|
|
357
357
|
if [ "$json_output" = true ]; then
|
|
358
358
|
eagle_db_json "SELECT m.memory_name, m.memory_type, m.description, m.project, m.updated_at, m.origin_agent
|
|
359
|
-
FROM
|
|
360
|
-
JOIN
|
|
359
|
+
FROM agent_memories m
|
|
360
|
+
JOIN agent_memories_fts f ON f.rowid = m.id
|
|
361
361
|
$where_match
|
|
362
362
|
ORDER BY rank
|
|
363
363
|
LIMIT $limit;"
|
|
@@ -366,8 +366,8 @@ search_memories() {
|
|
|
366
366
|
|
|
367
367
|
local results
|
|
368
368
|
results=$(eagle_db "SELECT m.memory_name, m.memory_type, m.description, m.project, m.updated_at, m.origin_agent
|
|
369
|
-
FROM
|
|
370
|
-
JOIN
|
|
369
|
+
FROM agent_memories m
|
|
370
|
+
JOIN agent_memories_fts f ON f.rowid = m.id
|
|
371
371
|
$where_match
|
|
372
372
|
ORDER BY rank
|
|
373
373
|
LIMIT $limit;")
|
|
@@ -390,14 +390,14 @@ search_memories() {
|
|
|
390
390
|
|
|
391
391
|
if [ "$json_output" = true ]; then
|
|
392
392
|
eagle_db_json "SELECT memory_name, memory_type, description, project, updated_at, origin_agent
|
|
393
|
-
FROM
|
|
393
|
+
FROM agent_memories $where_project
|
|
394
394
|
ORDER BY updated_at DESC LIMIT $limit;"
|
|
395
395
|
return
|
|
396
396
|
fi
|
|
397
397
|
|
|
398
398
|
local results
|
|
399
399
|
results=$(eagle_db "SELECT memory_name, memory_type, description, updated_at, origin_agent
|
|
400
|
-
FROM
|
|
400
|
+
FROM agent_memories $where_project
|
|
401
401
|
ORDER BY updated_at DESC LIMIT $limit;")
|
|
402
402
|
|
|
403
403
|
if [ -z "$results" ]; then
|
|
@@ -424,8 +424,10 @@ search_tasks() {
|
|
|
424
424
|
local p; p=$(eagle_sql_escape "$project")
|
|
425
425
|
|
|
426
426
|
local where_project=""
|
|
427
|
+
local where_task_project=""
|
|
427
428
|
if [ "$cross_project" = false ]; then
|
|
428
429
|
where_project="AND project = '$p'"
|
|
430
|
+
where_task_project="AND t.project = '$p'"
|
|
429
431
|
fi
|
|
430
432
|
|
|
431
433
|
if [ -n "$query" ]; then
|
|
@@ -439,10 +441,10 @@ search_tasks() {
|
|
|
439
441
|
|
|
440
442
|
if [ "$json_output" = true ]; then
|
|
441
443
|
eagle_db_json "SELECT t.subject, t.status, t.project, t.updated_at, t.origin_agent
|
|
442
|
-
FROM
|
|
443
|
-
JOIN
|
|
444
|
-
WHERE
|
|
445
|
-
$
|
|
444
|
+
FROM agent_tasks t
|
|
445
|
+
JOIN agent_tasks_fts f ON f.rowid = t.id
|
|
446
|
+
WHERE agent_tasks_fts MATCH '$q'
|
|
447
|
+
$where_task_project
|
|
446
448
|
ORDER BY rank
|
|
447
449
|
LIMIT $limit;"
|
|
448
450
|
return
|
|
@@ -450,10 +452,10 @@ search_tasks() {
|
|
|
450
452
|
|
|
451
453
|
local results
|
|
452
454
|
results=$(eagle_db "SELECT t.subject, t.status, t.project, t.updated_at, t.origin_agent
|
|
453
|
-
FROM
|
|
454
|
-
JOIN
|
|
455
|
-
WHERE
|
|
456
|
-
$
|
|
455
|
+
FROM agent_tasks t
|
|
456
|
+
JOIN agent_tasks_fts f ON f.rowid = t.id
|
|
457
|
+
WHERE agent_tasks_fts MATCH '$q'
|
|
458
|
+
$where_task_project
|
|
457
459
|
ORDER BY rank
|
|
458
460
|
LIMIT $limit;")
|
|
459
461
|
|
|
@@ -479,7 +481,7 @@ search_tasks() {
|
|
|
479
481
|
|
|
480
482
|
if [ "$json_output" = true ]; then
|
|
481
483
|
eagle_db_json "SELECT subject, status, project, updated_at, origin_agent
|
|
482
|
-
FROM
|
|
484
|
+
FROM agent_tasks
|
|
483
485
|
WHERE status IN ('in_progress', 'pending')
|
|
484
486
|
$where_project
|
|
485
487
|
ORDER BY CASE status WHEN 'in_progress' THEN 0 ELSE 1 END, updated_at DESC
|
|
@@ -489,7 +491,7 @@ search_tasks() {
|
|
|
489
491
|
|
|
490
492
|
local results
|
|
491
493
|
results=$(eagle_db "SELECT subject, status, updated_at, origin_agent
|
|
492
|
-
FROM
|
|
494
|
+
FROM agent_tasks
|
|
493
495
|
WHERE status IN ('in_progress', 'pending')
|
|
494
496
|
$where_project
|
|
495
497
|
ORDER BY CASE status WHEN 'in_progress' THEN 0 ELSE 1 END, updated_at DESC
|
package/scripts/statusline-em.sh
CHANGED
|
@@ -21,7 +21,7 @@ eagle_mem_statusline() {
|
|
|
21
21
|
cnt=$(echo ".headers off
|
|
22
22
|
SELECT COUNT(*) FROM sessions WHERE project = '${proj}';" | sqlite3 "$em_db" 2>/dev/null | tr -d '[:space:]')
|
|
23
23
|
mem=$(echo ".headers off
|
|
24
|
-
SELECT COUNT(*) FROM
|
|
24
|
+
SELECT COUNT(*) FROM agent_memories WHERE project = '${proj}';" | sqlite3 "$em_db" 2>/dev/null | tr -d '[:space:]')
|
|
25
25
|
cnt=${cnt:-0}; mem=${mem:-0}
|
|
26
26
|
|
|
27
27
|
local R='\033[0m' CYAN='\033[96m' WHT='\033[97m' DIM='\033[2m'
|
package/scripts/tasks.sh
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# ═══════════════════════════════════════════════════════════
|
|
3
|
-
# Eagle Mem — Tasks
|
|
4
|
-
#
|
|
5
|
-
#
|
|
3
|
+
# Eagle Mem — Tasks
|
|
4
|
+
# Mirrors native task state and lets agents without native task files persist
|
|
5
|
+
# task handoff records directly.
|
|
6
6
|
# ═══════════════════════════════════════════════════════════
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
|
|
@@ -26,22 +26,29 @@ esac
|
|
|
26
26
|
|
|
27
27
|
project=""
|
|
28
28
|
json_output=false
|
|
29
|
+
agent=""
|
|
29
30
|
|
|
30
31
|
show_help() {
|
|
31
|
-
echo -e " ${BOLD}eagle-mem tasks${RESET} — View mirrored
|
|
32
|
+
echo -e " ${BOLD}eagle-mem tasks${RESET} — View mirrored agent tasks"
|
|
32
33
|
echo ""
|
|
33
34
|
echo -e " ${BOLD}Usage:${RESET}"
|
|
34
35
|
echo -e " eagle-mem tasks ${DIM}# list pending/in-progress tasks${RESET}"
|
|
35
36
|
echo -e " eagle-mem tasks ${CYAN}list${RESET} ${DIM}# list all tasks${RESET}"
|
|
36
37
|
echo -e " eagle-mem tasks ${CYAN}completed${RESET} ${DIM}# list completed tasks${RESET}"
|
|
37
38
|
echo -e " eagle-mem tasks ${CYAN}search${RESET} <query> ${DIM}# search tasks by keyword${RESET}"
|
|
39
|
+
echo -e " eagle-mem tasks ${CYAN}add${RESET} <subject> ${DIM}# create a persistent task record${RESET}"
|
|
40
|
+
echo -e " eagle-mem tasks ${CYAN}update${RESET} <id> ${DIM}# update subject/description/status${RESET}"
|
|
41
|
+
echo -e " eagle-mem tasks ${CYAN}start${RESET} <id> ${DIM}# mark task in_progress${RESET}"
|
|
42
|
+
echo -e " eagle-mem tasks ${CYAN}complete${RESET} <id> ${DIM}# mark task completed${RESET}"
|
|
43
|
+
echo -e " eagle-mem tasks ${CYAN}cancel${RESET} <id> ${DIM}# mark task cancelled${RESET}"
|
|
38
44
|
echo ""
|
|
39
45
|
echo -e " ${BOLD}Options:${RESET}"
|
|
40
46
|
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir)"
|
|
47
|
+
echo -e " ${CYAN}--agent${RESET} <name> Source agent (codex or claude-code)"
|
|
41
48
|
echo -e " ${CYAN}-j, --json${RESET} Output as JSON"
|
|
42
49
|
echo ""
|
|
43
|
-
echo -e " ${DIM}
|
|
44
|
-
echo -e " ${DIM}
|
|
50
|
+
echo -e " ${DIM}Claude Code task files are mirrored automatically.${RESET}"
|
|
51
|
+
echo -e " ${DIM}Codex can persist tasks with this CLI when using the eagle-mem-tasks skill.${RESET}"
|
|
45
52
|
echo ""
|
|
46
53
|
exit 0
|
|
47
54
|
}
|
|
@@ -50,6 +57,7 @@ args=()
|
|
|
50
57
|
while [ $# -gt 0 ]; do
|
|
51
58
|
case "$1" in
|
|
52
59
|
--project|-p) project="$2"; shift 2 ;;
|
|
60
|
+
--agent) agent="$2"; shift 2 ;;
|
|
53
61
|
--json|-j) json_output=true; shift ;;
|
|
54
62
|
--help|-h) show_help ;;
|
|
55
63
|
*) args+=("$1"); shift ;;
|
|
@@ -58,6 +66,8 @@ done
|
|
|
58
66
|
|
|
59
67
|
[ -z "$project" ] && project=$(eagle_project_from_cwd "$(pwd)")
|
|
60
68
|
project_sql=$(eagle_sql_escape "$project")
|
|
69
|
+
[ -z "$agent" ] && agent=$(eagle_agent_source)
|
|
70
|
+
agent_sql=$(eagle_sql_escape "$agent")
|
|
61
71
|
|
|
62
72
|
# ─── List tasks ───────────────────────────────────────────
|
|
63
73
|
|
|
@@ -73,7 +83,7 @@ tasks_list() {
|
|
|
73
83
|
|
|
74
84
|
if [ "$json_output" = true ]; then
|
|
75
85
|
eagle_db_json "SELECT source_task_id, subject, description, status, blocks, blocked_by, updated_at
|
|
76
|
-
FROM
|
|
86
|
+
FROM agent_tasks
|
|
77
87
|
WHERE project = '$project_sql' $where_status
|
|
78
88
|
ORDER BY updated_at DESC
|
|
79
89
|
LIMIT 20;"
|
|
@@ -82,7 +92,7 @@ tasks_list() {
|
|
|
82
92
|
|
|
83
93
|
local results
|
|
84
94
|
results=$(eagle_db "SELECT source_task_id, subject, status, blocked_by, description
|
|
85
|
-
FROM
|
|
95
|
+
FROM agent_tasks
|
|
86
96
|
WHERE project = '$project_sql' $where_status
|
|
87
97
|
ORDER BY
|
|
88
98
|
CASE status WHEN 'in_progress' THEN 0 WHEN 'pending' THEN 1 ELSE 2 END,
|
|
@@ -106,7 +116,7 @@ tasks_list() {
|
|
|
106
116
|
in_progress) icon="${CYAN}>${RESET}"; marker=" ${CYAN}[in_progress]${RESET}" ;;
|
|
107
117
|
pending) icon="${DIM}o${RESET}"; marker="" ;;
|
|
108
118
|
completed) icon="${GREEN}+${RESET}"; marker=" ${DIM}[completed]${RESET}" ;;
|
|
109
|
-
|
|
119
|
+
cancelled) icon="${RED}x${RESET}"; marker=" ${RED}[cancelled]${RESET}" ;;
|
|
110
120
|
*) icon="$DOT"; marker="" ;;
|
|
111
121
|
esac
|
|
112
122
|
if [ "$blocked_by" != "[]" ] && [ -n "$blocked_by" ]; then
|
|
@@ -137,9 +147,9 @@ tasks_search() {
|
|
|
137
147
|
if [ "$json_output" = true ]; then
|
|
138
148
|
local query_sql; query_sql=$(eagle_sql_escape "$sanitized_query")
|
|
139
149
|
eagle_db_json "SELECT t.source_task_id, t.subject, t.status, t.description, t.updated_at
|
|
140
|
-
FROM
|
|
141
|
-
JOIN
|
|
142
|
-
WHERE
|
|
150
|
+
FROM agent_tasks t
|
|
151
|
+
JOIN agent_tasks_fts f ON f.rowid = t.id
|
|
152
|
+
WHERE agent_tasks_fts MATCH '$query_sql'
|
|
143
153
|
AND t.project = '$project_sql'
|
|
144
154
|
ORDER BY rank
|
|
145
155
|
LIMIT 10;"
|
|
@@ -149,9 +159,9 @@ tasks_search() {
|
|
|
149
159
|
local results
|
|
150
160
|
local query_sql; query_sql=$(eagle_sql_escape "$sanitized_query")
|
|
151
161
|
results=$(eagle_db "SELECT t.source_task_id, t.subject, t.status, t.description
|
|
152
|
-
FROM
|
|
153
|
-
JOIN
|
|
154
|
-
WHERE
|
|
162
|
+
FROM agent_tasks t
|
|
163
|
+
JOIN agent_tasks_fts f ON f.rowid = t.id
|
|
164
|
+
WHERE agent_tasks_fts MATCH '$query_sql'
|
|
155
165
|
AND t.project = '$project_sql'
|
|
156
166
|
ORDER BY rank
|
|
157
167
|
LIMIT 10;")
|
|
@@ -174,6 +184,162 @@ tasks_search() {
|
|
|
174
184
|
echo ""
|
|
175
185
|
}
|
|
176
186
|
|
|
187
|
+
# ─── Mutate task records ──────────────────────────────────
|
|
188
|
+
|
|
189
|
+
tasks_add() {
|
|
190
|
+
local subject="${args[0]:-}"
|
|
191
|
+
if [ -z "$subject" ]; then
|
|
192
|
+
eagle_err "Usage: eagle-mem tasks add <subject> [--desc <text>] [--status pending|in_progress]"
|
|
193
|
+
exit 1
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
local desc=""
|
|
197
|
+
local status="pending"
|
|
198
|
+
local i=1
|
|
199
|
+
while [ "$i" -lt "${#args[@]}" ]; do
|
|
200
|
+
case "${args[$i]}" in
|
|
201
|
+
--desc|-d)
|
|
202
|
+
i=$((i + 1))
|
|
203
|
+
desc="${args[$i]:-}"
|
|
204
|
+
;;
|
|
205
|
+
--status)
|
|
206
|
+
i=$((i + 1))
|
|
207
|
+
status="${args[$i]:-pending}"
|
|
208
|
+
;;
|
|
209
|
+
esac
|
|
210
|
+
i=$((i + 1))
|
|
211
|
+
done
|
|
212
|
+
|
|
213
|
+
case "$status" in
|
|
214
|
+
pending|in_progress|completed|cancelled) ;;
|
|
215
|
+
*)
|
|
216
|
+
eagle_err "Invalid status: $status"
|
|
217
|
+
exit 1
|
|
218
|
+
;;
|
|
219
|
+
esac
|
|
220
|
+
|
|
221
|
+
local task_id file_path content_hash
|
|
222
|
+
task_id="agent-$(date -u +%Y%m%d%H%M%S)-$$"
|
|
223
|
+
file_path="agent-task://$project/$task_id"
|
|
224
|
+
content_hash=$(printf '%s|%s|%s|%s' "$subject" "$desc" "$status" "$agent" | shasum -a 256 | awk '{print $1}')
|
|
225
|
+
|
|
226
|
+
local tid_sql fp_sql subj_sql desc_sql status_sql hash_sql
|
|
227
|
+
tid_sql=$(eagle_sql_escape "$task_id")
|
|
228
|
+
fp_sql=$(eagle_sql_escape "$file_path")
|
|
229
|
+
subj_sql=$(eagle_sql_escape "$subject")
|
|
230
|
+
desc_sql=$(eagle_sql_escape "$desc")
|
|
231
|
+
status_sql=$(eagle_sql_escape "$status")
|
|
232
|
+
hash_sql=$(eagle_sql_escape "$content_hash")
|
|
233
|
+
|
|
234
|
+
eagle_db_pipe <<SQL
|
|
235
|
+
INSERT INTO agent_tasks (project, source_session_id, source_task_id, file_path, subject, description, active_form, status, blocks, blocked_by, content_hash, origin_agent)
|
|
236
|
+
VALUES ('$project_sql', 'manual', '$tid_sql', '$fp_sql', '$subj_sql', '$desc_sql', '', '$status_sql', '[]', '[]', '$hash_sql', '$agent_sql');
|
|
237
|
+
SQL
|
|
238
|
+
|
|
239
|
+
if [ "$json_output" = true ]; then
|
|
240
|
+
jq -nc --arg id "$task_id" --arg subject "$subject" --arg status "$status" --arg agent "$agent" \
|
|
241
|
+
'{source_task_id:$id, subject:$subject, status:$status, origin_agent:$agent}'
|
|
242
|
+
else
|
|
243
|
+
eagle_ok "Task '$task_id' created"
|
|
244
|
+
fi
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
tasks_set_status() {
|
|
248
|
+
local task_id="${args[0]:-}"
|
|
249
|
+
local status="$1"
|
|
250
|
+
if [ -z "$task_id" ]; then
|
|
251
|
+
eagle_err "Usage: eagle-mem tasks $action <id>"
|
|
252
|
+
exit 1
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
local tid_sql status_sql
|
|
256
|
+
tid_sql=$(eagle_sql_escape "$task_id")
|
|
257
|
+
status_sql=$(eagle_sql_escape "$status")
|
|
258
|
+
|
|
259
|
+
changed=$(eagle_db_pipe <<SQL
|
|
260
|
+
UPDATE agent_tasks
|
|
261
|
+
SET status = '$status_sql',
|
|
262
|
+
origin_agent = COALESCE(NULLIF('$agent_sql', ''), origin_agent),
|
|
263
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
264
|
+
WHERE project = '$project_sql' AND source_task_id = '$tid_sql';
|
|
265
|
+
SELECT changes();
|
|
266
|
+
SQL
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
if [ "${changed:-0}" -gt 0 ] 2>/dev/null; then
|
|
270
|
+
eagle_ok "Task '$task_id' marked $status"
|
|
271
|
+
else
|
|
272
|
+
eagle_err "Task not found: $task_id"
|
|
273
|
+
exit 1
|
|
274
|
+
fi
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
tasks_update() {
|
|
278
|
+
local task_id="${args[0]:-}"
|
|
279
|
+
if [ -z "$task_id" ]; then
|
|
280
|
+
eagle_err "Usage: eagle-mem tasks update <id> [--subject <text>] [--desc <text>] [--status <status>]"
|
|
281
|
+
exit 1
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
local subject="" desc="" status=""
|
|
285
|
+
local i=1
|
|
286
|
+
while [ "$i" -lt "${#args[@]}" ]; do
|
|
287
|
+
case "${args[$i]}" in
|
|
288
|
+
--subject)
|
|
289
|
+
i=$((i + 1))
|
|
290
|
+
subject="${args[$i]:-}"
|
|
291
|
+
;;
|
|
292
|
+
--desc|-d)
|
|
293
|
+
i=$((i + 1))
|
|
294
|
+
desc="${args[$i]:-}"
|
|
295
|
+
;;
|
|
296
|
+
--status)
|
|
297
|
+
i=$((i + 1))
|
|
298
|
+
status="${args[$i]:-}"
|
|
299
|
+
;;
|
|
300
|
+
esac
|
|
301
|
+
i=$((i + 1))
|
|
302
|
+
done
|
|
303
|
+
|
|
304
|
+
if [ -n "$status" ]; then
|
|
305
|
+
case "$status" in
|
|
306
|
+
pending|in_progress|completed|cancelled) ;;
|
|
307
|
+
*)
|
|
308
|
+
eagle_err "Invalid status: $status"
|
|
309
|
+
exit 1
|
|
310
|
+
;;
|
|
311
|
+
esac
|
|
312
|
+
fi
|
|
313
|
+
|
|
314
|
+
local tid_sql subj_sql desc_sql status_sql hash_sql
|
|
315
|
+
tid_sql=$(eagle_sql_escape "$task_id")
|
|
316
|
+
subj_sql=$(eagle_sql_escape "$subject")
|
|
317
|
+
desc_sql=$(eagle_sql_escape "$desc")
|
|
318
|
+
status_sql=$(eagle_sql_escape "$status")
|
|
319
|
+
hash_sql=$(printf '%s|%s|%s|%s|%s' "$task_id" "$subject" "$desc" "$status" "$agent" | shasum -a 256 | awk '{print $1}')
|
|
320
|
+
hash_sql=$(eagle_sql_escape "$hash_sql")
|
|
321
|
+
|
|
322
|
+
changed=$(eagle_db_pipe <<SQL
|
|
323
|
+
UPDATE agent_tasks
|
|
324
|
+
SET subject = CASE WHEN '$subj_sql' != '' THEN '$subj_sql' ELSE subject END,
|
|
325
|
+
description = CASE WHEN '$desc_sql' != '' THEN '$desc_sql' ELSE description END,
|
|
326
|
+
status = CASE WHEN '$status_sql' != '' THEN '$status_sql' ELSE status END,
|
|
327
|
+
origin_agent = COALESCE(NULLIF('$agent_sql', ''), origin_agent),
|
|
328
|
+
content_hash = '$hash_sql',
|
|
329
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
330
|
+
WHERE project = '$project_sql' AND source_task_id = '$tid_sql';
|
|
331
|
+
SELECT changes();
|
|
332
|
+
SQL
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
if [ "${changed:-0}" -gt 0 ] 2>/dev/null; then
|
|
336
|
+
eagle_ok "Task '$task_id' updated"
|
|
337
|
+
else
|
|
338
|
+
eagle_err "Task not found: $task_id"
|
|
339
|
+
exit 1
|
|
340
|
+
fi
|
|
341
|
+
}
|
|
342
|
+
|
|
177
343
|
# ─── Dispatch ─────────────────────────────────────────────
|
|
178
344
|
|
|
179
345
|
case "$action" in
|
|
@@ -181,6 +347,11 @@ case "$action" in
|
|
|
181
347
|
pending) tasks_list "pending" ;;
|
|
182
348
|
completed) tasks_list "completed" ;;
|
|
183
349
|
search) tasks_search ;;
|
|
350
|
+
add) tasks_add ;;
|
|
351
|
+
update) tasks_update ;;
|
|
352
|
+
start) tasks_set_status "in_progress" ;;
|
|
353
|
+
complete) tasks_set_status "completed" ;;
|
|
354
|
+
cancel) tasks_set_status "cancelled" ;;
|
|
184
355
|
--help|-h) show_help ;;
|
|
185
356
|
*)
|
|
186
357
|
eagle_err "Unknown action: $action"
|
package/scripts/update.sh
CHANGED
|
@@ -119,7 +119,26 @@ if [ "$claude_found" = true ] && [ -d "$PACKAGE_DIR/skills" ]; then
|
|
|
119
119
|
[ -L "$dst" ] && rm "$dst"
|
|
120
120
|
ln -sf "$skill_dir" "$dst"
|
|
121
121
|
done
|
|
122
|
-
eagle_ok "
|
|
122
|
+
eagle_ok "Claude skills updated"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
if [ "$codex_found" = true ] && [ -d "$PACKAGE_DIR/skills" ]; then
|
|
126
|
+
mkdir -p "$EAGLE_CODEX_SKILLS_DIR"
|
|
127
|
+
find "$EAGLE_CODEX_SKILLS_DIR" -maxdepth 1 -name "eagle-mem-*" -type l 2>/dev/null | while read -r existing; do
|
|
128
|
+
skill_name=$(basename "$existing")
|
|
129
|
+
if [ ! -d "$PACKAGE_DIR/skills/$skill_name" ]; then
|
|
130
|
+
rm "$existing"
|
|
131
|
+
eagle_ok "Removed stale Codex skill: $skill_name"
|
|
132
|
+
fi
|
|
133
|
+
done
|
|
134
|
+
for skill_dir in "$PACKAGE_DIR"/skills/*/; do
|
|
135
|
+
[ ! -d "$skill_dir" ] && continue
|
|
136
|
+
skill_name=$(basename "$skill_dir")
|
|
137
|
+
dst="$EAGLE_CODEX_SKILLS_DIR/$skill_name"
|
|
138
|
+
[ -L "$dst" ] && rm "$dst"
|
|
139
|
+
ln -sf "$skill_dir" "$dst"
|
|
140
|
+
done
|
|
141
|
+
eagle_ok "Codex skills updated"
|
|
123
142
|
fi
|
|
124
143
|
|
|
125
144
|
# ─── Backfill project names ───────────────────────────────
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eagle-mem-memories
|
|
3
3
|
description: >
|
|
4
|
-
View and sync Claude Code
|
|
5
|
-
'eagle memories', 'show memories', 'sync memories', 'what does
|
|
4
|
+
View and sync Claude Code and Codex memories, plans, and tasks mirrored in Eagle Mem. Use when:
|
|
5
|
+
'eagle memories', 'show memories', 'sync memories', 'what does the agent remember',
|
|
6
6
|
'show plans', 'show tasks', 'mirror memories', 'onboard project',
|
|
7
7
|
'what did past sessions learn'. Uses the eagle-mem CLI.
|
|
8
8
|
---
|
|
@@ -11,9 +11,9 @@ description: >
|
|
|
11
11
|
|
|
12
12
|
## Purpose
|
|
13
13
|
|
|
14
|
-
**For the user:** Claude Code
|
|
14
|
+
**For the user:** Claude Code and Codex remember across sessions. Decisions, preferences, project context, and architectural plans survive session boundaries. The user never has to re-explain "we chose Postgres because..." or "don't use semicolons in this project."
|
|
15
15
|
|
|
16
|
-
**For you
|
|
16
|
+
**For you:** Access to what past Claude Code and Codex sessions learned about this project. Memories tell you *why* decisions were made. Plans tell you *what's coming*. Tasks tell you *what's in flight*. Together they're the knowledge bridge that makes you effective from message one.
|
|
17
17
|
|
|
18
18
|
## Judgment
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ description: >
|
|
|
21
21
|
- The user references a past decision ("remember when we decided to...", "what's our convention for...")
|
|
22
22
|
- You're about to make an architectural or style choice -- memories may record the user's preference
|
|
23
23
|
- You need project context that isn't in CLAUDE.md or README (relationships between services, deployment quirks, naming conventions)
|
|
24
|
-
- The user asks "what does Claude remember about X?"
|
|
24
|
+
- The user asks "what does Claude/Codex/Eagle Mem remember about X?"
|
|
25
25
|
|
|
26
26
|
**Check plans when:**
|
|
27
27
|
- The user asks about upcoming work or roadmap
|
|
@@ -43,21 +43,21 @@ description: >
|
|
|
43
43
|
|
|
44
44
|
### 1. Know the three data types
|
|
45
45
|
|
|
46
|
-
**Memories** -- Claude Code
|
|
46
|
+
**Memories** -- Claude Code auto-memory files (`~/.claude/projects/*/memory/*.md`) plus top-level Codex memory files (`~/.codex/memories/MEMORY.md`, `memory_summary.md`). These contain user preferences, project conventions, and feedback. Each mirrored row is source-attributed.
|
|
47
47
|
```bash
|
|
48
48
|
eagle-mem memories list # all memories
|
|
49
49
|
eagle-mem memories search "typescript" # FTS5 search
|
|
50
50
|
eagle-mem memories show <file_path> # full content
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
**Plans** -- Claude Code
|
|
53
|
+
**Plans** -- Claude Code plan files (`~/.claude/plans/*.md`) and future agent plan files as support is added. Multi-step strategies for complex work. Each has a title, optional project tag, and markdown content.
|
|
54
54
|
```bash
|
|
55
55
|
eagle-mem memories plans # all plans
|
|
56
56
|
eagle-mem memories plans search "migration"
|
|
57
57
|
eagle-mem memories plans show <file_path>
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
**Tasks** -- Claude Code
|
|
60
|
+
**Tasks** -- Claude Code task JSON (`~/.claude/tasks/<session>/*.json`) and Eagle Mem task records created directly by agents such as Codex. Individual units of work with status tracking (pending/in_progress/completed).
|
|
61
61
|
```bash
|
|
62
62
|
eagle-mem memories tasks # all tasks
|
|
63
63
|
eagle-mem memories tasks search "refactor"
|
|
@@ -68,13 +68,13 @@ eagle-mem memories tasks show <file_path>
|
|
|
68
68
|
|
|
69
69
|
Two paths feed the mirror:
|
|
70
70
|
|
|
71
|
-
**Real-time
|
|
71
|
+
**Real-time hooks.** Claude Code memory/plan/task files are mirrored when written. Codex sessions are captured through SessionStart/UserPromptSubmit/PostToolUse/Stop hooks, and important durable facts should be placed in `<eagle-summary>` so they become shared recall.
|
|
72
72
|
|
|
73
|
-
**Backfill (sync command).** For memories, plans, and tasks that existed before Eagle Mem was installed, or that were written outside a
|
|
73
|
+
**Backfill (sync command).** For memories, plans, and tasks that existed before Eagle Mem was installed, or that were written outside a hooked session:
|
|
74
74
|
```bash
|
|
75
75
|
eagle-mem memories sync
|
|
76
76
|
```
|
|
77
|
-
This scans
|
|
77
|
+
This scans known Claude Code and Codex memory/task locations, hashes each file, skips unchanged ones, and mirrors anything new or modified. It also backfills project names from transcripts. Safe to run repeatedly -- content-hash dedup prevents double-insertion.
|
|
78
78
|
|
|
79
79
|
### 3. Search effectively
|
|
80
80
|
|
|
@@ -104,7 +104,7 @@ This asymmetry is intentional but easy to forget. If you're getting too many irr
|
|
|
104
104
|
|
|
105
105
|
### 5. Onboard an existing project
|
|
106
106
|
|
|
107
|
-
When Eagle Mem is installed on a project that already has Claude Code history:
|
|
107
|
+
When Eagle Mem is installed on a project that already has Claude Code or Codex history:
|
|
108
108
|
```bash
|
|
109
109
|
eagle-mem memories sync
|
|
110
110
|
```
|
|
@@ -117,7 +117,7 @@ After sync or after expecting the hook to fire:
|
|
|
117
117
|
eagle-mem memories list # should show recent memories
|
|
118
118
|
eagle-mem search --stats # check counts are non-zero
|
|
119
119
|
```
|
|
120
|
-
If memories list is empty after sync, check that `~/.claude/projects/` contains memory files
|
|
120
|
+
If memories list is empty after sync, check that `~/.claude/projects/` or `~/.codex/memories/` contains memory files. If the hook isn't capturing new writes, check Claude Code `settings.json` or Codex `hooks.json`.
|
|
121
121
|
|
|
122
122
|
## What makes a good memory lookup
|
|
123
123
|
|