eagle-mem 4.7.1 → 4.8.1

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.
@@ -26,6 +26,8 @@ agent=$(eagle_agent_source_from_json "$input")
26
26
  [ -z "$user_prompt" ] && exit 0
27
27
 
28
28
  project=$(eagle_project_from_cwd "$cwd")
29
+ codex_compact=0
30
+ [ "$agent" = "codex" ] && codex_compact=1
29
31
 
30
32
  # ─── Context pressure detection (turn counter since last compact) ──
31
33
  # Must run before any early exits so every prompt is counted
@@ -85,8 +87,37 @@ if [ -z "$fts_query" ]; then
85
87
  exit 0
86
88
  fi
87
89
 
90
+ # ─── Agent-run orchestration nudge ────────────────────────
91
+
92
+ lower_prompt=$(printf '%s' "$user_prompt" | tr '[:upper:]' '[:lower:]')
93
+ if printf '%s\n' "$lower_prompt" | grep -Eq '(orchestrat|worker|parallel|multi-agent|multi agent|split|lane|scope out|plan and get started|broad|full codebase|release|publish|ship)'; then
94
+ if [ "$codex_compact" -eq 1 ]; then
95
+ context+="=== Eagle Mem: Orchestration Protocol ===
96
+ For broad work, you run eagle-mem orchestrate yourself. Use durable lanes, opposite-agent workers, and concise user-visible status.
97
+ "
98
+ else
99
+ context+="=== Eagle Mem: Orchestration Protocol ===
100
+ If this request is broad enough to split into worker lanes, YOU run the orchestration commands. Do not ask the user to run them.
101
+
102
+ Use:
103
+ eagle-mem orchestrate init \"<goal>\"
104
+ eagle-mem orchestrate lane add <key> --agent codex|claude-code --desc \"<self-contained scope>\" --validate \"<command>\"
105
+ eagle-mem orchestrate lane start|block|complete <key>
106
+
107
+ Keep this mostly invisible to the user; surface only concise status or handoff when useful.
108
+ "
109
+ fi
110
+ fi
111
+
88
112
  # Search for relevant past summaries (cross-session)
89
- results=$(eagle_search_summaries "$fts_query" "$project" 3)
113
+ summary_limit=2
114
+ code_limit=3
115
+ if [ "$codex_compact" -eq 1 ]; then
116
+ summary_limit=1
117
+ code_limit=2
118
+ fi
119
+
120
+ results=$(eagle_search_summaries "$fts_query" "$project" "$summary_limit")
90
121
 
91
122
  if [ -n "$results" ]; then
92
123
  context+="=== Eagle Mem: Relevant Recall ===
@@ -94,25 +125,46 @@ if [ -n "$results" ]; then
94
125
  while IFS='|' read -r req completed learned _next_steps created_at _proj decisions gotchas key_files summary_agent; do
95
126
  [ -z "$req" ] && [ -z "$completed" ] && continue
96
127
  origin_label=$(eagle_agent_label "$summary_agent")
97
- context+="[$created_at][$origin_label] "
98
- [ -n "$req" ] && context+="$req"
99
- [ -n "$completed" ] && context+=" → $completed"
100
- [ -n "$learned" ] && context+=" (Learned: $learned)"
101
- [ -n "$decisions" ] && context+="
128
+ if [ "$codex_compact" -eq 1 ]; then
129
+ req=$(eagle_trim_text "$req" 90)
130
+ completed=$(eagle_trim_text "$completed" 150)
131
+ learned=$(eagle_trim_text "$learned" 110)
132
+ context+="- [$origin_label] "
133
+ if [ -n "$completed" ]; then
134
+ context+="$completed"
135
+ else
136
+ context+="$req"
137
+ fi
138
+ [ -n "$learned" ] && context+=" | learned: $learned"
139
+ context+="
140
+ "
141
+ else
142
+ req=$(eagle_trim_text "$req" 160)
143
+ completed=$(eagle_trim_text "$completed" 220)
144
+ learned=$(eagle_trim_text "$learned" 180)
145
+ decisions=$(eagle_trim_text "$decisions" 160)
146
+ gotchas=$(eagle_trim_text "$gotchas" 160)
147
+ key_files=$(eagle_trim_text "$key_files" 160)
148
+ context+="[$created_at][$origin_label] "
149
+ [ -n "$req" ] && context+="$req"
150
+ [ -n "$completed" ] && context+=" → $completed"
151
+ [ -n "$learned" ] && context+=" (Learned: $learned)"
152
+ [ -n "$decisions" ] && context+="
102
153
  Decisions: $decisions"
