Preview instead of guessing
base context runs the same matching engine the hooks run, against text you supply, and prints what would have been injected. It is read-only and does not touch session state.
This answers most questions in one step. If base context returns nothing for the text you actually sent, the problem is upstream of the hooks entirely.
The four things that control injection
The first three are purely about triggers and content. Only the bracket layer looks at how full your context window is.
Brackets, and why the same rules keep appearing
Brackets stage injection by how deep you are into a session: FRESH, MODERATE, DEPLETED, CRITICAL. In percent mode, base reads real depletion from the live transcript and compares it againstbracket.context_window (default 200000), with thresholds at 20, 45 and 70 percent.
Why it works. Bracket rules are deliberately never deduplicated. They re-inject every prompt, on purpose, so the standing rules you care most about do not quietly erode as a conversation fills up. If you are seeing the same rules every turn, that is the feature.
The gotcha. bracket.mode absent means turns, not percent. That is deliberate: defaulting an absent key to percent would measure every older install against a 200k window, and anyone on a larger-context model would compute several times their real depletion and pin to CRITICAL permanently. New installs write the key explicitly. Verified from source at 4866996, the commit the shipped 0.13.2 binary was built from.
The one that catches everyone
Turn on the diagnostics
Run the hook by hand
session-start, user-prompt-submit, pre-tool-use, post-tool-use and stop.
The gotcha. Read stderr. It is the only place errors go.
Why errors are invisible
This is deliberate and it is the right trade: a corrupt graph or a failed extraction should never stop you working. The cost is that silent breakage can persist unnoticed, because your agent will usually not show you hook stderr. So do not infer failure from missing output. Run the hook by hand, or read the log.The audit trail
base dashboard has nothing trimming it. Check its size occasionally, or open the dashboard now and then.
The ladder, in order
1
Did you type a star command?
It short-circuits everything else for that prompt.
2
Does the domain have rules?
base rule list --domain <name>. An empty list means the trigger fires into nothing.3
Does the trigger match?
base context "<the exact text>". Substring matching is literal.4
Are you in a registered workspace?
base project list. Outside one there is no workspace graph to match against.5
Is the hook running?
Pipe JSON into
base hook <event> and read stderr.6
Is the graph healthy?
base doctor. It exits nonzero when it is not.Next
Graph health
What
base doctor checks, and how to repair or roll back.Rules and domains
Getting the trigger right in the first place.