eagle-mem 3.2.0 → 3.3.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 +14 -2
- package/db/020_drop_seeded_rules.sql +12 -0
- package/hooks/post-tool-use.sh +20 -1
- package/hooks/pre-tool-use.sh +115 -69
- package/hooks/session-start.sh +4 -0
- package/lib/db-observations.sh +2 -1
- package/lib/db-sessions.sh +3 -3
- package/lib/hooks.sh +9 -1
- package/package.json +1 -1
- package/scripts/curate.sh +7 -0
- package/scripts/install.sh +5 -1
- package/scripts/update.sh +1 -0
package/README.md
CHANGED
|
@@ -159,16 +159,27 @@ The `update` command copies new files, runs any pending database migrations, and
|
|
|
159
159
|
|
|
160
160
|
## How it works
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
Six hooks fire automatically at different points in Claude Code's lifecycle:
|
|
163
163
|
|
|
164
164
|
| Hook | Fires when | What it does |
|
|
165
165
|
|------|-----------|--------------|
|
|
166
166
|
| **SessionStart** | startup, resume, clear, compact | Injects overview, summaries, memories, tasks |
|
|
167
|
+
| **PreToolUse** | before Bash and Read calls | Rewrites noisy commands (learned rules), detects redundant reads |
|
|
167
168
|
| **UserPromptSubmit** | user sends a message | FTS5 search for relevant past context |
|
|
168
|
-
| **PostToolUse** | after tool calls | Records file touches, mirrors memory/plan/task writes |
|
|
169
|
+
| **PostToolUse** | after tool calls | Records file touches, mirrors memory/plan/task writes, tracks modifications |
|
|
169
170
|
| **Stop** | Claude's turn ends | Extracts `<eagle-summary>`, strips `<private>` tags |
|
|
170
171
|
| **SessionEnd** | session closes | Re-syncs tasks, marks session completed |
|
|
171
172
|
|
|
173
|
+
### Token savings
|
|
174
|
+
|
|
175
|
+
Eagle Mem actively reduces token consumption:
|
|
176
|
+
|
|
177
|
+
- **Command rewriting** — PreToolUse rewrites noisy Bash commands (e.g., `find`, `grep`) to pipe through `head -N`, using `updatedInput` to modify the command before execution. Rules are learned by the curator from real usage, not hardcoded.
|
|
178
|
+
- **Read-after-modify detection** — If you just edited or wrote a file, Eagle Mem nudges that the diff is already in context before a redundant Read.
|
|
179
|
+
- **Read dedup tracking** — Files read 3+ times in a session get a soft nudge that contents are likely already in context.
|
|
180
|
+
|
|
181
|
+
### Data
|
|
182
|
+
|
|
172
183
|
Data lives in a single SQLite database at `~/.eagle-mem/memory.db` (WAL mode, FTS5 full-text search):
|
|
173
184
|
|
|
174
185
|
| Table | What it stores |
|
|
@@ -178,6 +189,7 @@ Data lives in a single SQLite database at `~/.eagle-mem/memory.db` (WAL mode, FT
|
|
|
178
189
|
| observations | Per-tool-use file touch records |
|
|
179
190
|
| overviews | One overview per project (scan or manual) |
|
|
180
191
|
| code_chunks | FTS5-indexed source file chunks |
|
|
192
|
+
| command_rules | Curator-learned command output rules |
|
|
181
193
|
| claude_memories | Mirror of Claude Code auto-memories |
|
|
182
194
|
| claude_plans | Mirror of Claude Code plans |
|
|
183
195
|
| claude_tasks | Mirror of Claude Code tasks |
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Migration 020: Remove seeded global command rules.
|
|
2
|
+
-- Self-learning pipeline (curator) now generates rules from real usage.
|
|
3
|
+
-- Per-project rules created by the curator are preserved.
|
|
4
|
+
--
|
|
5
|
+
-- Safety: back up any existing global rules before deleting so they
|
|
6
|
+
-- can be restored if a user manually created rules they want to keep.
|
|
7
|
+
-- The backup table is left in place intentionally.
|
|
8
|
+
|
|
9
|
+
CREATE TABLE IF NOT EXISTS _backup_020_global_rules AS
|
|
10
|
+
SELECT * FROM command_rules WHERE project = '';
|
|
11
|
+
|
|
12
|
+
DELETE FROM command_rules WHERE project = '';
|
package/hooks/post-tool-use.sh
CHANGED
|
@@ -68,7 +68,7 @@ case "$tool_name" in
|
|
|
68
68
|
cmd=$(echo "$cmd" | eagle_redact)
|
|
69
69
|
tool_summary="Bash: $cmd"
|
|
70
70
|
|
|
71
|
-
tool_output=$(echo "$input" | jq -r '.
|
|
71
|
+
tool_output=$(echo "$input" | jq -r '.tool_response.stdout // empty' 2>/dev/null)
|
|
72
72
|
if [ -n "$tool_output" ]; then
|
|
73
73
|
output_bytes=${#tool_output}
|
|
74
74
|
output_lines=$(echo "$tool_output" | wc -l | tr -d ' ')
|
|
@@ -98,6 +98,25 @@ case "$tool_name" in
|
|
|
98
98
|
;;
|
|
99
99
|
esac
|
|
100
100
|
|
|
101
|
+
# ─── Track recent Edit/Write targets for Read-after-modify detection ──
|
|
102
|
+
|
|
103
|
+
if [ -n "$fp" ] && [ -n "$session_id" ] && eagle_validate_session_id "$session_id"; then
|
|
104
|
+
case "$tool_name" in
|
|
105
|
+
Edit|Write)
|
|
106
|
+
mod_dir="$EAGLE_MEM_DIR/mod-tracker"
|
|
107
|
+
mkdir -p "$mod_dir" 2>/dev/null
|
|
108
|
+
mod_file="$mod_dir/${session_id}"
|
|
109
|
+
echo "$fp" >> "$mod_file"
|
|
110
|
+
# Keep only last 3 entries — use per-process tmp to avoid
|
|
111
|
+
# race when parallel PostToolUse hooks fire on same session
|
|
112
|
+
if [ -f "$mod_file" ]; then
|
|
113
|
+
_mod_tmp=$(mktemp "${mod_file}.XXXXXX" 2>/dev/null) || _mod_tmp="${mod_file}.$$"
|
|
114
|
+
tail -3 "$mod_file" > "$_mod_tmp" && mv "$_mod_tmp" "$mod_file" || rm -f "$_mod_tmp"
|
|
115
|
+
fi
|
|
116
|
+
;;
|
|
117
|
+
esac
|
|
118
|
+
fi
|
|
119
|
+
|
|
101
120
|
# ─── Dispatch to extracted responsibilities ───────────────
|
|
102
121
|
|
|
103
122
|
eagle_posttool_mirror_writes "$tool_name" "$fp" "$session_id" "$project"
|
package/hooks/pre-tool-use.sh
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# ═══════════════════════════════════════════════════════════
|
|
3
3
|
# Eagle Mem — PreToolUse hook
|
|
4
|
-
# Fires before
|
|
4
|
+
# Fires before Bash and Read tool calls
|
|
5
5
|
# 1. Surfaces feature verification checklists before git push
|
|
6
|
-
# 2.
|
|
6
|
+
# 2. Truncates noisy commands via updatedInput (curator-learned rules)
|
|
7
|
+
# 3. Detects Read-after-Edit/Write (content already in context)
|
|
8
|
+
# 4. Nudges on repeated file reads (dedup tracker)
|
|
7
9
|
# ═══════════════════════════════════════════════════════════
|
|
8
10
|
set +e
|
|
9
11
|
|
|
@@ -17,12 +19,13 @@ input=$(eagle_read_stdin)
|
|
|
17
19
|
[ -z "$input" ] && exit 0
|
|
18
20
|
|
|
19
21
|
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
|
|
20
|
-
[ "$tool_name" != "Bash" ] && exit 0
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
case "$tool_name" in
|
|
24
|
+
Bash|Read) ;;
|
|
25
|
+
*) exit 0 ;;
|
|
26
|
+
esac
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
[ -z "$cmd" ] && exit 0
|
|
28
|
+
[ ! -f "$EAGLE_MEM_DB" ] && exit 0
|
|
26
29
|
|
|
27
30
|
session_id=$(echo "$input" | jq -r '.session_id // empty')
|
|
28
31
|
cwd=$(echo "$input" | jq -r '.cwd // empty')
|
|
@@ -30,77 +33,120 @@ project=$(eagle_project_from_cwd "$cwd")
|
|
|
30
33
|
[ -z "$project" ] && exit 0
|
|
31
34
|
|
|
32
35
|
context=""
|
|
36
|
+
updated_input=""
|
|
37
|
+
|
|
38
|
+
case "$tool_name" in
|
|
39
|
+
Bash)
|
|
40
|
+
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
|
|
41
|
+
[ -z "$cmd" ] && exit 0
|
|
42
|
+
|
|
43
|
+
# ─── Feature verification on git push ─────────────────────
|
|
44
|
+
|
|
45
|
+
case "$cmd" in
|
|
46
|
+
*"git push"*|*"gh pr create"*)
|
|
47
|
+
has_features=$(eagle_count_active_features "$project")
|
|
48
|
+
if [ "${has_features:-0}" -gt 0 ]; then
|
|
49
|
+
changed_files=""
|
|
50
|
+
if [ -n "$cwd" ] && [ -d "$cwd" ]; then
|
|
51
|
+
changed_files=$(git -C "$cwd" diff --name-only HEAD 2>/dev/null)
|
|
52
|
+
[ -z "$changed_files" ] && changed_files=$(git -C "$cwd" diff --cached --name-only 2>/dev/null)
|
|
53
|
+
fi
|
|
33
54
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
context
|
|
61
|
-
[ -n "$feat_smoke" ] && context+=" | smoke: $feat_smoke"
|
|
62
|
-
[ -n "$feat_deps" ] && context+=" | deps: $feat_deps"
|
|
63
|
-
if [ -n "$feat_verified" ]; then
|
|
64
|
-
context+=" | last verified: $feat_verified"
|
|
65
|
-
else
|
|
66
|
-
context+=" | never verified"
|
|
67
|
-
fi
|
|
68
|
-
context+=$'\n'
|
|
69
|
-
done <<< "$feature_hits"
|
|
70
|
-
done <<< "$changed_files"
|
|
71
|
-
|
|
72
|
-
if [ -n "$context" ]; then
|
|
73
|
-
context="Eagle Mem: This push affects the following features. After deploy, verify each works and run 'eagle-mem feature verify <name>'.
|
|
55
|
+
if [ -n "$changed_files" ]; then
|
|
56
|
+
seen_features=""
|
|
57
|
+
while IFS= read -r changed_file; do
|
|
58
|
+
[ -z "$changed_file" ] && continue
|
|
59
|
+
fname=$(basename "$changed_file")
|
|
60
|
+
|
|
61
|
+
feature_hits=$(eagle_find_feature_for_push "$project" "$fname")
|
|
62
|
+
|
|
63
|
+
while IFS='|' read -r feat_name feat_smoke feat_deps feat_verified; do
|
|
64
|
+
[ -z "$feat_name" ] && continue
|
|
65
|
+
case "$seen_features" in *"|$feat_name|"*) continue ;; esac
|
|
66
|
+
seen_features+="|$feat_name|"
|
|
67
|
+
|
|
68
|
+
context+=" - $feat_name"
|
|
69
|
+
[ -n "$feat_smoke" ] && context+=" | smoke: $feat_smoke"
|
|
70
|
+
[ -n "$feat_deps" ] && context+=" | deps: $feat_deps"
|
|
71
|
+
if [ -n "$feat_verified" ]; then
|
|
72
|
+
context+=" | last verified: $feat_verified"
|
|
73
|
+
else
|
|
74
|
+
context+=" | never verified"
|
|
75
|
+
fi
|
|
76
|
+
context+=$'\n'
|
|
77
|
+
done <<< "$feature_hits"
|
|
78
|
+
done <<< "$changed_files"
|
|
79
|
+
|
|
80
|
+
if [ -n "$context" ]; then
|
|
81
|
+
context="Eagle Mem: This push affects the following features. After deploy, verify each works and run 'eagle-mem feature verify <name>'.
|
|
74
82
|
${context}"
|
|
83
|
+
fi
|
|
75
84
|
fi
|
|
76
85
|
fi
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
esac
|
|
86
|
+
;;
|
|
87
|
+
esac
|
|
80
88
|
|
|
81
|
-
# ─── Command output filtering (learned rules) ─────────────
|
|
89
|
+
# ─── Command output filtering (learned rules) ─────────────
|
|
90
|
+
|
|
91
|
+
base_cmd=$(echo "$cmd" | awk '{print $1}' | sed 's|.*/||')
|
|
92
|
+
rule=$(eagle_get_command_rule "$project" "$base_cmd")
|
|
93
|
+
|
|
94
|
+
if [ -n "$rule" ]; then
|
|
95
|
+
IFS='|' read -r strategy max_lines reason <<< "$rule"
|
|
96
|
+
case "$strategy" in
|
|
97
|
+
truncate)
|
|
98
|
+
if [ -n "$max_lines" ] && [ "$max_lines" -gt 0 ] 2>/dev/null; then
|
|
99
|
+
case "$cmd" in
|
|
100
|
+
*"&&"*|*"||"*|*";"*)
|
|
101
|
+
context+="Eagle Mem: '${base_cmd}' produces long output (${reason}). Consider: | head -${max_lines}"
|
|
102
|
+
;;
|
|
103
|
+
*"| head"*|*"| tail"*|*"| wc"*|*"| grep"*|*">"*|*">>"*)
|
|
104
|
+
;;
|
|
105
|
+
*)
|
|
106
|
+
updated_input=$(jq -nc --arg cmd "${cmd} | head -${max_lines}" '{"command":$cmd}')
|
|
107
|
+
context+="Eagle Mem: '${base_cmd}' output is typically long (${reason}). Piped through head -${max_lines}."
|
|
108
|
+
;;
|
|
109
|
+
esac
|
|
110
|
+
fi
|
|
111
|
+
;;
|
|
112
|
+
summary)
|
|
113
|
+
context+="Eagle Mem: '${base_cmd}' is typically noisy (${reason}). Consider piping through tail or checking exit code only."
|
|
114
|
+
;;
|
|
115
|
+
esac
|
|
116
|
+
fi
|
|
117
|
+
;;
|
|
118
|
+
|
|
119
|
+
Read)
|
|
120
|
+
fp=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
|
121
|
+
if [ -n "$fp" ] && [ -n "$session_id" ] && eagle_validate_session_id "$session_id"; then
|
|
122
|
+
|
|
123
|
+
# ─── Read-after-modify detection ──────────────────────
|
|
124
|
+
mod_file="$EAGLE_MEM_DIR/mod-tracker/${session_id}"
|
|
125
|
+
if [ -f "$mod_file" ] && grep -qFx -- "$fp" "$mod_file" 2>/dev/null; then
|
|
126
|
+
context+="Eagle Mem: '$(basename "$fp")' was just edited/written — the diff is already in context from the tool output. "
|
|
127
|
+
fi
|
|
82
128
|
|
|
83
|
-
#
|
|
84
|
-
|
|
129
|
+
# ─── Read dedup tracker (soft nudge) ──────────────────
|
|
130
|
+
tracker_dir="$EAGLE_MEM_DIR/read-tracker"
|
|
131
|
+
mkdir -p "$tracker_dir" 2>/dev/null
|
|
132
|
+
tracker_file="$tracker_dir/${session_id}"
|
|
133
|
+
echo "$fp" >> "$tracker_file"
|
|
134
|
+
read_count=$(grep -cFx -- "$fp" "$tracker_file" 2>/dev/null)
|
|
135
|
+
read_count=${read_count:-0}
|
|
136
|
+
if [ "$read_count" -ge 3 ]; then
|
|
137
|
+
context+="Eagle Mem: '$(basename "$fp")' has been read ${read_count} times this session. Its contents are likely already in context."
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
;;
|
|
141
|
+
esac
|
|
85
142
|
|
|
86
|
-
|
|
143
|
+
[ -z "$context" ] && [ -z "$updated_input" ] && exit 0
|
|
87
144
|
|
|
88
|
-
if [ -n "$
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
;;
|
|
94
|
-
truncate)
|
|
95
|
-
if [ -n "$max_lines" ] && [ "$max_lines" -gt 0 ] 2>/dev/null; then
|
|
96
|
-
context+="Eagle Mem command hint: '${base_cmd}' produces long output (${reason}). Consider: ${cmd} | head -${max_lines}"
|
|
97
|
-
fi
|
|
98
|
-
;;
|
|
99
|
-
esac
|
|
145
|
+
if [ -n "$updated_input" ]; then
|
|
146
|
+
jq -nc --arg ctx "$context" --argjson ui "$updated_input" \
|
|
147
|
+
'{"hookSpecificOutput":{"hookEventName":"PreToolUse","updatedInput":$ui,"additionalContext":$ctx}}'
|
|
148
|
+
else
|
|
149
|
+
jq -nc --arg ctx "$context" '{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":$ctx}}'
|
|
100
150
|
fi
|
|
101
151
|
|
|
102
|
-
[ -z "$context" ] && exit 0
|
|
103
|
-
|
|
104
|
-
jq -nc --arg ctx "$context" '{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":$ctx}}'
|
|
105
|
-
|
|
106
152
|
exit 0
|
package/hooks/session-start.sh
CHANGED
|
@@ -61,6 +61,10 @@ if [ "$curator_schedule" = "auto" ]; then
|
|
|
61
61
|
fi
|
|
62
62
|
fi
|
|
63
63
|
|
|
64
|
+
# ─── Cleanup stale tracker files (non-blocking) ─────────────
|
|
65
|
+
find "$EAGLE_MEM_DIR/read-tracker" -type f -mtime +1 -delete 2>/dev/null &
|
|
66
|
+
find "$EAGLE_MEM_DIR/mod-tracker" -type f -mtime +1 -delete 2>/dev/null &
|
|
67
|
+
|
|
64
68
|
# ─── Version check (non-blocking) ────────────────────────────
|
|
65
69
|
|
|
66
70
|
update_notice=""
|
package/lib/db-observations.sh
CHANGED
|
@@ -52,7 +52,8 @@ eagle_get_command_rule() {
|
|
|
52
52
|
WHERE enabled = 1
|
|
53
53
|
AND (project = '$project' OR project = '')
|
|
54
54
|
AND ('$cmd' LIKE pattern OR '$cmd' = pattern)
|
|
55
|
-
ORDER BY CASE WHEN project != '' THEN 0 ELSE 1 END
|
|
55
|
+
ORDER BY CASE WHEN project != '' THEN 0 ELSE 1 END,
|
|
56
|
+
LENGTH(pattern) DESC
|
|
56
57
|
LIMIT 1;"
|
|
57
58
|
}
|
|
58
59
|
|
package/lib/db-sessions.sh
CHANGED
|
@@ -15,9 +15,9 @@ eagle_upsert_session() {
|
|
|
15
15
|
eagle_db "INSERT INTO sessions (id, project, cwd, model, source, last_activity_at)
|
|
16
16
|
VALUES ('$session_id', '$project', '$cwd', '$model', '$source', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
17
17
|
ON CONFLICT(id) DO UPDATE SET
|
|
18
|
-
cwd = COALESCE(excluded.cwd, sessions.cwd),
|
|
19
|
-
model = COALESCE(excluded.model, sessions.model),
|
|
20
|
-
source = COALESCE(excluded.source, sessions.source),
|
|
18
|
+
cwd = COALESCE(NULLIF(excluded.cwd, ''), sessions.cwd),
|
|
19
|
+
model = COALESCE(NULLIF(excluded.model, ''), sessions.model),
|
|
20
|
+
source = COALESCE(NULLIF(excluded.source, ''), sessions.source),
|
|
21
21
|
status = 'active',
|
|
22
22
|
last_activity_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now');"
|
|
23
23
|
}
|
package/lib/hooks.sh
CHANGED
|
@@ -11,7 +11,15 @@ eagle_patch_hook() {
|
|
|
11
11
|
local command="$4"
|
|
12
12
|
local description="${5:-}"
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
# Check both command AND matcher to avoid skipping entries with different matchers
|
|
15
|
+
# (e.g. PreToolUse with "Bash" vs "Read" matcher using the same script)
|
|
16
|
+
local match_query
|
|
17
|
+
if [ -n "$matcher" ]; then
|
|
18
|
+
match_query=".hooks.${event}[]? | select(.matcher == \"$matcher\" and (.hooks[]?.command == \"$command\"))"
|
|
19
|
+
else
|
|
20
|
+
match_query=".hooks.${event}[]? | select(.matcher == null and (.hooks[]?.command == \"$command\"))"
|
|
21
|
+
fi
|
|
22
|
+
if jq -e "$match_query" "$settings" &>/dev/null; then
|
|
15
23
|
[ -n "$description" ] && eagle_ok "$description ${DIM}(already registered)${RESET}"
|
|
16
24
|
return 0
|
|
17
25
|
fi
|
package/package.json
CHANGED
package/scripts/curate.sh
CHANGED
|
@@ -222,6 +222,13 @@ If no rules needed, output: NONE"
|
|
|
222
222
|
eagle_log "WARN" "Curator: skipping RULE with invalid strategy '$strategy'"
|
|
223
223
|
continue
|
|
224
224
|
;; esac
|
|
225
|
+
# Guard: reject dangerous LLM-generated patterns that match everything
|
|
226
|
+
# Require at least 2 literal characters (not just wildcards)
|
|
227
|
+
_literal_chars=$(printf '%s' "$pattern" | sed 's/[%_]//g')
|
|
228
|
+
if [ ${#_literal_chars} -lt 2 ]; then
|
|
229
|
+
eagle_log "WARN" "Curator: skipping overly broad pattern '$pattern' (needs >=2 literal chars)"
|
|
230
|
+
continue
|
|
231
|
+
fi
|
|
225
232
|
|
|
226
233
|
[ "$max_lines" = "-" ] && max_lines=""
|
|
227
234
|
|
package/scripts/install.sh
CHANGED
|
@@ -186,7 +186,11 @@ eagle_patch_hook "$SETTINGS" "UserPromptSubmit" "" \
|
|
|
186
186
|
|
|
187
187
|
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash" \
|
|
188
188
|
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
189
|
-
"PreToolUse hook"
|
|
189
|
+
"PreToolUse hook (Bash)"
|
|
190
|
+
|
|
191
|
+
eagle_patch_hook "$SETTINGS" "PreToolUse" "Read" \
|
|
192
|
+
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
193
|
+
"PreToolUse hook (Read)"
|
|
190
194
|
|
|
191
195
|
# ─── Install skills ────────────────────────────────────────
|
|
192
196
|
|
package/scripts/update.sh
CHANGED
|
@@ -76,6 +76,7 @@ if [ -f "$SETTINGS" ] && command -v jq &>/dev/null; then
|
|
|
76
76
|
eagle_patch_hook "$SETTINGS" "SessionEnd" "" "$EAGLE_MEM_DIR/hooks/session-end.sh"
|
|
77
77
|
eagle_patch_hook "$SETTINGS" "UserPromptSubmit" "" "$EAGLE_MEM_DIR/hooks/user-prompt-submit.sh"
|
|
78
78
|
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
79
|
+
eagle_patch_hook "$SETTINGS" "PreToolUse" "Read" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
79
80
|
|
|
80
81
|
eagle_ok "Hooks registered"
|
|
81
82
|
fi
|