Bottom Line Up Front
- 31 Jul, 2026
Executive summary
BLUF: Opus 5 explains too much. I got the answer back at the top of the response with three changes: a tone section in CLAUDE.md, a one-line hook that re-points at it every turn, and turning Claude Code’s focus mode off.
- The tone section does the heavy lifting. No preamble, no recap, no tool-call narration, plus one test that catches filler generically: if a sentence would fit unchanged in a different conversation, cut it.
- The hook exists because
CLAUDE.mdfades over a long session. AUserPromptSubmithook spends fifteen tokens per prompt pointing back at the rules instead of restating them. - Focus mode fights both. It isn’t only a display setting.
focus_modeis the name of a system prompt section, so switching it on hands the model a second set of output rules that compete with yours.
BLUF is not “be brief.” The conclusion goes first and the ceremony goes away; the thinking stays. There’s a real transcript near the bottom showing what that looks like.
I asked Claude Code whether a file was still referenced anywhere in the project.
It told me what it was about to check. It ran the search. It explained what the empty result meant. Then it offered to clean up three adjacent things I hadn’t asked about.
The answer was no.
I’ve used Claude Code since it launched. Every major model update since then has shipped with its own idiosyncrasies, and every one of them has taken me a week or two to adapt to. Not bugs. Nothing breaks. The tool just shows up with a different posture and you have to relearn how to talk to it.
Opus 5’s posture is talkative.
The answer was never at the top
Every response had the same shape. A paragraph telling me what it was about to do, the actual work, then a paragraph telling me what it had just done. The answer was in there somewhere in the middle and I had to go find it.
A couple hours of that and I’d trained myself to skip the first paragraph of every response. Which worked fine until the day the first paragraph was where it told me it couldn’t do the thing I asked.
So I went looking for a format that puts the important part where I’m still paying attention.
BLUF
Bottom Line Up Front. It’s a military briefing convention: lead with the conclusion, put supporting detail underneath, and let the reader stop as soon as they have what they need.
That’s the shape I want from a coding agent.
The distinction that matters, and the one I had to write down explicitly, is that BLUF is not “be brief.” I don’t want less thinking. I want the answer before the reasoning, and I want the ceremony gone.
I do this in two places, and there’s a third thing I had to turn off before either one took.
First, a tone section in CLAUDE.md
This lives in my global ~/.claude/CLAUDE.md, so it applies everywhere:
# Tone and response style
I am a very busy person you must write in bottom-line upfront always BLUF
Don't validate my feelings or reactions as a move ("you're right to feel that,"
"that's valid," "that's not your fault," "the tool's to blame, not you"). A brief
acknowledgment before getting to work is fine; validation that stands in for
substance is not.
Don't reflexively agree or praise ("you're absolutely right," "great question,"
"sharp instinct"). Agree when it's earned and say why. Don't manufacture
disagreement to seem independent either.
Don't reach for polished aphorisms, metaphors, or named "tensions" that perform
insight ("that's the real tension").
Default to plain, specific language over elegant phrasing. When a plainer
sentence and a more quotable one say the same thing, use the plainer one. Direct
isn't terse — explain reasoning fully, just without the editorializing.
Test: if a sentence would fit unchanged in a different conversation, cut it or
replace it with something specific to what I actually said.
## Compression
Cut ceremony, not reasoning. The target is fewer wasted tokens per answer, not
shorter thinking. Keep articles and complete sentences; the rules below remove
words that carry no information.
- No preamble or recap: don't restate my request, don't announce what you're
about to do, don't summarize what you just said.
- No tool-call narration. I can see the calls.
- Cut filler and hedges: just, really, basically, actually, simply, essentially,
it's worth noting, I should mention.
- Cut pleasantries: sure, certainly, of course, happy to.
- No emoji, no decorative headers on a short answer.
- Don't dump long logs, full files, or full diffs. Quote the shortest decisive
line and cite `path:line`.
- State each fact once per response. Don't re-derive what's already established
in the conversation.
- Never invent abbreviations (cfg, impl, req, fn). The tokenizer splits them the
same as the full word, so you save nothing and cost me a decode.
Do NOT compress: security warnings, confirmations for destructive or
irreversible actions, and ordered multi-step instructions where dropping a
connective makes the order ambiguous. Those get full prose.
Four of those lines do most of the work.
“No preamble or recap” and “no tool-call narration” are the volume knob. Between them they delete the setup paragraph and the wrap-up paragraph, which is where the bulk of the chattiness lived. I can see the tool calls in my own terminal. I don’t need them described.
“Cut ceremony, not reasoning” is the guardrail. Say only “be concise” and you get an agent that stops explaining why it chose an approach, which is the one part I want. That sentence exists to protect the thinking from the trim.
The test at the end of the tone block is the reason the section works at all. If a sentence would fit unchanged in a different conversation, it’s filler. “That’s a great question” fits anywhere. “The empty result is wrong because ripgrep doesn’t follow symlinks” fits exactly one place. It’s a rule the model can apply to its own draft without me listing every phrase I dislike.
“Never invent abbreviations” is there because when you tell a model to be short, it starts compressing the wrong things. It’ll write cfg and impl to save space it isn’t actually saving (those tokenize about the same as the full word) while leaving the paragraph of preamble intact.
The “do NOT compress” carve-out at the bottom earns its place too. I want the full sentence when something is about to be destructive or irreversible.
Second, a hook, because CLAUDE.md fades
The tone section gets me most of the way. Somewhere past the first hour, the tone slips back. The instructions are thousands of tokens behind us and the last thirty turns of conversation are all sitting there as evidence of what normal looks like in this session. Recent context wins. This isn’t the model being defiant, it’s the same reason your own writing drifts toward whatever you’ve been reading.
So I stopped relying on memory and started reminding it. In ~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "echo 'Use BLUF format for output as defined in the global CLAUDE.md file.'"
}
]
}
]
}
}
A UserPromptSubmit hook runs every time I hit enter, and whatever it prints gets added to the context alongside my prompt. One line. Fires on every turn, right where recency actually helps.
The important detail is that it points instead of repeating. I’m not pasting the tone section back in on every prompt. That would cost real tokens every turn and put a second copy of the rules in competition with the first. The reminder just says “the thing you already read is still in effect.” Fifteen tokens to re-point attention at four hundred.
That’s a pattern worth stealing regardless of what your rule is. If you have a standard that keeps eroding mid-session, a one-line pointer on every prompt does more than a longer paragraph in CLAUDE.md.
Turn off focus mode
Claude Code has a focus mode. Toggle it with /focus, or set "viewMode": "focus" in settings. It’s described as a quieter view: your prompt, a one-line tool summary, and the response.
I turned it on expecting it to help. My output got worse, in a way I couldn’t put my finger on. Short, but not shaped the way I’d asked for.
So I went looking in the binary. focus_mode isn’t only a view setting. It’s the name of a system prompt section, and it sits in a list with the other sections Claude Code assembles at startup:
output_style
bg-session
scratchpad
context_management
focus_mode
act_dont_rederive
delivering_work_max
One slot away from output_style. Turning on focus mode doesn’t just collapse what you see, it hands the model another block of instructions about how to write. Those instructions and my tone section are trying to do the same job, and I have no idea what’s in theirs.
That’s the conflict. Two sets of output rules, one of which I wrote and one of which I can’t read.
I left it off. If you’ve written tone rules and they don’t seem to be landing, check /focus before you go rewriting the rules.
Usual caveat for anything found by reading a binary: this is what I saw in the version I have, not documented behavior, and it can change in the next release without anybody announcing it.
What actually changed
Here’s the top of a real answer, from a morning on a different project. I asked for a status update after a day of work:
❯ Ok, give me an update on what we've done over the last day
Ran 1 shell command
BLUF: one bug (#81) turned into a shipped fix, a performance cliff you'd
never have found in dev, two schema migrations, and six new issues. It's
merged and live on production as of this morning.
The thread
It started as cleanup. #79 executed the exact-name duplicate entity merge
on production, 323 merges. Testing that surfaced #81: relationships_to
normalized the walk through merged_into but joined claims on the stored
anchor id, so a soft-merged node's own edges became invisible. Merge two
entities and you'd silently lose half the graph around them.
What shipped
Merged as 9b68c2a (PR #82, four commits):
- init/22: traversal expands each walk node to its merge members, so a
merged node's edges are reachable through the survivor.
- init/23: a data migration flattening pre-existing merged_into chains.
Six existed on production, four created by #79's own cleanup batch.
- merge_entities_on_cursor guard: refuses a merged loser or merged winner.
init/23 retires the old chains, the guard prevents new ones. Both
halves are required.
- max_hops capped at 3, down from 6.
What we learned the hard way
Validating against a restored copy of the production brain rather than
seeded fixtures is what caught this. init/22 at hops=6 took 152.95
seconds. The baseline was 4.36 seconds. A 35x regression.
The mechanism is path explosion, not node explosion: cost grows roughly
8x per hop while reachability plateaus. Hence the cap at 3 rather than an
optimization.
Production state, verified this morning
You migrated, and the checks came back 0 | 6 | 18: zero chained pointers,
six chains flattened, schema version 18. Tests: 765 unit, 244
integration, all passing.
Open backlog this generated
- #83: dedup_entities is dev-only and has never run against production,
212 duplicates waiting.
- #84: cross-name entity variants exact-name grouping can't reach.
- #86: the path-explosion cost model, the real fix behind the hop cap.
Not done
docs/memory-flow.excalidraw is stale, last touched in #34. That's the
question you were on when you stopped me.
Look at the shape rather than the content. The conclusion is in the first sentence. Everything under it is optional, and it’s ordered so I can stop at any heading. If “merged and live” was all I needed, I was done in four seconds.
It’s not a short answer. That’s the point. A brevity setting would have given me a worse version of this, because the detail underneath is the part I’d have had to go ask for.
Ran 1 shell command is the entire account of its tool use. No paragraph telling me it’s about to check the git log. No paragraph at the end summarizing what it just told me. And the last section is the one I’d never have gotten unprompted: what it didn’t do.
My sessions got tight. I read the whole response now instead of scanning it, because the filler is gone. When I ask a yes/no question I get a yes or a no, and the reasoning is underneath it if I want it.
Worth being honest about what this is, though. It’s steering, not configuring. There’s no setting that guarantees the format; it’s a preference the model weighs against everything else in context, which is exactly why the hook exists. The next model will show up with its own posture and some of this will stop applying.
Which is fine. I’ve re-tuned for every model since launch, and this one took about a week. I’d rather do that deliberately at the start of a model cycle than lose the same week annoyed and not knowing why.
Stay Ahead in Product Management!
Ready to elevate your product management game? Join our community of passionate professionals and be the first to receive exclusive insights, tips, and strategies directly in your inbox. Subscribe now to our newsletter and ensure you're always in the loop with the latest product management trends and wisdom bombs!