Skip to content

fix(hooks): budget session-start to the 10,000-char hook cap, keep the trailer - #291

Merged
JordanCoin merged 3 commits into
mainfrom
fix/session-start-budget
Nov 6, 2026
Merged

JordanCoin merged 3 commits into
mainfrom
fix/session-start-budget

Conversation

@JordanCoin

Copy link
Copy Markdown
Owner

Closes #288.

codemap hook session-start printed 17,134 bytes on this repository; Claude Code caps hook stdout at 10,000 characters, so the tree was cut mid-directory and the hubs, diff and intent trailer after it were lost.

  • limits/limits.go: MaxHookOutputBytes = 10000; CODEMAP_HOOK_OUTPUT_CAP overrides it.
  • cmd/hooks.go fitSessionStart: header and trailer rendered first (trailer capped at half the budget), tree re-rendered at decreasing depth until it fits, notice line (tree limited to depth N to fit the 10000-char hook cap; run codemap . for the full tree). If depth 1 is still too big the tree is cut at a line boundary. Multi-repo path uses the same cap.
  • Test: TestFitSessionStartStaysUnderHookCap with a synthetic tree growing tenfold per level.

On this repo: 17,134 -> 5,135 bytes; hubs, diff vs main and impact warnings all survive. It lands well under the cap because depth 2 is 14 KB (scanner/ is wide), so it steps to a complete depth-1 tree. A later refinement could collapse only the widest directory instead.

Known: multi-repo loop checks the total before each repo so can overshoot by one repo's share; Codex JSON escaping is not budgeted. Conflicts with #287 around the stdout-capture helper; whichever merges second rebases.

go test ./cmd/ ./render/ ./limits/ ./config/, gofmt -l clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWQw8AjoCA1yjN3T59vk46

Claude Code truncates hook stdout/additionalContext at 10,000 characters.
On this repo (380 files) session-start printed 17,134 bytes, so the tree
was cut mid-directory and the hubs, diff and handoff after it were lost.

session-start now captures the header and trailer first, reserves their
size (trailer capped at half the budget), and re-renders the tree at
decreasing depth until the whole output fits, noting the depth it settled
on. If depth 1 is still too large the tree is cut at a line boundary.
The cap is limits.MaxHookOutputBytes, overridable with
CODEMAP_HOOK_OUTPUT_CAP; the multi-repo path uses the same cap.
captureStdout is extracted from emitCodexHookContext and reused.

Closes #288

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8AjoCA1yjN3T59vk46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The change still has two active output-size bugs: multi-repository output can exceed the configured cap, and very small positive caps can produce output larger than maxBytes.

2 open issues
What changed in this PR

This pull request constrains session-start hook output to a configurable 10,000-character cap while preserving important trailer context such as hubs, diffs, and impact information.

Changes:

  • Adds the default MaxHookOutputBytes limit and CODEMAP_HOOK_OUTPUT_CAP override.
  • Budgets header, tree, and trailer output together, reducing tree depth or truncating at line boundaries when necessary.
  • Updates multi-repository handling and documents the new behavior.
  • Adds tests for depth reduction, truncation, and oversized output.
File Description
limits/​limits.go Defines the default hook output cap.
docs/​HOOKS.md Documents session-start budgeting and the environment override.
cmd/​hooks.go Captures, fits, truncates, and emits session-start output, including multi-repository handling.
cmd/​hooks_more_test.go Tests output fitting, depth reduction, line-boundary truncation, and oversized trailers.

Review effort: Lite

Comment thread cmd/hooks.go Resolved
Comment thread cmd/hooks.go Resolved
JordanCoin and others added 2 commits November 6, 2026 10:29
fitSessionStart could exceed maxBytes when the remaining tree budget was
smaller than the depth notice (any small CODEMAP_HOOK_OUTPUT_CAP), since
the header and notice were appended uncapped. The notice is now dropped
when it does not fit and the assembled output gets a final line cut at
maxBytes.

The multi-repo path only charged each child's tree against the total;
the header, setup hints, separators and truncation suffix were printed
outside the accounting. It now builds the whole output, sizes each
repo's budget from what is left (reserving room for the "more repos"
line) and applies a final cut at the cap. indexOf is no longer used.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8AjoCA1yjN3T59vk46
Resolves cmd/hooks.go against #290: keep emitHookContext (no CODEX gate) built on captureStdout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8AjoCA1yjN3T59vk46
@JordanCoin
JordanCoin merged commit a56f8a7 into main Nov 6, 2026
13 checks passed
JordanCoin added a commit that referenced this pull request Nov 6, 2026
Resolves cmd/hooks.go against #291: the collapsed package hub list now renders inside the captured session-start trailer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8AjoCA1yjN3T59vk46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session-start output (~17 KB) exceeds Claude Code's 10,000-char hook cap

2 participants