103
- [ -n "$gotchas" ] && context+="
154
+ [ -n "$gotchas" ] && context+="
104
155
  Gotchas: $gotchas"
105
- [ -n "$key_files" ] && context+="
156
+ [ -n "$key_files" ] && context+="
106
157
  Key files: $key_files"
107
- context+="
158
+ context+="
108
159
  "
160
+ fi
109
161
  done <<< "$results"
110
162
  fi
111
163
 
112
164
  # Search indexed code chunks (if any exist for this project)
113
165
  has_chunks=$(eagle_count_code_chunks "$project")
114
166
  if [ "${has_chunks:-0}" -gt 0 ]; then
115
- code_results=$(eagle_search_code_chunks "$fts_query" "$project" 5)
167
+ code_results=$(eagle_search_code_chunks "$fts_query" "$project" "$code_limit")
116
168
 
117
169
  if [ -n "$code_results" ]; then
118
170
  context+="=== Eagle Mem: Relevant Code ===
@@ -129,11 +181,17 @@ fi
129
181
 
130
182
  [ -z "$context" ] && exit 0
131
183
 
132
- context+="
133
- IMPORTANT: When Eagle Mem finds relevant memories or code for the user's prompt, briefly mention it at the start of your response: \"Eagle Mem recalled N relevant sessions\" or \"Eagle Mem found related code in [files]\". One line max — then proceed with the answer.
184
+ if [ "$codex_compact" -eq 1 ]; then
185
+ context+="
186
+ Use only if directly useful. If you mention it to the user, keep Eagle Mem attribution to one short line.
187
+ "
188
+ else
189
+ context+="
190
+ IMPORTANT: If directly useful, start with one short Eagle Mem attribution line, then proceed.
134
191
 
135
192
  === Eagle Mem: Persistent Memory ===
136
193
  "
194
+ fi
137
195
 
138
196
  eagle_emit_context_for_agent "$agent" "UserPromptSubmit" "$context"
139
197
  exit 0
package/lib/common.sh CHANGED
@@ -31,6 +31,11 @@ eagle_log() {
31
31
  }
32
32
 
33
33
  eagle_project_from_cwd() {
34
+ if [ -n "${EAGLE_MEM_PROJECT:-}" ]; then
35
+ echo "$EAGLE_MEM_PROJECT"
36
+ return
37
+ fi
38
+
34
39
  local cwd="${1:-$(pwd)}"
35
40
  local resolved="$cwd"
36
41
 
@@ -113,7 +118,13 @@ eagle_agent_source() {
113
118
  case "$agent" in
114
119
  codex|openai-codex) echo "codex" ;;
115
120
  claude|claude-code|cloud-code) echo "claude-code" ;;
116
- *) echo "claude-code" ;;
121
+ *)
122
+ if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${CODEX_CI:-}" ] || [ -n "${CODEX_MANAGED_BY_NPM:-}" ]; then
123
+ echo "codex"
124
+ else
125
+ echo "claude-code"
126
+ fi
127
+ ;;
117
128
  esac
118
129
  }
119
130
 
@@ -147,6 +158,22 @@ eagle_agent_label() {
147
158
  esac
148
159
  }
149
160
 
