eagle-mem 3.2.0 → 4.0.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 +45 -131
- package/bin/eagle-mem +2 -11
- 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 +53 -69
- package/lib/db-observations.sh +2 -1
- package/lib/db-sessions.sh +3 -3
- package/lib/hooks-sessionstart.sh +89 -0
- package/lib/hooks.sh +9 -1
- package/lib/provider.sh +2 -2
- package/package.json +1 -1
- package/scripts/curate.sh +7 -0
- package/scripts/help.sh +8 -20
- package/scripts/install.sh +5 -1
- package/scripts/update.sh +1 -0
- package/skills/eagle-mem-overview/SKILL.md +8 -8
- package/skills/eagle-mem-index/SKILL.md +0 -120
- package/skills/eagle-mem-prune/SKILL.md +0 -131
- package/skills/eagle-mem-scan/SKILL.md +0 -116
package/README.md
CHANGED
|
@@ -12,183 +12,97 @@ Persistent memory for [Claude Code](https://docs.anthropic.com/en/docs/claude-co
|
|
|
12
12
|
|
|
13
13
|
## Getting started
|
|
14
14
|
|
|
15
|
-
**1. Install** (once — this is the only setup step):
|
|
16
|
-
|
|
17
15
|
```bash
|
|
18
16
|
npm install -g eagle-mem
|
|
19
17
|
eagle-mem install
|
|
20
18
|
```
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
That's it. Open Claude Code in any project directory. Eagle Mem activates automatically:
|
|
23
21
|
|
|
24
22
|
```
|
|
25
23
|
======================================
|
|
26
24
|
Eagle Mem Loaded
|
|
27
25
|
======================================
|
|
28
26
|
Project | my-app
|
|
29
|
-
Sessions | 42
|
|
27
|
+
Sessions | 42 (18 with summaries)
|
|
30
28
|
Memories | 7 stored
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Code Index | 156 chunks indexed
|
|
34
|
-
Observations | 340 captured
|
|
35
|
-
Last Active | 2026-04-28
|
|
29
|
+
Tasks | 1 in progress, 3 pending
|
|
30
|
+
Code Index | 156 chunks
|
|
36
31
|
Last Work | Added auth middleware with JWT validation
|
|
37
32
|
======================================
|
|
38
33
|
```
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
**3. Already have Claude Code history on a project?** Run this inside the project directory:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
cd ~/projects/my-app
|
|
46
|
-
eagle-mem refresh
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
This backfills everything into Eagle Mem:
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
Eagle Mem Refresh
|
|
53
|
-
─────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
Step 1/4: Scanning codebase structure...
|
|
56
|
-
✓ 120 files found
|
|
57
|
-
✓ Languages: TypeScript (15k lines), CSS (2k lines)
|
|
58
|
-
✓ Frameworks: Next.js, React, Tailwind, Prisma
|
|
59
|
-
✓ Scan complete
|
|
60
|
-
|
|
61
|
-
Step 2/4: Indexing source files...
|
|
62
|
-
✓ Index complete
|
|
63
|
-
|
|
64
|
-
Step 3/4: Syncing Claude Code memories, plans, and tasks...
|
|
65
|
-
✓ Memory sync complete
|
|
66
|
-
|
|
67
|
-
Step 4/4: Verifying...
|
|
68
|
-
Sessions: 12
|
|
69
|
-
Code chunks: 340
|
|
70
|
-
Memories: 8
|
|
71
|
-
Tasks: 15
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Now open Claude Code in that project — it sees your full history from the start.
|
|
35
|
+
Everything is automatic from here. Eagle Mem scans your codebase, indexes source files, captures session summaries, mirrors Claude's memories and tasks, learns which commands are noisy, and prunes stale data — all in the background via hooks.
|
|
75
36
|
|
|
76
37
|
## Commands
|
|
77
38
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
### Search past sessions
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
eagle-mem search "auth middleware"
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Searches across session summaries, Claude memories, and indexed code using FTS5. Use this when you know you worked on something last week but can't remember the details.
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
eagle-mem search --timeline
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Shows your most recent sessions in chronological order — useful for catching up after a break.
|
|
93
|
-
|
|
94
|
-
### View or set your project overview
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
eagle-mem overview
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Shows the overview that gets injected into every Claude Code session. This is what Claude reads first to understand your project.
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
eagle-mem overview set "My app is a Next.js dashboard for monitoring API health..."
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Set a custom overview. You can also let Claude write one for you by running `/eagle-mem-overview` inside a Claude Code session — it reads your README, entry points, and git history to synthesize one.
|
|
107
|
-
|
|
108
|
-
### Sync everything
|
|
39
|
+
Six commands. Three for lifecycle, three for when you need to look something up or troubleshoot.
|
|
109
40
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
| Command | When to use it |
|
|
119
|
-
|---------|---------------|
|
|
120
|
-
| `eagle-mem scan` | Re-analyze codebase structure (languages, frameworks, entry points) |
|
|
121
|
-
| `eagle-mem index` | Re-index source files for code search |
|
|
122
|
-
| `eagle-mem memories` | View or sync mirrored Claude Code memories and plans |
|
|
123
|
-
| `eagle-mem tasks` | View mirrored Claude Code tasks |
|
|
124
|
-
| `eagle-mem prune` | Clean up old observations and orphaned code chunks |
|
|
41
|
+
| Command | What it does |
|
|
42
|
+
|---------|-------------|
|
|
43
|
+
| `eagle-mem install` | First-time setup: hooks, database, skills |
|
|
44
|
+
| `eagle-mem update` | Re-deploy hooks and run migrations after `npm update` |
|
|
45
|
+
| `eagle-mem uninstall` | Remove hooks and optionally delete data |
|
|
46
|
+
| `eagle-mem search "query"` | Search past sessions, memories, and code (FTS5) |
|
|
47
|
+
| `eagle-mem health` | Diagnose pipeline health and background automation |
|
|
48
|
+
| `eagle-mem config` | View or change LLM provider settings |
|
|
125
49
|
|
|
126
50
|
## Skills (inside Claude Code)
|
|
127
51
|
|
|
128
|
-
Inside a Claude Code session, you have slash commands that let Claude do the work for you:
|
|
129
|
-
|
|
130
|
-
### `/eagle-mem-search`
|
|
131
|
-
|
|
132
|
-
Search past sessions from within Claude Code. Claude interprets results and connects them to your current work — better than raw terminal search when you need context, not just a match.
|
|
133
|
-
|
|
134
|
-
### `/eagle-mem-overview`
|
|
135
|
-
|
|
136
|
-
Build a rich project briefing. Claude reads your README, entry points, recent git history, and current codebase to write a 2-3 paragraph overview that captures what the project *does*, not just its file counts. This overview is injected at every session start.
|
|
137
|
-
|
|
138
|
-
### `/eagle-mem-tasks`
|
|
139
|
-
|
|
140
|
-
Break complex work into tasks that survive `/compact`. Uses Claude Code's native `TaskCreate`/`TaskUpdate` with dependency support. When context fills up and you compact, Eagle Mem re-injects the task state so Claude picks up where it left off.
|
|
141
|
-
|
|
142
|
-
### Other skills
|
|
143
|
-
|
|
144
52
|
| Skill | What it does |
|
|
145
53
|
|-------|-------------|
|
|
146
|
-
| `/eagle-mem-
|
|
147
|
-
| `/eagle-mem-
|
|
148
|
-
| `/eagle-mem-memories` | View
|
|
149
|
-
| `/eagle-mem-
|
|
150
|
-
|
|
151
|
-
## Updating
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
npm update -g eagle-mem
|
|
155
|
-
eagle-mem update
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
The `update` command copies new files, runs any pending database migrations, and re-registers hooks. Your data is preserved.
|
|
54
|
+
| `/eagle-mem-search` | Search memory and past sessions — Claude interprets results in context |
|
|
55
|
+
| `/eagle-mem-overview` | Build a rich project briefing from README, entry points, and git history |
|
|
56
|
+
| `/eagle-mem-memories` | View and search mirrored Claude Code memories and plans |
|
|
57
|
+
| `/eagle-mem-tasks` | TaskAware Compact Loop — break complex work into tasks that survive `/compact` |
|
|
159
58
|
|
|
160
59
|
## How it works
|
|
161
60
|
|
|
162
|
-
|
|
61
|
+
Six hooks fire automatically at different points in Claude Code's lifecycle:
|
|
163
62
|
|
|
164
63
|
| Hook | Fires when | What it does |
|
|
165
64
|
|------|-----------|--------------|
|
|
166
|
-
| **SessionStart** | startup, resume, clear, compact | Injects overview, summaries, memories, tasks |
|
|
65
|
+
| **SessionStart** | startup, resume, clear, compact | Injects overview, summaries, memories, tasks. Auto-provisions new projects (scan, index). |
|
|
66
|
+
| **PreToolUse** | before Bash and Read calls | Rewrites noisy commands (learned rules), detects redundant reads |
|
|
167
67
|
| **UserPromptSubmit** | user sends a message | FTS5 search for relevant past context |
|
|
168
|
-
| **PostToolUse** | after tool calls | Records file touches, mirrors memory/plan/task writes |
|
|
68
|
+
| **PostToolUse** | after tool calls | Records file touches, mirrors memory/plan/task writes, tracks modifications |
|
|
169
69
|
| **Stop** | Claude's turn ends | Extracts `<eagle-summary>`, strips `<private>` tags |
|
|
170
70
|
| **SessionEnd** | session closes | Re-syncs tasks, marks session completed |
|
|
171
71
|
|
|
172
|
-
|
|
72
|
+
### Background automation
|
|
73
|
+
|
|
74
|
+
These run automatically via SessionStart — no commands needed:
|
|
75
|
+
|
|
76
|
+
- **Auto-scan** — new project with no overview triggers a codebase scan
|
|
77
|
+
- **Auto-index** — new or stale project triggers FTS5 source indexing
|
|
78
|
+
- **Auto-prune** — observations over 10K rows trigger cleanup
|
|
79
|
+
- **Auto-curate** — the self-learning curator analyzes observation data and generates project-specific command rules (requires LLM provider)
|
|
80
|
+
|
|
81
|
+
### Token savings
|
|
82
|
+
|
|
83
|
+
Eagle Mem actively reduces token consumption:
|
|
84
|
+
|
|
85
|
+
- **Injection compression** — zero-value stats are elided from the banner, overview is capped, compact reloads get 1 recent session instead of 3
|
|
86
|
+
- **Command rewriting** — PreToolUse rewrites noisy Bash commands to pipe through `head -N` via `updatedInput`. Rules are learned by the curator from real usage, not hardcoded.
|
|
87
|
+
- **Read-after-modify detection** — detects when you read a file that was just edited or written, nudges that the diff is already in context
|
|
88
|
+
- **Read dedup tracking** — files read 3+ times in a session get a soft nudge
|
|
89
|
+
|
|
90
|
+
### Data
|
|
91
|
+
|
|
92
|
+
Single SQLite database at `~/.eagle-mem/memory.db` (WAL mode, FTS5 full-text search):
|
|
173
93
|
|
|
174
94
|
| Table | What it stores |
|
|
175
95
|
|-------|---------------|
|
|
176
96
|
| sessions | Active/completed sessions per project |
|
|
177
97
|
| summaries | Per-session summaries (FTS5-indexed) |
|
|
178
98
|
| observations | Per-tool-use file touch records |
|
|
179
|
-
| overviews | One overview per project (scan or manual) |
|
|
99
|
+
| overviews | One overview per project (auto-scan or manual) |
|
|
180
100
|
| code_chunks | FTS5-indexed source file chunks |
|
|
101
|
+
| command_rules | Curator-learned command output rules |
|
|
181
102
|
| claude_memories | Mirror of Claude Code auto-memories |
|
|
182
103
|
| claude_plans | Mirror of Claude Code plans |
|
|
183
104
|
| claude_tasks | Mirror of Claude Code tasks |
|
|
184
105
|
|
|
185
|
-
## Uninstall
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
eagle-mem uninstall
|
|
189
|
-
npm uninstall -g eagle-mem
|
|
190
|
-
```
|
|
191
|
-
|
|
192
106
|
## Prerequisites
|
|
193
107
|
|
|
194
108
|
- `sqlite3` with FTS5 support (ships with macOS; the installer offers to install if missing)
|
package/bin/eagle-mem
CHANGED
|
@@ -17,20 +17,11 @@ shift 2>/dev/null || true
|
|
|
17
17
|
|
|
18
18
|
case "$command" in
|
|
19
19
|
install) bash "$SCRIPTS_DIR/install.sh" "$PACKAGE_DIR" "$@" ;;
|
|
20
|
-
uninstall) bash "$SCRIPTS_DIR/uninstall.sh" "$@" ;;
|
|
21
20
|
update) bash "$SCRIPTS_DIR/update.sh" "$PACKAGE_DIR" "$@" ;;
|
|
22
|
-
|
|
23
|
-
index) bash "$SCRIPTS_DIR/index.sh" "$@" ;;
|
|
21
|
+
uninstall) bash "$SCRIPTS_DIR/uninstall.sh" "$@" ;;
|
|
24
22
|
search) bash "$SCRIPTS_DIR/search.sh" "$@" ;;
|
|
25
|
-
tasks) bash "$SCRIPTS_DIR/tasks.sh" "$@" ;;
|
|
26
|
-
overview) bash "$SCRIPTS_DIR/overview.sh" "$@" ;;
|
|
27
|
-
refresh) bash "$SCRIPTS_DIR/refresh.sh" "$@" ;;
|
|
28
|
-
prune) bash "$SCRIPTS_DIR/prune.sh" "$@" ;;
|
|
29
|
-
memories) bash "$SCRIPTS_DIR/memories.sh" "$@" ;;
|
|
30
|
-
config) bash "$SCRIPTS_DIR/config.sh" "$@" ;;
|
|
31
|
-
curate) bash "$SCRIPTS_DIR/curate.sh" "$@" ;;
|
|
32
|
-
feature) bash "$SCRIPTS_DIR/feature.sh" "$@" ;;
|
|
33
23
|
health) bash "$SCRIPTS_DIR/health.sh" "$@" ;;
|
|
24
|
+
config) bash "$SCRIPTS_DIR/config.sh" "$@" ;;
|
|
34
25
|
help|--help|-h)
|
|
35
26
|
bash "$SCRIPTS_DIR/help.sh" ;;
|
|
36
27
|
version|--version|-v|-V)
|
|
@@ -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
|