Summary
hooks/session-directive.mjs renders the session-resume directive injected at SessionStart. Its ## Data References section inlines every captured tool-output (grouped.data) into the context block — at both render sites. On a long agentic session (hundreds of tool calls) this adds ~10K tokens to every session start / resume.
This contradicts context-mode's own headline principle, stated in the same SessionStart block it ships (<context_window_protection>):
Every byte a tool returns enters your conversation memory and costs reasoning capacity… the context-mode tools let you do the work in a sandbox and surface only the derived answer — the raw bytes stay out.
The captured outputs are already in the sandbox and queryable via ctx_search — inlining all of them verbatim into the resume directive is exactly the raw-bytes-in-context cost the plugin exists to avoid.
Evidence
hooks/session-directive.mjs, two sites:
// site 1 (lines/array builder) — uncapped, full blob per entry
if (grouped.data?.length > 0) {
lines.push("## Data References");
lines.push("");
for (const ev of grouped.data) lines.push(`- ${ev.data}`);
lines.push("");
}
// site 2 (block builder) — 150-char-capped per entry, but still ALL entries
if (grouped.data?.length > 0) {
block += `\n## Data References`;
for (const ev of grouped.data) {
const text = ev.data.length > 150 ? ev.data.substring(0, 147) + "..." : ev.data;
block += `\n- ${text}`;
}
block += `\n`;
}
Observed: a single long session rendered a ## Data References section of hundreds of full tool-result JSON blobs ({"stdout":"...","stderr":"","interrupted":false,...}), ~10K tokens, injected on every SessionStart.
Proposed fix
Cap the inline rendering to the most recent N captures (e.g. 8) plus a one-line pointer; the rest stay queryable via ctx_search:
if (grouped.data?.length > 0) {
lines.push("## Data References");
lines.push("");
const recent = grouped.data.slice(-8);
for (const ev of recent) lines.push(`- ${ev.data}`);
if (grouped.data.length > recent.length) {
lines.push(`- … ${grouped.data.length - recent.length} older captures — query with ctx_search (kept in the sandbox).`);
}
lines.push("");
}
This keeps recent resume context, preserves full searchability, and aligns the resume directive with the plugin's own raw-bytes-stay-out principle.
Related: the ## Git section can also grow large on long sessions and may warrant a similar cap.
Summary
hooks/session-directive.mjsrenders the session-resume directive injected at SessionStart. Its## Data Referencessection inlines every captured tool-output (grouped.data) into the context block — at both render sites. On a long agentic session (hundreds of tool calls) this adds ~10K tokens to every session start / resume.This contradicts context-mode's own headline principle, stated in the same SessionStart block it ships (
<context_window_protection>):The captured outputs are already in the sandbox and queryable via
ctx_search— inlining all of them verbatim into the resume directive is exactly the raw-bytes-in-context cost the plugin exists to avoid.Evidence
hooks/session-directive.mjs, two sites:Observed: a single long session rendered a
## Data Referencessection of hundreds of full tool-result JSON blobs ({"stdout":"...","stderr":"","interrupted":false,...}), ~10K tokens, injected on every SessionStart.Proposed fix
Cap the inline rendering to the most recent N captures (e.g. 8) plus a one-line pointer; the rest stay queryable via
ctx_search:This keeps recent resume context, preserves full searchability, and aligns the resume directive with the plugin's own raw-bytes-stay-out principle.
Related: the
## Gitsection can also grow large on long sessions and may warrant a similar cap.