How We Keep Claude's Context Lean While Building CatalEx
When you build software with an AI agent day to day, the thing you run out of first isn't intelligence — it's context. The window is finite, attention inside it isn't free, and a session that starts sharp gets duller as it fills with the exhaust of the work: verbose command output, whole files read to find one function, stale documentation, the residue of three tasks ago.
So a real part of building CatalEx is context hygiene — keeping the model's window full of signal and empty of everything else. This is the setup we actually run, and how each piece is configured. The theme underneath all of it is the same one from our post on harnesses: spend context like a budget, and make every token earn its place.
The principle: tokens-per-successful-task
It's tempting to optimize the wrong number. The instinct is to minimize tokens per call — shorter prompts, fewer tools. But the metric that actually matters is tokens per successful task. A window bloated with noise makes the model reason worse, which causes correction turns, which costs far more tokens than the noise you were trying to trim.
Everything below is in service of that number. Some tools cut what enters the window; some cut what the model has to emit; some replace a large, vague context with a small, precise one. All of them are trying to get the task done in fewer total tokens by keeping the window clean, not just short.
RTK: filter command output at the source
The single biggest source of context bloat in day-to-day development is command
output. git status, npm install, a test run, a container log — these print
for humans, in full, and every character lands back in the model's context on the
next turn.
RTK (a token-optimizing CLI proxy) intercepts this at the source. It runs as
a PreToolUse hook, so it's transparent — the agent runs a normal command and
RTK rewrites it through a proxy that strips the output down to what matters
before it ever reaches the window. In our global Claude config it's wired as:
{
"hooks": {
"PreToolUse": [
{ "hooks": [{ "type": "command", "command": "rtk hook claude" }] }
]
}
}
The effect is invisible and large: routine dev operations come back 60–90%
smaller with no change to how you drive the agent. git status returns the
signal, not the decoration. When you genuinely need the raw firehose, there's an
escape hatch (rtk proxy <cmd>) that bypasses the filtering — but the default is
lean, which is the right default.
caveman: compress the conversation itself
RTK trims what tools put in; caveman trims what the model and you put into
the conversation. It's a plugin that switches communication into an
ultra-compressed mode — the tagline is "why use many token when few do trick" —
cutting roughly 75% of conversational tokens while preserving technical accuracy.
It's enabled per-repo in .claude/settings.json:
{
"enabledPlugins": { "caveman@caveman": true },
"extraKnownMarketplaces": {
"caveman": { "source": { "source": "github", "repo": "JuliusBrussee/caveman" } }
}
}
The tradeoff is real and worth stating: compression is lossy, and there are moments — subtle design discussion, careful reasoning about a tricky bug — where you want the model spending tokens, not saving them. Caveman is a lever, not a law. We lean on it for the high-volume, low-nuance stretches of work and ease off when the thinking gets delicate.
context7: fresh docs instead of stale memory (or a doc dump)
A quieter context problem is wrong context. A model's training data has a cutoff, so its memory of a fast-moving library is often months stale — and the usual fix, pasting in whole documentation pages, floods the window to answer one question.
context7 (an Upstash MCP server) solves both ends. It pulls version-specific documentation and code examples from the source on demand, so the model gets the current API for the exact version we're on, scoped to what was asked, instead of hallucinating from stale memory or drowning in a doc dump. It's enabled the same way:
{ "enabledPlugins": { "context7@claude-plugins-official": true } }
This is context management by substitution — replacing a large, unreliable context (training memory, or a pasted doc site) with a small, accurate one.
Code intelligence: read symbols, not whole files
One of the least obvious context sinks is exploration. To change one function, an agent will happily read the whole file it lives in — and the two files it imports — just to understand the types. That's a lot of tokens to answer "what's the signature of this thing."
We run language-server plugins (pyright-lsp, typescript-lsp) so the agent has
precise, symbol-level intelligence: go-to-definition, hover types, references. It
can ask "what is this symbol" and get a one-line answer instead of reading three
files to infer it. Across a working session that's an enormous saving, and it
also makes the edits more reliable — the model is acting on the actual type, not
a guess assembled from surrounding code.
Worktree isolation: keep each task's context scoped
The last piece is structural. When several pieces of work happen in parallel, their contexts bleed into each other — and a window carrying the residue of three half-finished tasks reasons worse on the one in front of it.
We use git worktrees with lifecycle hooks so each task runs in its own isolated checkout, with its environment set up and torn down automatically:
{
"hooks": {
"WorktreeCreate": [
{ "hooks": [{ "type": "command", "command": ".claude/hooks/setup-worktree.sh" }] }
],
"WorktreeRemove": [
{ "hooks": [{ "type": "command", "command": ".claude/hooks/remove-worktree.sh" }] }
]
}
}
The context benefit is that each session's window stays scoped to a single task — its files, its branch, its environment — instead of accumulating the state of everything else in flight. Isolation is a context-management technique as much as a workflow one.
The pattern across all of these: none is a clever prompt. Each is a piece of harness — a hook, a plugin, a proxy, an isolation boundary — that shapes what reaches the model. Context management isn't something you do by asking nicely in the prompt; it's something you build into the environment the agent runs in.
The shape of a lean setup
Put together, the setup layers cleanly by what it targets:
- What tools emit → RTK filters command output at the source.
- What the conversation costs → caveman compresses the exchange.
- What the model knows → context7 substitutes fresh, scoped docs for stale memory.
- What exploration costs → LSP intel answers "what is this symbol" without reading whole files.
- What leaks between tasks → worktree isolation keeps each window scoped.
Every one of them is pointed at the same number — total tokens to get the task done right — and every one is configuration, not willpower. That's the real lesson: managing context while building with Claude is the same discipline as building a good agent harness, turned around and aimed at your own development loop. Set the environment up so the window stays lean, and the model does its best work for longer before the exhaust builds up.
Written by CatalEx Engineering. We build the AI operating layer for AI-native companies — one platform to build, deploy, and run AI agents in production. More at catalex.co.