← all writing

AI Engineering

The user isn't logged in

A good friend and coworker (he runs pirate.baby) hit his limit with Claude Code last week and came to me looking for an exit. His agent had just announced, mid-session, “I need to correct myself — that clean story I told doesn’t survive contact with the grep.” He didn’t want an apology with a narrative arc. He wanted the answer. His words: how do I get out of soy hell?

What he was really asking for was a filter on the model’s register, and what he was really worried about was that installing one would hurt the code underneath. That’s the right worry, aimed at the wrong layer.

The voice is an instruction, not a personality

Claude Code ships with a long system prompt. It tells the model how to behave as an agent: when to reach for tools, how to report results, and how to talk to you while it works. The narration my friend was drowning in isn’t the model’s soul leaking through. It’s house style, written down somewhere you didn’t write it. Which is good news. You’re not deprogramming anything. You’re filing a style memo.

The fix he almost shipped

His first draft opened by telling the model to ignore its Anthropic system prompt, which he then quoted back to it, except he made the quote up (something about “sounding the part in front of non-engineers in meetings”). Funny, but two problems. Telling a model to defy its instructions frames every reply as a small act of insubordination, and models are worse at sustained rebellion than they are at following a clear target. And phrasing the whole thing as a negation keeps the behavior you hate sitting in context, freshly described, every single turn.

The part of his draft that was exactly right: he wrote a bad example and a good one. A contrastive pair is the strongest style signal you can hand a model. Keep the pair, drop the insurrection.

Put it in the layer built for this

Claude Code has a mechanism for exactly this job: output styles. One markdown file, switched on from /config under “Output style.”

---
name: Terse
description: Short, confident answers. No narration.
keep-coding-instructions: true
---

Answer like a senior engineer who trusts the reader. State the
finding, then stop. No preamble, no "let me unpack," no reflecting
my question back to me as a compliment.

Bad: "Let me unpack the honest answer, because it's a real issue
you've pinpointed. The auth gate is triggering without a proper
authorization, and that's a denial story that needs a real human fix."

Good: "The user isn't logged in."

// ~/.claude/output-styles/terse.md

The detail that answers his actual worry is in the frontmatter. An output style swaps the tone instructions and leaves the software-engineering instructions alone (keep-coding-instructions guards exactly that boundary). You’re editing how it talks, not how it works.

If a whole style file feels like commitment, there are softer options: a paragraph in ~/.claude/CLAUDE.md applies across every project on your machine, though it rides along as context rather than system instruction, so adherence is good rather than guaranteed. And --append-system-prompt does what it says, one invocation at a time, which makes it the right tool for scripts and the wrong one for your daily driver.

Whether it costs you anything

The tokens you’re deleting are narration, not reasoning. The thinking happens in the tool calls and the scratchpad; the “denial story” paragraph gets written afterward, for your benefit, on the theory that you wanted it. Run the same task with the style on and off, and diff what it built. That’s a small eval. Small evals are still evals.

The user isn’t logged in. Four words. It turns out you’re allowed to just ask for them.

Filed under AI Engineering