161
+ eagle_trim_text() {
162
+ local text="${1:-}"
163
+ local max="${2:-240}"
164
+
165
+ text=$(printf '%s' "$text" | tr '\n' ' ' | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//')
166
+ if [ "${#text}" -gt "$max" ] 2>/dev/null; then
167
+ if [ "$max" -gt 3 ] 2>/dev/null; then
168
+ printf '%s...' "${text:0:$((max - 3))}"
169
+ else
170
+ printf '%s' "${text:0:$max}"
171
+ fi
172
+ else
173
+ printf '%s' "$text"
174
+ fi
175
+ }
176
+
150
177
  eagle_is_shell_tool() {
151
178
  case "${1:-}" in
152
179
  Bash|exec_command|shell_command|unified_exec) return 0 ;;
@@ -190,8 +217,124 @@ eagle_emit_context_for_agent() {
190
217
  printf '%s\n' "$context"
191
218
  }
192
219
 
220
+ eagle_config_get_light() {
221
+ local section="$1"
222
+ local key="$2"
223
+ local default="${3:-}"
224
+ local cfg="${EAGLE_CONFIG_FILE:-$EAGLE_MEM_DIR/config.toml}"
225
+
226
+ if [ ! -f "$cfg" ]; then
227
+ echo "$default"
228
+ return
229
+ fi
230
+
231
+ local value
232
+ value=$(awk -v section="$section" -v key="$key" '
233
+ /^[[:space:]]*\[/ {
234
+ gsub(/[\[\][:space:]]/, "")
235
+ current = $0
236
+ }
237
+ current == section && /^[[:space:]]*[^#\[]/ {
238
+ split($0, parts, "=")
239
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[1])
240
+ if (parts[1] == key) {
241
+ val = substr($0, index($0, "=") + 1)
242
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
243
+ gsub(/^["'"'"']|["'"'"']$/, "", val)
244
+ print val
245
+ exit
246
+ }
247
+ }
248
+ ' "$cfg")
249
+
250
+ if [ -n "$value" ]; then
251
+ echo "$value"
252
+ else
253
+ echo "$default"
254
+ fi
255
+ }
256
+
257
+ eagle_token_guard_rtk_mode() {
258
+ if declare -F eagle_config_get >/dev/null 2>&1; then
259
+ eagle_config_get "token_guard" "rtk" "auto"
260
+ else
261
+ eagle_config_get_light "token_guard" "rtk" "auto"
262
+ fi
263
+ }
264
+
265
+ eagle_token_guard_raw_bash_mode() {
266
+ if declare -F eagle_config_get >/dev/null 2>&1; then
267
+ eagle_config_get "token_guard" "raw_bash" "block"
268
+ else
269
+ eagle_config_get_light "token_guard" "raw_bash" "block"
270
+ fi
271
+ }
272
+
273
+ eagle_raw_output_command_needs_guard() {
274
+ local cmd="$1"
275
+ local first
276
+ first=$(printf '%s\n' "$cmd" | awk 'NR == 1 {print $1}' | sed 's|.*/||')
277
+
278
+ case "$first" in
279
+ cat|head|tail|find|grep|rg|wc) return 0 ;;
280
+ esac
281
+
282
+ if printf '%s\n' "$cmd" \
283
+ | tr '\n' ';' \
284
+ | sed -E 's/(&&|[|][|]|;)/\
285
+ /g' \
286
+ | awk '
287
+ {
288
+ for (i = 1; i <= NF; i++) {
289
+ token = $i
290
+ sub(/^.*\//, "", token)
291
+ if (token ~ /^(cat|head|tail|find|grep|rg|wc)$/) found = 1
292
+ }
293
+ }
294
+ END { exit(found ? 0 : 1) }
295
+ '
296
+ then
297
+ return 0
298
+ fi
299
+
300
+ if printf '%s\n' "$cmd" \
301
+ | tr '\n' ';' \
302
+ | sed -E 's/(&&|[|][|]|;)/\
303
+ /g' \
304
+ | awk '
305
+ {
306
+ for (i = 1; i <= NF; i++) {
307
+ if ($i !~ /(^|\/)git$/) continue
308
+ j = i + 1
309
+ while (j <= NF && $j ~ /^-/) {
310
+ opt = $j
311
+ j++
312
+ if (opt == "-C" || opt == "-c" ||
313
+ opt == "--git-dir" || opt == "--work-tree" ||
314
+ opt == "--namespace" || opt == "--exec-path" ||
315
+ opt == "--config-env" || opt == "--super-prefix") {
316
+ j++
317
+ }
318
+ }
319
+ if ($j ~ /^(diff|show|log|blame|grep)$/) found = 1
320
+ }
321
+ }
322
+ END { exit(found ? 0 : 1) }
323
+ '
324
+ then
325
+ return 0
326
+ fi
327
+
328
+ if printf '%s\n' "$cmd" | grep -qE '\|\s*(head|tail|grep|rg|wc)\b'; then
329
+ return 0
330
+ fi
331
+
332
+ return 1
333
+ }
334
+
193
335
  eagle_rtk_rewrite_command() {
194
336
  local cmd="$1"
337
+ [ "$(eagle_token_guard_rtk_mode)" = "off" ] && return 1
195
338
  command -v rtk >/dev/null 2>&1 || return 1
196
339
 
197
340
  case "$cmd" in
@@ -464,7 +607,7 @@ _eagle_claude_md_section() {
464
607
 
465
608
  ## Eagle Mem — Persistent Memory
466
609
 
467
- Eagle Mem hooks are active in every project. SessionStart injects context (overview, recent sessions, memories, tasks, core files). Stop captures session summaries. PostToolUse mirrors memories/plans/tasks.
610
+ Eagle Mem hooks are active in every project. SessionStart injects context (overview, recent sessions, memories, tasks, orchestration lanes, core files). Stop captures session summaries. PostToolUse mirrors memories/plans/tasks.
468
611
 
469
612
  **Rule:** Before your final response in every session, emit an `<eagle-summary>` block so the Stop hook can capture a rich summary instead of just heuristics.
470
613
 
@@ -492,6 +635,7 @@ regression_risks: [risk, ...]
492
635
  - When Eagle Mem injects context at SessionStart, attribute it: "Eagle Mem recalls:"
493
636
  - Do not revert decisions surfaced by PostToolUse without asking the user
494
637
  - If Eagle Mem reports pending feature verification, verify or waive it before push/PR/publish
638
+ - For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands
495
639
  - Never put raw secrets in the summary — Eagle Mem redacts but defense in depth
496
640
  - If you contradict a loaded memory, update the memory file
497
641
  EAGLE_MD
@@ -522,6 +666,17 @@ eagle_patch_claude_md() {
522
666
  _eagle_claude_md_section >> "$claude_md"
523
667
  return 0
524
668
  fi
669
+ if ! grep -qF 'eagle-mem orchestrate' "$claude_md" 2>/dev/null; then
670
+ local tmp_md
671
+ tmp_md=$(mktemp)
672
+ awk '
673
+ { print }
674
+ /pending feature verification/ {
675
+ print "- For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands"
676
+ }
677
+ ' "$claude_md" > "$tmp_md" && mv "$tmp_md" "$claude_md"
678
+ return 0
679
+ fi
525
680
  return 1
526
681
  fi
527
682
 
@@ -558,7 +713,8 @@ regression_risks: [risk, ...]
558
713
 
559
714
  **How to apply:**
560
715
  - Attribute recalled context as "Eagle Mem recalls:" when it is injected
561
- - Use the Eagle Mem skills when relevant: `eagle-mem-search`, `eagle-mem-overview`, `eagle-mem-memories`, and `eagle-mem-tasks`
716
+ - Use the Eagle Mem skills when relevant: `eagle-mem-search`, `eagle-mem-overview`, `eagle-mem-memories`, `eagle-mem-tasks`, and `eagle-mem-orchestrate`
717
+ - For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands
562
718
  - For important decisions, preferences, gotchas, or durable project facts, explicitly include them in the `<eagle-summary>` block so Codex-originated memories become available to future Claude Code and Codex sessions
563
719
  - Do not revert Eagle Mem-surfaced decisions without asking the user
564
720
  - If Eagle Mem reports pending feature verification, verify or waive it before push/PR/publish
@@ -573,6 +729,17 @@ eagle_patch_codex_agents_md() {
573
729
  mkdir -p "$(dirname "$agents_md")"
574
730
 
575
731
  if [ -f "$agents_md" ] && grep -qF "$marker" "$agents_md" 2>/dev/null; then
732
+ if ! grep -qF 'eagle-mem orchestrate' "$agents_md" 2>/dev/null; then
733
+ local tmp_md
734
+ tmp_md=$(mktemp)
735
+ awk '
736
+ { print }
737
+ /eagle-mem-tasks/ {
738
+ print "- Use the `eagle-mem-orchestrate` skill for broad multi-agent work. YOU run `eagle-mem orchestrate`; do not ask the user to run these commands"
739
+ }
740
+ ' "$agents_md" > "$tmp_md" && mv "$tmp_md" "$agents_md"
741
+ return 0
742
+ fi
576
743
  return 1
577
744
  fi
578
745
 
package/lib/db-mirrors.sh CHANGED
@@ -23,7 +23,7 @@ eagle_capture_agent_memory() {
23
23
  body=$(cat "$file_path")
24
24
  fi
25
25
 
26
- _fm_field() { printf '%s\n' "$fm" | awk -F': *' -v k="$1" '$1==k{sub(/^[^:]+: */,""); gsub(/^"|"$/,""); print; exit}'; }
26
+ _fm_field() { awk -F': *' -v k="$1" '$1==k{sub(/^[^:]+: */,""); gsub(/^"|"$/,""); print; exit}' <<< "$fm"; }
27
27
 
28
28
  local mname mdesc mtype morigin
29
29
  mname=$(_fm_field "name")
@@ -41,7 +41,14 @@ eagle_capture_agent_memory() {
41
41
  fi
42
42
  [ -z "$mtype" ] && mtype="$agent"
43
43
  if [ -z "$mdesc" ]; then
44
- mdesc=$(printf '%s\n' "$body" | sed '/^[[:space:]]*$/d' | head -1 | cut -c1-200)
44
+ mdesc=$(awk '
45
+ /^[[:space:]]*$/ { next }
46
+ {
47
+ line = substr($0, 1, 200)
48
+ print line
49
+ exit
50
+ }
51
+ ' <<< "$body")
45
52
  fi
46
53
 
47
54
  local fp_sql proj_sql name_sql desc_sql type_sql content_sql hash_sql origin_sql agent_sql
@@ -70,6 +70,13 @@ eagle_search_code_chunks() {
70
70
  JOIN code_chunks_fts f ON f.rowid = c.id
71
71
  WHERE code_chunks_fts MATCH '$query'
72
72
  AND c.project = '$project'
73
+ AND c.file_path NOT LIKE '.playwright-mcp/%'
74
+ AND c.file_path NOT LIKE '.eagle-worktrees/%'
75
+ AND c.file_path NOT LIKE '.git/%'
76
+ AND c.file_path NOT LIKE 'node_modules/%'
77
+ AND c.file_path NOT LIKE 'dist/%'
78
+ AND c.file_path NOT LIKE 'build/%'
79
+ AND c.file_path NOT LIKE 'coverage/%'
73
80
  ORDER BY rank
74
81
  LIMIT $limit;"
75
82
  }
@@ -57,7 +57,13 @@ SELECT 'tasks_done|' || COUNT(*) FROM agent_tasks WHERE project = '$project' AND
57
57
  SELECT 'chunks|' || COUNT(*) FROM code_chunks WHERE project = '$project';
58
58
  SELECT 'observations|' || COUNT(*) FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE project = '$project');
59
59
  SELECT 'last_active|' || COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE project = '$project';
60
- SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60) FROM summaries WHERE project = '$project' ORDER BY created_at DESC LIMIT 1), '');
60
+ SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60)
61
+ FROM summaries
62
+ WHERE project = '$project'
63
+ AND COALESCE(request, '') NOT LIKE '# AGENTS.md instructions%'
64
+ AND COALESCE(request, '') NOT LIKE '<environment_context>%'
65
+ ORDER BY created_at DESC
66
+ LIMIT 1), '');
61
67
  SQL
62
68
  }
63
69
 
@@ -63,7 +63,9 @@ eagle_get_recent_summaries() {
63
63
  eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.decisions, s.gotchas, s.key_files, s.agent
64
64
  FROM summaries s
65
65
  WHERE s.project = '$project'
66
- AND s.request NOT LIKE '%<local-command-caveat>%'
66
+ AND COALESCE(s.request, '') NOT LIKE '%<local-command-caveat>%'
67
+ AND COALESCE(s.request, '') NOT LIKE '# AGENTS.md instructions%'
68
+ AND COALESCE(s.request, '') NOT LIKE '<environment_context>%'
67
69
  ORDER BY s.created_at DESC
68
70
  LIMIT $limit;"
69
71
  }
@@ -84,7 +86,9 @@ eagle_search_summaries() {
84
86
  FROM summaries s
85
87
  JOIN summaries_fts f ON f.rowid = s.id
86
88
  WHERE summaries_fts MATCH '$query'
87
- AND s.request NOT LIKE '%<local-command-caveat>%'
89
+ AND COALESCE(s.request, '') NOT LIKE '%<local-command-caveat>%'
90
+ AND COALESCE(s.request, '') NOT LIKE '# AGENTS.md instructions%'
91
+ AND COALESCE(s.request, '') NOT LIKE '<environment_context>%'
88
92
  $where_clause
89
93
  ORDER BY rank
90
94
  LIMIT $limit;"
package/lib/provider.sh CHANGED
@@ -143,6 +143,7 @@ eagle_config_init() {
143
143
  # Create config with restrictive permissions from the start (no TOCTOU window)
144
144
  (
145
145
  umask 077
146
+ mkdir -p "$EAGLE_MEM_DIR"
146
147
  cat > "$EAGLE_CONFIG_FILE" << TOML
147
148
  # Eagle Mem configuration
148
149
  # Docs: https://github.com/eagleisbatman/eagle-mem
@@ -164,6 +165,17 @@ preferred = "current"
164
165
  codex_model = ""
165
166
  claude_model = ""
166
167
 
168
+ [orchestration]
169
+ # route = "opposite" means Codex coordinates Claude workers and Claude
170
+ # coordinates Codex workers by default.
171
+ route = "opposite"
172
+ auto_worktree = "true"
173
+ worktree_root = ""
174
+ codex_worker_model = "gpt-5.5"
175
+ codex_worker_effort = "xhigh"
176
+ claude_worker_model = "claude-opus-4-7"
177
+ claude_worker_effort = "xhigh"
178
+
167
179
  [anthropic]
168
180
  # Uses ANTHROPIC_API_KEY env var for authentication
169
181
  model = "claude-haiku-4-5-20251001"
@@ -177,11 +189,20 @@ model = "gpt-4o-mini"
177
189
  schedule = "auto"
178
190
  min_sessions = 5
179
191
 
192
+ [token_guard]
193
+ # rtk: "off" disables RTK help, "auto" uses RTK when found,
194
+ # "enforce" blocks known raw-output shell commands when RTK is unavailable.
195
+ rtk = "auto"
196
+ # raw_bash: "block" blocks raw Codex shell output when an RTK rewrite exists.
197
+ # "allow" keeps RTK advisory only.
198
+ raw_bash = "block"
199
+
180
200
  [redaction]
181
201
  # Additional secret patterns (regex) beyond built-in defaults
182
202
  # extra_patterns = ["MY_CUSTOM_SECRET_.*"]
183
203
  TOML
184
204
  )
205
+ chmod 700 "$EAGLE_MEM_DIR" 2>/dev/null || true
185
206
  eagle_log "INFO" "Config initialized: provider=$provider model=$model"
186
207
  }
187
208
 
@@ -537,6 +558,19 @@ eagle_show_config() {
537
558
  echo "Claude: $(command -v claude 2>/dev/null || echo "not found")"
538
559
  fi
539
560
 
561
+ echo ""
562
+ echo "Orchestration:"
563
+ echo " Route: $(eagle_config_get "orchestration" "route" "opposite")"
564
+ echo " Worktrees: $(eagle_config_get "orchestration" "auto_worktree" "true")"
565
+ echo " Codex: $(eagle_config_get "orchestration" "codex_worker_model" "gpt-5.5") / $(eagle_config_get "orchestration" "codex_worker_effort" "xhigh")"
566
+ echo " Claude: $(eagle_config_get "orchestration" "claude_worker_model" "claude-opus-4-7") / $(eagle_config_get "orchestration" "claude_worker_effort" "xhigh")"
567
+
568
+ echo ""
569
+ echo "Token guard:"
570
+ echo " RTK mode: $(eagle_config_get "token_guard" "rtk" "auto")"
571
+ echo " Raw bash: $(eagle_config_get "token_guard" "raw_bash" "block")"
572
+ echo " RTK bin: $(command -v rtk 2>/dev/null || echo "not found")"
573
+
540
574
  echo ""
541
575
  echo "Config: $EAGLE_CONFIG_FILE"
542
576
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eagle-mem",
3
- "version": "4.7.1",
4
- "description": "Context that survives /compact for Claude Code and Codex SQLite + FTS5, no daemon, no bloat",
3
+ "version": "4.8.1",
4
+ "description": "Shared memory, release guardrails, RTK token protection, and worker lanes for Claude Code and Codex",
5
5
  "bin": {
6
6
  "eagle-mem": "bin/eagle-mem"
7
7
  },
@@ -20,6 +20,8 @@
20
20
  "sqlite",
21
21
  "fts5",
22
22
  "hooks",
23
+ "orchestration",
24
+ "rtk",
23
25
  "persistent-memory"
24
26
  ],
25
27
  "author": "eagleisbatman",
package/scripts/config.sh CHANGED
@@ -17,7 +17,32 @@ eagle_header "Config"
17
17
  subcommand="${1:-show}"
18
18
  shift 2>/dev/null || true
19
19
 
20
+ show_help() {
21
+ echo -e " ${BOLD}eagle-mem config${RESET} — Provider and token-guard settings"
22
+ echo ""
23
+ echo -e " ${BOLD}Usage:${RESET}"
24
+ echo -e " eagle-mem config ${DIM}# show current config${RESET}"
25
+ echo -e " eagle-mem config ${CYAN}init${RESET} ${DIM}# create config.toml${RESET}"
26
+ echo -e " eagle-mem config ${CYAN}set${RESET} section.key value"
27
+ echo -e " eagle-mem config ${CYAN}test${RESET} ${DIM}# test curator provider${RESET}"
28
+ echo ""
29
+ echo -e " ${BOLD}Examples:${RESET}"
30
+ echo -e " eagle-mem config set provider.type agent_cli"
31
+ echo -e " eagle-mem config set agent_cli.preferred current"
32
+ echo -e " eagle-mem config set orchestration.route opposite"
33
+ echo -e " eagle-mem config set orchestration.codex_worker_model gpt-5.5"
34
+ echo -e " eagle-mem config set orchestration.claude_worker_model claude-opus-4-7"
35
+ echo -e " eagle-mem config set token_guard.rtk enforce"
36
+ echo -e " eagle-mem config set token_guard.raw_bash block"
37
+ echo ""
38
+ exit 0
39
+ }
40
+
20
41
  case "$subcommand" in
42
+ --help|-h|help)
43
+ show_help
44
+ ;;
45
+
21
46
  init)
22
47
  eagle_config_init
23
48
  eagle_ok "Config created: $EAGLE_CONFIG_FILE"
@@ -38,8 +63,13 @@ case "$subcommand" in
38
63
  eagle_info " eagle-mem config set provider.type ollama"
39
64
  eagle_info " eagle-mem config set provider.type agent_cli"
40
65
  eagle_info " eagle-mem config set agent_cli.preferred current"
66
+ eagle_info " eagle-mem config set orchestration.route opposite"
67
+ eagle_info " eagle-mem config set orchestration.codex_worker_effort xhigh"
68
+ eagle_info " eagle-mem config set orchestration.claude_worker_effort xhigh"
41
69
  eagle_info " eagle-mem config set ollama.model mistral"
42
70
  eagle_info " eagle-mem config set anthropic.model claude-haiku-4-5-20251001"
71
+ eagle_info " eagle-mem config set token_guard.rtk enforce"
72
+ eagle_info " eagle-mem config set token_guard.raw_bash block"
43
73
  exit 1
44
74
  fi
45
75
  section="${key%%.*}"
package/scripts/health.sh CHANGED
@@ -39,6 +39,8 @@ if [ -z "$project" ]; then
39
39
  exit 1
40
40
  fi
41
41
 
42
+ eagle_ensure_db
43
+
42
44
  p_esc=$(eagle_sql_escape "$project")
43
45
 
44
46
  eagle_info "Project: ${BOLD}$project${RESET}"
@@ -145,6 +147,50 @@ else
145
147
  issues+=("Configure a provider: eagle-mem config init")
146
148
  fi
147
149
 
150
+ # ─── Token guard visibility (informational) ────────────────
151
+
152
+ rtk_mode=$(eagle_config_get "token_guard" "rtk" "auto")
153
+ raw_bash_mode=$(eagle_config_get "token_guard" "raw_bash" "block")
154
+ rtk_bin=$(command -v rtk 2>/dev/null || true)
155
+ if [ -n "$rtk_bin" ]; then
156
+ eagle_ok "Token guard: RTK $rtk_mode (${rtk_bin}), raw_bash=$raw_bash_mode"
157
+ elif [ "$rtk_mode" = "enforce" ]; then
158
+ eagle_fail "Token guard: RTK enforce enabled, but rtk not found"
159
+ issues+=("Install RTK or run: eagle-mem config set token_guard.rtk auto")
160
+ else
161
+ eagle_dim " Token guard: RTK not found (mode: $rtk_mode, raw_bash: $raw_bash_mode)"
162
+ fi
163
+
164
+ # ─── Orchestration visibility (informational) ───────────────
165
+
166
+ orch_route=$(eagle_config_get "orchestration" "route" "opposite")
167
+ orch_auto_worktree=$(eagle_config_get "orchestration" "auto_worktree" "true")
168
+ orch_worktree_root=$(eagle_config_get "orchestration" "worktree_root" "")
169
+ orch_codex_model=$(eagle_config_get "orchestration" "codex_worker_model" "gpt-5.5")
170
+ orch_codex_effort=$(eagle_config_get "orchestration" "codex_worker_effort" "xhigh")
171
+ orch_claude_model=$(eagle_config_get "orchestration" "claude_worker_model" "claude-opus-4-7")
172
+ orch_claude_effort=$(eagle_config_get "orchestration" "claude_worker_effort" "xhigh")
173
+ codex_bin=$(command -v codex 2>/dev/null || true)
174
+ claude_bin=$(command -v claude 2>/dev/null || true)
175
+
176
+ if [ -n "$codex_bin" ] && [ -n "$claude_bin" ]; then
177
+ eagle_ok "Orchestration: route=$orch_route, worktrees=$orch_auto_worktree, Codex + Claude workers available"
178
+ elif [ -n "$codex_bin" ]; then
179
+ eagle_warn "Orchestration: Codex available, Claude CLI missing"
180
+ issues+=("Install or authenticate Claude Code CLI before spawning Claude worker lanes.")
181
+ elif [ -n "$claude_bin" ]; then
182
+ eagle_warn "Orchestration: Claude available, Codex CLI missing"
183
+ issues+=("Install or authenticate Codex CLI before spawning Codex worker lanes.")
184
+ else
185
+ eagle_warn "Orchestration: worker CLIs not found"
186
+ issues+=("Install/authenticate Codex and Claude Code CLIs before using eagle-mem orchestrate spawn.")
187
+ fi
188
+
189
+ eagle_dim " Workers: codex=${orch_codex_model}/${orch_codex_effort}, claude-code=${orch_claude_model}/${orch_claude_effort}"
190
+ if [ -n "$orch_worktree_root" ]; then
191
+ eagle_dim " Worktree root: $orch_worktree_root"
192
+ fi
193
+
148
194
  # ─── 5. Data quality (10 pts) ──────────────────────────
149
195
 
150
196
  max_score=$((max_score + 10))
@@ -232,11 +278,31 @@ if [ "$JSON_OUT" -eq 1 ]; then
232
278
  --argjson enriched_summaries "${enriched_summaries:-0}" \
233
279
  --argjson features "${feature_count:-0}" \
234
280
  --arg provider "$provider" \
281
+ --arg token_guard_rtk "$rtk_mode" \
282
+ --arg token_guard_raw_bash "$raw_bash_mode" \
283
+ --arg rtk_bin "${rtk_bin:-}" \
284
+ --arg orchestration_route "$orch_route" \
285
+ --arg orchestration_auto_worktree "$orch_auto_worktree" \
286
+ --arg orchestration_worktree_root "$orch_worktree_root" \
287
+ --arg codex_worker_model "$orch_codex_model" \
288
+ --arg codex_worker_effort "$orch_codex_effort" \
289
+ --arg claude_worker_model "$orch_claude_model" \
290
+ --arg claude_worker_effort "$orch_claude_effort" \
291
+ --arg codex_bin "${codex_bin:-}" \
292
+ --arg claude_bin "${claude_bin:-}" \
235
293
  --argjson noise_pct "$noise_pct" \
236
294
  --arg last_curated "${last_curated:-never}" \
237
295
  '{project:$project, score:$score, max:$max_score, pct:$pct, grade:$grade,
238
296
  capture:{sessions:$total_sessions, summaries:$total_summaries, heuristic:$heuristic_summaries},
239
297
  enrichment:$enriched_summaries,
240
298
  features:$features, provider:$provider,
299
+ token_guard:{rtk:$token_guard_rtk, raw_bash:$token_guard_raw_bash, rtk_bin:$rtk_bin},
300
+ orchestration:{
301
+ route:$orchestration_route,
302
+ auto_worktree:$orchestration_auto_worktree,
303
+ worktree_root:$orchestration_worktree_root,
304
+ codex:{model:$codex_worker_model, effort:$codex_worker_effort, cli:$codex_bin},
305
+ claude_code:{model:$claude_worker_model, effort:$claude_worker_effort, cli:$claude_bin}
306
+ },
241
307
  noise_pct:$noise_pct, last_curated:$last_curated}' >&3
242
308
  fi