<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jonas Rohde (@edhor) — Blog</title><description>Jonas Rohde (edhor) builds product systems, mobile apps, developer tools, and AI-assisted engineering workflows. Field reports on agentic coding, plus projects and an “ask me” agent.</description><link>https://edhor.me/</link><language>en</language><atom:link href="https://edhor.me/rss.xml" rel="self" type="application/rss+xml"/><item><title>Don&apos;t look at unreviewed code</title><link>https://edhor.me/blog/dont-look-at-unreviewed-code/</link><guid isPermaLink="true">https://edhor.me/blog/dont-look-at-unreviewed-code/</guid><description>Prompts became loops, and the loop&apos;s most valuable step is the one most people skip: a review by a model from a different family, wired into the prompt itself, so findings get addressed before a human ever opens the diff.</description><pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You maybe heard about that “prompts are dead, use loops”, “loops are dead”
etc. Things really evolve daily, or it seems to.&lt;/p&gt;
&lt;p&gt;Yes, it really makes sense to adapt how you work and how you use these
tools, but don’t get distracted by these things. You need to figure out
what works best for you, what feels right and how you get the best results
for you and the team.&lt;/p&gt;
&lt;p&gt;So instead of arguing about the naming… here are the three things I would
actually defend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;don’t look at unreviewed code&lt;/li&gt;
&lt;li&gt;code → review → code (you can call that a loop)&lt;/li&gt;
&lt;li&gt;use an external / different model family for review&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rest of this post is why.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You should be the &lt;em&gt;last&lt;/em&gt; reviewer, not the first one&lt;/li&gt;
&lt;li&gt;One pass is not a loop → the value sits in the second iteration&lt;/li&gt;
&lt;li&gt;Review with a different model family, always with its most intelligent
model&lt;/li&gt;
&lt;li&gt;Put the review into the prompt as a final step, so it also addresses the
findings directly&lt;/li&gt;
&lt;li&gt;What you review changes → intent and architecture, not typos&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-you-shouldnt-be-the-first-reader&quot;&gt;Why you shouldn’t be the first reader&lt;/h2&gt;
&lt;p&gt;The workflow most people fall into is: prompt, wait, read the diff. That’s
the old habit (code appears, a human looks at it) and it wastes the
cheapest reviewer you have.&lt;/p&gt;
&lt;p&gt;If you are reading code that no model reviewed yet, two things are true at
the same time. You are doing work that could have happened before you even
came, and you are doing it on a worse draft than the one you could have
had. Every finding you catch by hand is a finding a review pass would have
caught &lt;em&gt;and fixed&lt;/em&gt; while you were doing something else.&lt;/p&gt;
&lt;p&gt;And there is a second cost which is maybe even worse. Reading raw agent
output pulls you down to the level of typos, missing null checks and style
nits… which is exactly the level where you feel productive and contribute
the least. You are the one with the context nobody else has: is this even
the right thing to build? Spending that on mechanical review is the real
waste.&lt;/p&gt;
&lt;h2 id=&quot;one-pass-is-not-a-loop&quot;&gt;One pass is not a loop&lt;/h2&gt;
&lt;p&gt;“Code → review → code” looks trivial written down, but the shape I see most
of the time is code → review → &lt;em&gt;human reads the review&lt;/em&gt;. That’s not a loop,
that’s a report.&lt;/p&gt;
&lt;p&gt;The value sits in the second iteration. A review that produces findings
nobody acts on cost you tokens and produced a document. A review whose
findings go straight back to the agent that wrote the code produces a
better artifact. And it’s fast, because that agent still has the full
context of why it did what it did.&lt;/p&gt;
&lt;p&gt;This is also where the tempting mistake is: making the loop longer instead
of tighter. Three review passes on a bad plan is still a bad plan. The loop
fixes execution quality, not direction.&lt;/p&gt;
&lt;h2 id=&quot;the-key-move-a-different-model-family&quot;&gt;The key move: a different model family&lt;/h2&gt;
&lt;p&gt;This is the one I would push the hardest, and it’s the cheapest change on
the list.&lt;/p&gt;
&lt;p&gt;Let your code be reviewed by an external agent or subagent from a different
model family, and always use the most intelligent model of it. If one
family wrote it, another family reviews it.&lt;/p&gt;
&lt;p&gt;The reason is blind spots. A model is the least likely to catch exactly the
failure modes it is prone to itself: same training, same habits, same
confident wrong turns. Ask a model to review its own output and you get a
competent sounding pass that systematically misses the category of mistake
it just made. Ask a different family and the disagreements get interesting
immediately, because they come from a different idea of what good code even
looks like.&lt;/p&gt;
&lt;p&gt;And use the strong model here, not the cheap one. Review is judgment work →
it’s the wrong place to save money, and it’s where a more capable model
pays for itself the most directly.&lt;/p&gt;
&lt;h2 id=&quot;put-it-into-the-prompt&quot;&gt;Put it into the prompt&lt;/h2&gt;
&lt;p&gt;The mechanical part that makes this actually stick: integrate that in your
prompt directly as a final step, so it’s also addressing possible
findings, even before you look at the code the first time.&lt;/p&gt;
&lt;p&gt;Not as a separate command you remember to run afterwards. As part of the
task itself.&lt;/p&gt;
&lt;p&gt;The point is not automation for the sake of it. The point is that no human
decision should sit between “code written” and “code reviewed”… because
that’s exactly the decision that gets skipped when you’re busy, which is
when you need it the most.&lt;/p&gt;
&lt;h2 id=&quot;what-kind-of-review&quot;&gt;What kind of review&lt;/h2&gt;
&lt;p&gt;“Review this code” is a weak prompt and the reviews you get back show it.
What works much better for me is steering the review to one specific lens
at a time. Three that earn their place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;a rigor pass for quality and maintainability&lt;/strong&gt; → the
&lt;code&gt;thermo-nuclear-code-review&lt;/code&gt; skill is a very sophisticated steering for
exactly that, I really like it&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;a simplification pass&lt;/strong&gt; → a completely different concern from
correctness, and generic review prompts nearly never surface it on their
own. &lt;code&gt;ponytail&lt;/code&gt; is a super nice one and also includes hooks if you want
to integrate it even further&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;a bug hunt before CI&lt;/strong&gt; → if you have a review bot in your pipeline:
running the same kind of check locally means you find things inside the
loop instead of waiting for a pipeline round-trip&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take those as examples for the &lt;em&gt;categories&lt;/em&gt;, not as a shopping list. The
tools will change. The useful part is that separate lenses give you better
findings than one review prompt that has to do everything at once.&lt;/p&gt;
&lt;h2 id=&quot;whats-left-for-you&quot;&gt;What’s left for you&lt;/h2&gt;
&lt;p&gt;None of this takes you out of the process. It moves you.&lt;/p&gt;
&lt;p&gt;You stop reviewing on the level of “this should be a const” and start
reviewing on the level of “this solves the wrong problem”, “this shouldn’t
be a new abstraction”, “this contradicts a decision we made for a reason”.
That’s the review only you can do.&lt;/p&gt;
&lt;p&gt;It also changes what review structurally &lt;em&gt;is&lt;/em&gt;: continuous, inside the loop,
happening while the work happens. Instead of a handoff at the end to a
colleague who has to context-switch into a 40 file diff. I think that shift
takes the whole pull request ceremony with it eventually, but &lt;a href=&quot;https://edhor.me/blog/we-need-to-get-over-git/&quot;&gt;that’s a
separate argument&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For now, just don’t be the first one to read it.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>agentic-coding</category><category>code-review</category><category>loops</category><category>developer-workflow</category></item><item><title>I&apos;m not the expert, and that&apos;s the point</title><link>https://edhor.me/blog/learning-in-public/</link><guid isPermaLink="true">https://edhor.me/blog/learning-in-public/</guid><description>Why I write about agentic coding without claiming to have it figured out: what I&apos;m bad at (slowing down, evaluating, finishing), why I&apos;d rather be wrong in public than fluent in a workflow that&apos;s already obsolete, and what you should expect from anything here.</description><pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the last months some people asked me for advice regarding AI and agentic
coding. They wanted to know things like: how to use these agents, my
experiences, best practices, which model to use etc.&lt;/p&gt;
&lt;p&gt;That actually increased in the last weeks, so I asked them if it would be
helpful to have a summary of things going on in that field on a regular
basis. They agreed. This blog is the public part of that.&lt;/p&gt;
&lt;p&gt;So before anything else, let me say what you are actually getting here…
because I think the framing matters more than the content that follows it.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I am not the expert on this, and I don’t think anybody is yet&lt;/li&gt;
&lt;li&gt;“Then just write it by hand” is fair today and still misses where this
goes → if the results are bad it’s most likely misusage&lt;/li&gt;
&lt;li&gt;What I’m really bad at: slowing down, recapping, evaluating&lt;/li&gt;
&lt;li&gt;Not every generated line needs to be a pull request&lt;/li&gt;
&lt;li&gt;Expect field reports with a date on them, not tutorials&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;far-away-from-being-the-expert&quot;&gt;Far away from being the expert&lt;/h2&gt;
&lt;p&gt;Let me get that out of the way first.&lt;/p&gt;
&lt;p&gt;I am far away from being the expert on agentic coding, or having a perfect
workflow, or getting mergeable code one-shotted. Or maybe even reaching
the point where I get code out of the models which is on the same quality
as I would get if I did it by hand all the time.&lt;/p&gt;
&lt;p&gt;That’s not me being humble as a rhetoric move. This whole thing is maybe
two years old in the current form and it changes monthly. Everybody
presenting a finished methodology is really just presenting a snapshot.&lt;/p&gt;
&lt;h2 id=&quot;then-just-write-it-by-hand&quot;&gt;”Then just write it by hand”&lt;/h2&gt;
&lt;p&gt;Maybe you think exactly that… and yes, maybe it would actually be faster
and maybe the results would be even better. I really get that and see the
point at the current state today.&lt;/p&gt;
&lt;p&gt;But I think we need to get over it: these frontier models can write fully
functional code on nearly the same level most of us can deliver. If the results are bad, it’s most likely a
misusage, wrong/missing/polluted context or anything else.&lt;/p&gt;
&lt;p&gt;That’s basically the reason I write any of this down. It moves the question
from “can it do this?” to “what did I actually give it?” → and the second
one you can do something about. When a model produces garbage out of a
codebase &lt;a href=&quot;https://edhor.me/blog/good-for-new-joiners-good-for-agents/&quot;&gt;where the truth is not
findable&lt;/a&gt;, or out of a session
&lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/&quot;&gt;that already rotted&lt;/a&gt;, that’s not
the limit of the model, that’s what you gave it.&lt;/p&gt;
&lt;p&gt;And that’s also happening to me… regularly. The reframe doesn’t make me
better at this, it just points me at the part I can fix.&lt;/p&gt;
&lt;h2 id=&quot;what-im-really-bad-at&quot;&gt;What I’m really bad at&lt;/h2&gt;
&lt;p&gt;I want to see what’s working, what’s not working, which model is good at
which things or not… and to be honest… I am not good at evaluation at the
moment. I am bad at slowing down, recapping and adapting, maybe because of
my ADHD, but that is something I need to get better at.&lt;/p&gt;
&lt;p&gt;I think this is the underrated skill in the whole field. Not prompting, not
picking tools. Evaluation. Actually noticing which of the twelve things you
changed last week made anything better, instead of collecting habits that
felt good in the moment. Most of us (definitely me) are running on vibes
and call it experience.&lt;/p&gt;
&lt;p&gt;Writing this on a schedule is my fix for that. It forces the recap I
normally skip, and it puts a date on everything so I can be visibly wrong
later. That’s a feature, not a bug. A workflow I described in March that I
silently dropped by July is more useful to you than a polished guide
pretending it never happened.&lt;/p&gt;
&lt;h2 id=&quot;not-everything-has-to-be-a-pull-request&quot;&gt;Not everything has to be a pull request&lt;/h2&gt;
&lt;p&gt;To be clear, I don’t say each generated LOC needs to be for a pull request
trying to get merged into production. If you don’t feel comfortable using
it for production work, use it for prototypes, use it for getting ideas,
use it for battle testing your solutions or stuff like that.&lt;/p&gt;
&lt;p&gt;And that’s not the consolation prize, that’s how you build the feeling
for when it &lt;em&gt;is&lt;/em&gt; ready for the production work. You can’t get that from reading
about it, only from watching these tools succeed and fail on problems you
understand well enough to grade yourself.&lt;/p&gt;
&lt;h2 id=&quot;we-are-all-over-the-place&quot;&gt;We are all over the place&lt;/h2&gt;
&lt;p&gt;Look around any engineering team right now and the spread is huge. Some of
us are creating a hell lot of tokens, some of us nearly nothing. Same
tools, same access, completely different usage.&lt;/p&gt;
&lt;p&gt;I don’t think that’s a discipline problem, and treating it like one is how
you get a mandate nobody follows. It’s an information problem. The people
on the low end mostly never saw what the setup looks like when it works,
and the people on the high end nearly never write down what they changed.&lt;/p&gt;
&lt;p&gt;We can and we should learn from each other here, and also make the
environment better for ourselves and also for our agents, because it turns
out that’s &lt;a href=&quot;https://edhor.me/blog/good-for-new-joiners-good-for-agents/&quot;&gt;the same work&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-thing-that-really-pushed-me&quot;&gt;The thing that really pushed me&lt;/h2&gt;
&lt;p&gt;What really impressed me lately was not an engineering team at all. It was
seeing people with no engineering background (marketing people) writing
their own skills and plugins, experimenting with it, using MCPs in
different tools, automating stuff. It’s really crazy, and it moved faster
than most engineering adoption I’ve seen.&lt;/p&gt;
&lt;p&gt;Think about that for a second, because I find it the most interesting data
point in this whole discussion: the group with the least attachment to
writing code by hand moved the fastest. That’s not a coincidence, and it’s
uncomfortable if your professional identity sits on the craft → which is
&lt;a href=&quot;https://edhor.me/blog/the-adoption-experts-who-wont-adopt/&quot;&gt;a post of its own&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It really inspired me to also go more in that direction, be even more
engaged, share more. This is part of that.&lt;/p&gt;
&lt;h2 id=&quot;what-to-expect-here&quot;&gt;What to expect here&lt;/h2&gt;
&lt;p&gt;Field reports, not tutorials. Things I tried, with a date on them, in the
state I really found them, including the parts that didn’t work.&lt;/p&gt;
&lt;p&gt;And the obvious one, which I mean seriously: don’t copy any of it blindly.
Take the observation, leave the config → &lt;a href=&quot;https://edhor.me/blog/steal-the-idea-not-the-config/&quot;&gt;there is a whole post about
that&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Actually I don’t really know where to start with all of this. I have so
much to share but don’t want to overload you, so I just start where we are
now and go one topic at a time :D&lt;/p&gt;</content:encoded><category>agentic-coding</category><category>learning-in-public</category><category>adhd</category><category>developer-culture</category></item><item><title>Orchestrate, don&apos;t operate</title><link>https://edhor.me/blog/orchestrate-dont-operate/</link><guid isPermaLink="true">https://edhor.me/blog/orchestrate-dont-operate/</guid><description>The most capable model is the most expensive one to let do grunt work. Put it in the orchestrator seat (planning, steering, judging subagent results) and hand the searching, reading, and typing to cheaper models.</description><pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every now and then a model shows up that is not just a better version of
the last one. A new generation of model, a new type of model, with a whole
new level of taste and capabilities. But it is expensive: expensive to run
and expensive to use.&lt;/p&gt;
&lt;p&gt;And then nearly everybody does the same thing, me included: you run it
exactly like you ran the one before. Same prompts, same single-agent loop,
same habits… and a bill that shows up without any of the value the model
was supposed to give you.&lt;/p&gt;
&lt;p&gt;The fix is not rationing it. The fix is putting it into a different seat.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Don’t run a new top model like you ran the old one → same usage, way more
cost, similar output&lt;/li&gt;
&lt;li&gt;Its value is taste and orchestration, not throughput&lt;/li&gt;
&lt;li&gt;Let it plan, write the subagent prompts, read the results and decide what
to redo → let cheaper models search, read and type&lt;/li&gt;
&lt;li&gt;Run it on medium or at the very most high (the levels above burn your
tokens in seconds)&lt;/li&gt;
&lt;li&gt;If your tasks are already well defined, &lt;em&gt;you&lt;/em&gt; are the orchestrator → skip
the layer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-trap&quot;&gt;The trap&lt;/h2&gt;
&lt;p&gt;The failure mode is sneaky because nothing looks wrong. You give the best
model a task, it does the whole thing itself: greps the repo, reads twenty
files, writes the boilerplate, runs the tests, fixes the lint… and the
result is good.&lt;/p&gt;
&lt;p&gt;It’s just that most of those steps produced output you can’t tell apart
from what a model at a fraction of the price would have produced. And you
paid the premium rate for all of them.&lt;/p&gt;
&lt;p&gt;Searching a codebase is not a task that rewards taste. Reading a file
isn’t. Writing the fifteenth similar handler isn’t. The expensive model is
not better at any of that in a way you can measure. It’s better at deciding
&lt;em&gt;which&lt;/em&gt; files matter, whether that fifteenth handler should exist at all,
and whether the result is actually right.&lt;/p&gt;
&lt;p&gt;So you paid for judgment and used it for searching and typing.&lt;/p&gt;
&lt;h2 id=&quot;put-it-in-the-orchestrator-seat&quot;&gt;Put it in the orchestrator seat&lt;/h2&gt;
&lt;p&gt;The pattern: the strongest model you have holds the goal, writes the
prompts for the agents doing the work, reads what comes back, and decides
what to accept, redo or throw away. It doesn’t do the work itself.&lt;/p&gt;
&lt;p&gt;Concretely that means telling it to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use cheaper models for helper tasks → searching, reading, mechanical
implementation with a clear spec. This is the single biggest cost cut
available&lt;/li&gt;
&lt;li&gt;run on medium or at the very most high → the levels above burn your
tokens in seconds and in my experience nearly never change the decision
it ends up with&lt;/li&gt;
&lt;li&gt;also use external agents → if you have more than one agent CLI around,
let it drive them non-interactively as workers. That’s also the natural
place for a &lt;a href=&quot;https://edhor.me/blog/dont-look-at-unreviewed-code/&quot;&gt;review from a different model
family&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;look at the results, not just delegate → this is what makes it
orchestration instead of a routing table&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last one is really the whole thing. The value is that it looks at the
subagents and their results and steers them, killing a bad approach after
one round instead of five.&lt;/p&gt;
&lt;p&gt;The word I keep coming back to, as weird or humanized as it sounds, is
&lt;em&gt;advisor&lt;/em&gt;. Orchestrator and advisor: it plans, it delegates, it judges, it
advises. It doesn’t type.&lt;/p&gt;
&lt;h2 id=&quot;the-important-part-tell-it-explicitly&quot;&gt;The important part: tell it explicitly&lt;/h2&gt;
&lt;p&gt;Here is the thing nobody tells you and which cost me real money to learn.&lt;/p&gt;
&lt;p&gt;Left alone, a capable model will helpfully do the work itself. That’s what
it’s trained for: you gave it a task, it completes the task. It will not
spontaneously decide that step four should go to something cheaper. It just
gets on with it, competently, at the premium rate, including every search
and every helper task on the way.&lt;/p&gt;
&lt;p&gt;So don’t let it take over a complete task itself, incl. searches and all
these helper/worker tasks → that’s how you burn your tokens. Prompt it to
be the orchestrator, explicitly, in the prompt.&lt;/p&gt;
&lt;p&gt;Without that instruction the whole pattern just doesn’t happen, and you
only notice it later on the invoice.&lt;/p&gt;
&lt;h2 id=&quot;when-to-skip-the-layer-completely&quot;&gt;When to skip the layer completely&lt;/h2&gt;
&lt;p&gt;Two-layer setups are not always right, and this is where I think people
overbuild.&lt;/p&gt;
&lt;p&gt;If you are doing a plan + implementation setup (the task is fuzzy, the
approach is not settled, somebody has to decide what “done” even means)
then yes, take the strongest model for the plan/orchestration agent. That’s
exactly the shape it is good at.&lt;/p&gt;
&lt;p&gt;But if you already have well defined tasks, you as the human are basically
the orchestrator. You did the decomposition, you know what has to happen,
there is no judgment left to delegate. Then the orchestration layer is pure
overhead, you are paying a model to forward instructions you already wrote.
Call the worker model directly.&lt;/p&gt;
&lt;p&gt;Keep the review either way. Skipping the orchestration layer means you took
over the steering, it doesn’t mean the work stops needing a second pair of
eyes from another family.&lt;/p&gt;
&lt;h2 id=&quot;why-this-really-cuts-the-bill&quot;&gt;Why this really cuts the bill&lt;/h2&gt;
&lt;p&gt;Worth being precise about the mechanism, because “use cheaper models” alone
is not the insight.&lt;/p&gt;
&lt;p&gt;The saving is not mainly the price difference between the tiers, even
though that’s real. It’s that most tokens in any bigger task go into
exploration: reading files, searching, trying something and backing out
again. That’s the bulk, and that’s exactly the part where the model tier
matters the least. The tokens that really need the strong model are a small
share: the plan, the judgment calls, the assessment of what came back.&lt;/p&gt;
&lt;p&gt;Splitting those two groups is where the cost drops a lot, and it drops
without the quality dropping → because you didn’t downgrade the decisions,
only the labour.&lt;/p&gt;
&lt;p&gt;That’s basically the whole idea: use the expensive model only for the
parts where its judgment actually shows up in the result.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>agentic-coding</category><category>orchestration</category><category>model-selection</category><category>subagents</category></item><item><title>Turn the reasoning up before you turn the model down</title><link>https://edhor.me/blog/reasoning-over-model-size/</link><guid isPermaLink="true">https://edhor.me/blog/reasoning-over-model-size/</guid><description>A smarter model needs less reasoning to reach the same answer, so it often costs less than a weaker model cranked to maximum effort. Adjust the effort dial first; change model tiers only when the dial runs out.</description><pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Short: smarter → needs less reasoning → fewer tokens for easy work →
cheaper.&lt;/p&gt;
&lt;p&gt;That sounds wrong the first time you read it, because we all learned the
opposite. Big model expensive, small model cheap… so when the budget gets
tight everybody does the same thing: switch to the smaller model and crank
the reasoning up to compensate.&lt;/p&gt;
&lt;p&gt;And that’s mostly the worst option you have.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Written in July 2026. Model names and effort levels will be outdated
pretty quickly, the mechanism won’t.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There are two dials: model tier and reasoning effort. Most people only
ever touch the first one&lt;/li&gt;
&lt;li&gt;Better adjust the reasoning level than switching to a smaller model&lt;/li&gt;
&lt;li&gt;A more capable model needs less reasoning for the same result → it can be
cheaper &lt;em&gt;and&lt;/em&gt; better at the same time&lt;/li&gt;
&lt;li&gt;Weak model + maximum effort is the worst cell in the whole grid&lt;/li&gt;
&lt;li&gt;Start strong and tune the effort down. Not the other way around.&lt;/li&gt;
&lt;li&gt;Escalating to a better model is cheaper than shipping something mediocre&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;two-dials-and-everybody-only-turns-one&quot;&gt;Two dials, and everybody only turns one&lt;/h2&gt;
&lt;p&gt;Every serious model today has some reasoning or effort setting: low,
medium, high and something above that. And most people I talk to pick a
model once, leave the effort on whatever the default was, and then treat
“which model” as the only lever they have.&lt;/p&gt;
&lt;p&gt;But the effort dial does something really different from the tier dial, and
it’s usually the one you actually want.&lt;/p&gt;
&lt;p&gt;Reasoning tokens are tokens. They get generated, they get billed, they fill
up your context. A model on maximum effort thinks a lot before it answers,
that’s the whole point. And for a task that didn’t need it you paid for
all of that thinking and got the same answer anyway.&lt;/p&gt;
&lt;h2 id=&quot;the-concrete-case&quot;&gt;The concrete case&lt;/h2&gt;
&lt;p&gt;It’s not worth it to use Sonnet on xhigh. Use Opus on medium, it’s a more
capable model, needs less reasoning for the same “intelligence” and it’s
cheaper.&lt;/p&gt;
&lt;p&gt;That’s the sentence I would put on the wall of every team getting nervous
about their usage. The smaller model on maximum effort is doing more work
to get to a worse answer, and you pay for the extra work.&lt;/p&gt;
&lt;p&gt;Why? Because reasoning is how a model compensates for not immediately
knowing. A stronger model needs fewer steps to get to the same place: you
pay for capability once, instead of paying for extra thinking on every
single task.&lt;/p&gt;
&lt;h2 id=&quot;the-worst-cell-in-the-grid&quot;&gt;The worst cell in the grid&lt;/h2&gt;
&lt;p&gt;If you lay both dials out as a grid, one square is clearly the loser:
&lt;strong&gt;weak model, maximum effort&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It burns the most tokens per task of all the small-model configurations,
it’s slow, and it still lands below what a stronger model gives you on
medium. You get the cost profile of the expensive option with the quality
profile of the cheap one.&lt;/p&gt;
&lt;p&gt;And it &lt;em&gt;feels&lt;/em&gt; responsible while you do it, which is maybe why it’s so
common. You didn’t reach for the expensive model, you were being careful.
But you weren’t, the cost just moved to a place the model dropdown
doesn’t show you.&lt;/p&gt;
&lt;h2 id=&quot;so-what-i-do-now&quot;&gt;So what I do now&lt;/h2&gt;
&lt;p&gt;The default that works for me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;take the strongest model I have access to&lt;/li&gt;
&lt;li&gt;tune the effort &lt;strong&gt;down&lt;/strong&gt; until the quality drops&lt;/li&gt;
&lt;li&gt;leave it there&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not the other way around. Starting cheap and cranking the effort up until
it works means you never find out how good the result could actually be.
You only find out how much thinking a weaker model needs to approximate
it.&lt;/p&gt;
&lt;p&gt;Nearly everything I do daily runs on medium. High is for the genuinely hard
stuff where the plan itself is the difficult part. The levels above that
burn your tokens in seconds and honestly nearly never change the decision
the model ends up with.&lt;/p&gt;
&lt;h2 id=&quot;where-this-flips&quot;&gt;Where this flips&lt;/h2&gt;
&lt;p&gt;There is one case where “just take the small model” is right: bulk
mechanical work with a fully specified spec. Migrations, mass renames, data
shape changes, the fifteenth similar handler. Intelligence buys you nothing
there because there is no judgment left in the task, somebody already made
all the decisions and volume is the only cost driver.&lt;/p&gt;
&lt;p&gt;Which is also why this fits together with putting the strong model into the
&lt;a href=&quot;https://edhor.me/blog/orchestrate-dont-operate/&quot;&gt;orchestrator seat&lt;/a&gt; instead of letting it
type. The strong model decides, the cheap ones execute the decided part.
Same principle, one level up.&lt;/p&gt;
&lt;h2 id=&quot;escalating-is-cheaper-than-shipping-bad-work&quot;&gt;Escalating is cheaper than shipping bad work&lt;/h2&gt;
&lt;p&gt;Last thing… and this one really took me the longest to accept.&lt;/p&gt;
&lt;p&gt;If a cheaper model gives you something that doesn’t meet the bar, don’t
review it, don’t patch it, don’t argue with it in three follow-up prompts.
Just run it again on a better model.&lt;/p&gt;
&lt;p&gt;Re-running a task costs a few cents. Reviewing and fixing a weak result
costs your attention, which is the actually scarce thing. And merging it
costs whoever touches that code next, forever. The price tag on the model
dropdown is the smallest number in that whole comparison and it’s the only
one we ever look at :D&lt;/p&gt;
&lt;p&gt;So: judge the output, not the price tag.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>model-selection</category><category>reasoning-effort</category><category>cost</category><category>agentic-coding</category></item><item><title>Steal the idea, not the config</title><link>https://edhor.me/blog/steal-the-idea-not-the-config/</link><guid isPermaLink="true">https://edhor.me/blog/steal-the-idea-not-the-config/</guid><description>Every shared CLAUDE.md, skill, and prompt is someone else&apos;s answer to someone else&apos;s problem. Copying it wholesale imports their constraints and taxes every session. Start vanilla, and only add what a real, felt problem justifies.</description><pubDate>Sat, 25 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Don’t blindly copy-paste anything I say or show you. Don’t do that with
stuff from anyone. Don’t blindly install skills, paste things into your
CLAUDE.md or complete prompts.&lt;/p&gt;
&lt;p&gt;See all of that stuff as ideas or inspiration. It’s like anything else in
your setup: you start somehow vanilla, and if you find something not
working for you, address that. You see optimization potential? Try it.&lt;/p&gt;
&lt;p&gt;That’s the disclaimer I put in front of everything I share… and here is why
I think it’s more than just being polite.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A shared config is someone else’s answer to a problem you maybe don’t
have&lt;/li&gt;
&lt;li&gt;Copying is not neutral-if-unused → a wrong instruction overrides what the
agent would have found out by itself&lt;/li&gt;
&lt;li&gt;Start vanilla → hit real friction → fix that specific thing → keep it
only as long as it earns its place&lt;/li&gt;
&lt;li&gt;What’s worth sharing is the observation, not the artifact&lt;/li&gt;
&lt;li&gt;Nobody ever deletes anything from these files. Do that too.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;a-config-is-an-answer-to-a-question-you-never-asked&quot;&gt;A config is an answer to a question you never asked&lt;/h2&gt;
&lt;p&gt;When somebody publishes their CLAUDE.md, a skill or a prompt library, what
you see is basically a list of things that went wrong for them. In their
repo, with their conventions, on the model they used at that time.&lt;/p&gt;
&lt;p&gt;“Always run the type-check before committing” is in there because their CI
kept breaking. “Never use barrel files” is in there because some import
cycle cost them a day. “Prefer the repository pattern” describes an
architecture you don’t even have. Take the context away and what’s left
looks like universal best practice, but is really just a list of things
that hurt them once.&lt;/p&gt;
&lt;p&gt;Which is fine, that’s exactly what makes it interesting to read. It’s just
not what makes it good to &lt;em&gt;install&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;copying-is-not-free-even-when-the-instruction-is-wrong&quot;&gt;Copying is not free, even when the instruction is wrong&lt;/h2&gt;
&lt;p&gt;This is the part people underestimate. The intuition is that a borrowed
instruction either helps or does nothing. Both halves of that are wrong.&lt;/p&gt;
&lt;p&gt;It’s not free, because everything in that file goes into every single
session, relevant or not. A big context file &lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/&quot;&gt;is a tax on every session you
will ever run&lt;/a&gt;, and the numbers we
have say these files are really easy to overuse: developer-written ones
helped a little, generated ones &lt;a href=&quot;https://edhor.me/blog/how-to-claude-md/&quot;&gt;made things slightly worse and more
expensive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And it’s not harmless when it’s wrong, because agents follow instructions
quite literally. A modern agent dropped into your repo without any guidance
goes and looks: searches, reads the actual code, figures out the actual
pattern. Now give it a confident instruction that doesn’t match your repo →
you just replaced something it would have gotten right by looking with
something it now gets wrong by obeying.&lt;/p&gt;
&lt;p&gt;You didn’t add context there, you overrode it.&lt;/p&gt;
&lt;p&gt;And nobody really calculates that trade: the upside is a bit of guidance
you maybe don’t need, the downside is your agent being confidently wrong
about your own codebase.&lt;/p&gt;
&lt;h2 id=&quot;start-vanilla-then-earn-every-addition&quot;&gt;Start vanilla, then earn every addition&lt;/h2&gt;
&lt;p&gt;So the loop I would argue for is boring and it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;start vanilla → no skills, no context file, defaults. Yes really, you
need a baseline before you can say if anything you add is an improvement&lt;/li&gt;
&lt;li&gt;work, and notice real friction → not theoretical friction, the thing that
annoyed you for the third time this week&lt;/li&gt;
&lt;li&gt;fix that specific thing → the narrowest fix for the friction you actually
felt&lt;/li&gt;
&lt;li&gt;keep it only while it earns its place → if you can’t remember why a line
is in there, that’s information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why the order matters: additions triggered by inspiration grow forever,
because nothing in that process ever removes something. Additions triggered
by pain limit themselves, because you only have so much pain.&lt;/p&gt;
&lt;p&gt;And this is also why I’m suspicious about my own setup, not only about
other people’s. To be honest… I really can’t tell you which of my
customizations are load-bearing and which are just superstition I added
once and never tested again. &lt;a href=&quot;https://edhor.me/blog/learning-in-public/&quot;&gt;Being bad at evaluating that&lt;/a&gt; is a real
problem, and stacking somebody else’s untested choices on top of my own
untested choices doesn’t make it better.&lt;/p&gt;
&lt;h2 id=&quot;so-what-is-worth-sharing&quot;&gt;So what &lt;em&gt;is&lt;/em&gt; worth sharing?&lt;/h2&gt;
&lt;p&gt;If configs don’t transfer, why write about this stuff at all?&lt;/p&gt;
&lt;p&gt;Because the part that transfers was never the file. It’s the observation
behind it: this failed for me, here is what I think happened, here is what
I changed. That survives the move to your repo, your model, your team. The
artifact doesn’t.&lt;/p&gt;
&lt;p&gt;So when you read somebody’s setup, mine included, the useful question is
not “what do I copy?” It’s “what problem was this person solving, and do I
even have it?” Usually the answer is no… and you still learned something,
because now you know that problem exists and what it looks like when it
shows up.&lt;/p&gt;
&lt;h2 id=&quot;the-habit-nobody-has-deleting&quot;&gt;The habit nobody has: deleting&lt;/h2&gt;
&lt;p&gt;Last thing, because it’s the cheapest improvement available and basically
nobody does it.&lt;/p&gt;
&lt;p&gt;These files only grow. Every one I ever saw, mine too, has instructions for
a framework that got replaced, a convention that changed, a model weakness
that got fixed two generations ago. And all of it still loads, every
session, describing a project that doesn’t exist anymore.&lt;/p&gt;
&lt;p&gt;Open yours and read it like the agent would: as a factual description of
the codebase you are about to work in. Delete everything that is not true
anymore.&lt;/p&gt;
&lt;p&gt;It’s usually more than you think, and it’s the one edit that makes the file
better in every direction at once → smaller, cheaper, and not lying
anymore.&lt;/p&gt;</content:encoded><category>claude-code</category><category>claude-md</category><category>skills</category><category>agentic-coding</category><category>ai-agents</category></item><item><title>If your codebase is good for new-joiners, it&apos;s also good for agents</title><link>https://edhor.me/blog/good-for-new-joiners-good-for-agents/</link><guid isPermaLink="true">https://edhor.me/blog/good-for-new-joiners-good-for-agents/</guid><description>A fresh agent session is structurally a new joiner: empty context, no tribal knowledge, dependent on what&apos;s discoverable. The difference is that the new joiner pays the onboarding tax once, and your agent pays it several times a day.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Starts with an empty context. Explores the repo to figure out how things
work, picks up patterns that are already deprecated, follows docs that
don’t match reality anymore… and the output needs a careful review before
you can trust it.&lt;/p&gt;
&lt;p&gt;You probably are thinking of agents, context windows, fresh sessions… but I
was talking about this new guy who joined last week.&lt;/p&gt;
&lt;p&gt;He tries to find his way through the giant codebase with 3 different ways
of styling, different UI libraries, multiple validation approaches. And
some components with “new” in the filename which are actually used nowhere. The
wiki pages he reads are outdated for at least half a year, and it takes him
a whole day (and asking multiple people) just to get the complete stack
running. Only to find out one important service he has no access to is
missing.&lt;/p&gt;
&lt;p&gt;It maybe sounds familiar. Everybody knows this is something we should clean
up, but other things have more priority, and “hey, you just have this pain
once, then you know it”.&lt;/p&gt;
&lt;p&gt;That’s true for the new joiner. His context window fills up once and stays.
But there is one guy going through this exact process multiple times a day,
with a context window that gets deleted on every fresh session… your code
agent.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A fresh agent session and a new joiner have the identical problem → no
prior knowledge, only what’s findable&lt;/li&gt;
&lt;li&gt;The difference is the frequency. The human pays that once, the agent pays
it on every new session, forever&lt;/li&gt;
&lt;li&gt;Agents are really good at self-onboarding, but only up to the quality of
what’s findable&lt;/li&gt;
&lt;li&gt;They don’t hallucinate your architecture, they infer it from the stuff
you left lying around&lt;/li&gt;
&lt;li&gt;Agent confusion doesn’t reach you as a question. It reaches you as a
mediocre diff.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-its-the-same-problem&quot;&gt;Why it’s the same problem&lt;/h2&gt;
&lt;p&gt;An agent session starts empty. It knows nothing about your project, your
conventions, or that three year old decision behind the weird adapter in
the payments module. It builds that up the only way it can: searching,
going through the code, following the links you left it… and it does that
again on the next session, and the one after that.&lt;/p&gt;
&lt;p&gt;The good news is agents are really good at this. It’s the part they are
built for: reading a lot of unfamiliar material fast and staying close to
what’s actually there instead of inventing something. A fresh session is
maybe even the better onboarder: faster, never tired, and no ego about
reading the same file for the fifth time.&lt;/p&gt;
&lt;p&gt;But that only holds as long as the material supports it. An agent finds its
way when the path from “task” to “the right file” is short, when there is
one way to do a thing instead of three half-migrated ones, when the
documentation matches the code. And when the reasoning behind non-obvious
decisions is written down somewhere the code can’t say it itself.&lt;/p&gt;
&lt;p&gt;Take that away and the agent doesn’t fail loudly. It does something worse:
it infers confidently from bad evidence. Three styling approaches in the
repo means it picks one, plausibly and defensibly… and often the
deprecated one.&lt;/p&gt;
&lt;p&gt;That’s not really a hallucination, the codebase told it wrong.&lt;/p&gt;
&lt;p&gt;And that’s also why dead code became an actual liability. A human learns at
some point that everything with “new” in the name is the abandoned rewrite.
An agent reads it as the newest and most intentional version, because
that’s literally what the name says.&lt;/p&gt;
&lt;h2 id=&quot;the-frequency-is-the-whole-argument&quot;&gt;The frequency is the whole argument&lt;/h2&gt;
&lt;p&gt;If this was only about quality, this post would be the usual “keep your
codebase clean” advice and you would have stopped reading. The thing that
changed is the multiplier.&lt;/p&gt;
&lt;p&gt;Onboarding used to be a one-time cost per person. You could rationally
decide to leave the mess and let that pain be paid by somebody new,
twice a year. The maths worked out. Now the same environment gets re-read
by a fresh context multiple times a day, by something that produces code
the whole time. A one-time tax became a recurring one and nobody redid the
calculation.&lt;/p&gt;
&lt;p&gt;And the pain is invisible, which is really the problem. When the new joiner
runs into the wall, he walks over and asks you. When the agent runs into
it, it just produces something slightly wrong and you think: &lt;em&gt;the model is
getting worse&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The feedback that would tell you your environment is broken never reaches
you as a question. It reaches you as a mediocre diff.&lt;/p&gt;
&lt;h2 id=&quot;your-new-joiner-is-a-measurement-instrument&quot;&gt;Your new joiner is a measurement instrument&lt;/h2&gt;
&lt;p&gt;Which brings me to the practical part. You can’t ask your agent what
confused it, but you can ask a human, and the answer transfers nearly
perfectly.&lt;/p&gt;
&lt;p&gt;You really can test your setup when you have new people joining. If they
have no questions at all, that reads in two very different ways: either you
did a great job, or they decided to struggle through quietly instead of
looking slow in week one. Ask them to walk you through their first day if
you want to know which one it was.&lt;/p&gt;
&lt;p&gt;If there are a lot of questions, look at what kind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“why don’t we have this?”&lt;/li&gt;
&lt;li&gt;“why is this not working?”&lt;/li&gt;
&lt;li&gt;“what do I need to install?”&lt;/li&gt;
&lt;li&gt;“something is not working as I assumed”&lt;/li&gt;
&lt;li&gt;“this readme is pretty old, is this actually up-to-date?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every single one of those is a gap between what your project claims and
what it is. And each one tells you three things at once: you are answering
out of experience that is written down nowhere, that knowledge is not
spread around the whole team either. And there is a high chance this is
also the answer why your results with agents are not as good as everybody
told you they would be.&lt;/p&gt;
&lt;p&gt;That last one is the interesting one for me. If your agents underperform,
the instinct is to reach for a better model, a longer prompt, more
tooling. Sometimes the honest answer is that you handed a competent worker
a codebase where the truth is not findable.&lt;/p&gt;
&lt;h2 id=&quot;where-the-answers-go&quot;&gt;Where the answers go&lt;/h2&gt;
&lt;p&gt;So now you have a list of questions. The tempting move is to dump every
answer into one big context file so the agent always has it.&lt;/p&gt;
&lt;p&gt;Don’t → a big CLAUDE.md &lt;a href=&quot;https://edhor.me/blog/how-to-claude-md/&quot;&gt;measurably doesn’t help and can even
hurt&lt;/a&gt;, and it &lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/&quot;&gt;is a tax on every single
session&lt;/a&gt;, no matter if the
information is relevant this time or not.&lt;/p&gt;
&lt;p&gt;Put the answer where the question was asked instead. If the confusion was
about a function, the answer is a comment above that function. If it was
about a setup step, the answer goes into the setup script, or into the
error message that fires when the step is missing. If it was about a
decision, write the &lt;em&gt;why&lt;/em&gt; next to the thing it explains. That’s the one
piece of context an agent can never derive from reading the code, because
it’s about the alternatives you rejected.&lt;/p&gt;
&lt;p&gt;That’s a full reversal for me by the way, and it took a while. I used to
treat comments as a smell. But that rule was about humans maintaining prose
they don’t want to maintain… and the reader changed. There is more about
where exactly that inverts in &lt;a href=&quot;https://edhor.me/blog/maintainable-for-whom/&quot;&gt;Maintainable for
whom?&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And while you are in there: delete the dead component, finish the half-done
migration, fix the readme. Not as a cleanup sprint. As the cheapest AI
investment you have available → no budget, no vendor, no procurement.&lt;/p&gt;
&lt;h2 id=&quot;one-effort-two-beneficiaries&quot;&gt;One effort, two beneficiaries&lt;/h2&gt;
&lt;p&gt;I like this one because you don’t have to believe anything about agents for
it to be worth doing. Making a codebase self-explaining was always the
right thing, it just never had a good enough business case against the next
feature.&lt;/p&gt;
&lt;p&gt;Now it has one. Improving the environment for a new joiner automatically
improves the environment for the coding agents and the other way around.
One effort, two beneficiaries. This is something we could work on and keep
an eye on.&lt;/p&gt;
&lt;p&gt;The agents didn’t create this problem. They just made it expensive enough
to finally care about it.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>onboarding</category><category>documentation</category><category>developer-experience</category><category>claude-code</category></item><item><title>Maintainable for whom?</title><link>https://edhor.me/blog/maintainable-for-whom/</link><guid isPermaLink="true">https://edhor.me/blog/maintainable-for-whom/</guid><description>Our whole quality vocabulary (maintainable, readable, clean) silently assumes a human will hand-edit the code later. If agents do the maintaining, the definition doesn&apos;t die, it inverts in surprising places.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If an agent is taking care of the code, what is “maintainable” even
meaning? Maintainable for humans, or for agents?&lt;/p&gt;
&lt;p&gt;That question got stuck in my head, because “but is it maintainable?” is
the most senior-sounding question in every code review. It ends
discussions. Nobody is against maintainability, like nobody is against
safety.&lt;/p&gt;
&lt;p&gt;But the word has a hidden assumption we never had to spell out. For
decades the answer was so obvious nobody asked: maintainable for a human,
with a human’s working memory, a human’s reading speed and a human’s
patience. If agents write and maintain most of the code, that assumption
breaks… and I don’t think the word gets useless then, it just needs a new
definition.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;“Maintainable” always meant “maintainable by a future human hand-editing
this file” → that part was never questioned&lt;/li&gt;
&lt;li&gt;A lot of it survives the shift: clear names, one obvious pattern,
discoverable structure help agents exactly like they help humans&lt;/li&gt;
&lt;li&gt;But some rules invert: verbosity, repetition and “too many” comments are
cheap for agents → implicit conventions and tribal knowledge, which
humans tolerate, are the deadly part now&lt;/li&gt;
&lt;li&gt;My new definition: maintainable is what a fresh context window can
safely change&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-survives&quot;&gt;What survives&lt;/h2&gt;
&lt;p&gt;The good news first: most classic maintainability advice was never really
about humans, it was about &lt;em&gt;readers&lt;/em&gt;, and agents are readers too. A fresh
agent session is &lt;a href=&quot;https://edhor.me/blog/good-for-new-joiners-good-for-agents/&quot;&gt;structurally a new
joiner&lt;/a&gt;: no tribal knowledge,
only what’s discoverable. So everything that helps a new joiner still
holds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;self-explaining names and structure&lt;/li&gt;
&lt;li&gt;one way to do a thing, not three half-migrated ones&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;why&lt;/em&gt; written down where the code can’t say it&lt;/li&gt;
&lt;li&gt;tests that state the intended behavior, not the implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your codebase is a mess, agents won’t save you. They’ll just produce
mess faster. So no, maintainability is not obsolete, it’s what the agents
themselves depend on.&lt;/p&gt;
&lt;h2 id=&quot;what-inverts&quot;&gt;What inverts&lt;/h2&gt;
&lt;p&gt;Now the uncomfortable part. Some rules we treated as timeless were
actually workarounds for human limitations, and those flip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;“Don’t repeat yourself, ever.”&lt;/strong&gt; DRY exists because humans forget to
update the second copy. An agent greps all copies in seconds. Aggressive
abstraction to save keystrokes (keystrokes are free now) often just
adds indirection a fresh context has to unwind first. Some duplication
with local clarity beats a clever abstraction three files away.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Comments are a smell.”&lt;/strong&gt; This one I really reversed on completely.
The old logic: comments drift, humans hate maintaining them, code should
speak for itself. But agents &lt;em&gt;read every comment on every session&lt;/em&gt; and
update them while they edit. An inline “why” comment is context exactly
where it’s needed, paid for exactly when it’s needed. The opposite of a
&lt;a href=&quot;https://edhor.me/blog/how-to-claude-md/&quot;&gt;bloated CLAUDE.md&lt;/a&gt; that
&lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/&quot;&gt;taxes every session&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Keep files short.”&lt;/strong&gt; Human-sized files were about scrolling and
cognitive load. For agents the unit that matters is not file length,
it’s whether a change is &lt;em&gt;local&lt;/em&gt;: can you touch this behavior without
holding five distant files in context?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Clever and compact is elegant.”&lt;/strong&gt; Nobody is reading the code for
pleasure anymore. Boring, explicit, maybe even verbose code that a model
can’t misread wins against the clever one-liner every time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the things humans tolerate best (implicit conventions, “everyone
knows we do it like this”, knowledge living in one colleague’s head) are
exactly what agents can’t survive. We optimized for the weaknesses of a
reader who is not the main reader anymore.&lt;/p&gt;
&lt;h2 id=&quot;the-new-definition&quot;&gt;The new definition&lt;/h2&gt;
&lt;p&gt;The definition I landed on for myself: &lt;strong&gt;code is maintainable if a fresh
context window can safely change it.&lt;/strong&gt; Safely meaning: find the right
place, understand the local why, make the change and verify it, without a
human feeding it tribal knowledge and without unintended blast radius.&lt;/p&gt;
&lt;p&gt;To be clear, this doesn’t mean humans stop reading code. You’ll still read
code, on the level of review, architecture and “is this actually what I
meant”. And a codebase a fresh agent can safely change is one a human can
safely read too. The reader changed, not the care.&lt;/p&gt;
&lt;p&gt;So next time “but is it maintainable?” ends a discussion, ask the hidden
question out loud: maintainable for whom? If the honest answer is “for a
kind of maintenance that stopped happening”… then maybe you are not
defending quality anymore, just a habit.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>maintainability</category><category>code-quality</category><category>agentic-coding</category><category>developer-experience</category></item><item><title>The adoption experts who won&apos;t adopt</title><link>https://edhor.me/blog/the-adoption-experts-who-wont-adopt/</link><guid isPermaLink="true">https://edhor.me/blog/the-adoption-experts-who-wont-adopt/</guid><description>Developers spent a decade complaining that users won&apos;t adopt new software. Now agents arrive, and the same people go through denial, cherry-picked failure stories, and workflow-clinging themselves. The blocker isn&apos;t capability, it&apos;s identity.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s really funny to see: the exact people who complained for years about
users not being able to adopt new software are now behaving the same with
agents.&lt;/p&gt;
&lt;p&gt;Every developer knows the complaint. We built the new system, it’s
objectively better, and the users… just won’t use it. They cling to their
Excel sheet. They ask for the old button back. They found one bug in week
one and now “the new tool doesn’t work”. We rolled our eyes at this for a
decade, gave talks about change management, built onboarding flows and
feature tours because &lt;em&gt;users resist change&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And now agents arrive in software development, and the same people (us)
go through the identical stages. Which brings me to the question this post
is actually about: &lt;strong&gt;why is this agents topic so difficult exactly in
software development?&lt;/strong&gt; I think the answer is more uncomfortable than
“developers are lazy”.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Developers are going through textbook adoption resistance: denial,
cherry-picked failure stories, clinging to the old workflow. The same
pattern we mocked our users for&lt;/li&gt;
&lt;li&gt;The blocker is not capability. Agents got good, the arguments didn’t
update&lt;/li&gt;
&lt;li&gt;The real blocker is identity: writing code is what many of us built our
professional self-image on, and agents automate exactly that part&lt;/li&gt;
&lt;li&gt;The way out is to stop being fixed on the keystrokes. You were never
paid for code, you were paid for working software&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-pattern-looks-really-familiar&quot;&gt;The pattern looks really familiar&lt;/h2&gt;
&lt;p&gt;Watch a software department meet agents and you see every stage we know
from our users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Denial:&lt;/strong&gt; “It’s just fancy autocomplete.” Said today, about tools that
plan, run tests, review their own diffs and work for hours unattended.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The one failure story:&lt;/strong&gt; “I tried it once, it hallucinated an API.
Useless.” One bug in the new system, and the old Excel sheet was
suddenly great again… remember?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflow-clinging:&lt;/strong&gt; insisting every agent change goes through the
full human-sized ceremony, so the new way is guaranteed to feel slower
than the old one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Waiting it out:&lt;/strong&gt; “Let’s see where this goes first.” A strategy that,
as far as I can tell, has never once worked for a platform shift.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a user behaved like this about our software, we would call it a change
management problem and get to work. Somehow when we do the same ourselves,
it counts as engineering rigor.&lt;/p&gt;
&lt;h2 id=&quot;its-not-about-capability&quot;&gt;It’s not about capability&lt;/h2&gt;
&lt;p&gt;First, rule out the obvious suspect. Most of the resistance arguments were
formed on models from one or two generations ago and never updated. Agents
today onboard into a codebase &lt;a href=&quot;https://edhor.me/blog/good-for-new-joiners-good-for-agents/&quot;&gt;like a professional new
joiner&lt;/a&gt;, keep their own
context, verify their work and loop with reviewers. Are they flawless? No.
Neither is any colleague you ever had. The honest comparison is not “agent
vs. perfect engineer”, it’s “agent loop with reviews vs. what your team
actually ships under deadline pressure”.&lt;/p&gt;
&lt;p&gt;But here is the thing: the capability arguments get weaker with every
model generation, and the resistance stays exactly the same. So I don’t
believe capability was ever the real argument.&lt;/p&gt;
&lt;h2 id=&quot;the-real-one-identity&quot;&gt;The real one: identity&lt;/h2&gt;
&lt;p&gt;Software developers are in a strange position: we are the first profession
watching our &lt;em&gt;craft itself&lt;/em&gt; get automated, by ourselves, with tools we
built. Writing code is not just what many developers do, it’s what they
&lt;em&gt;are&lt;/em&gt;. The years of learning, the taste, the elegance of a well-crafted
function: that’s the identity. And agents walk in and do exactly the
typing part.&lt;/p&gt;
&lt;p&gt;That’s why I think this is so much harder in software departments than
anywhere else. Nobody’s identity was “person who fills in the Excel
sheet”. But “person who writes great code”… that’s a self-image worth
defending, and people defend it with technical-sounding arguments because
those are more acceptable than “I’m scared of losing what makes me
valuable”.&lt;/p&gt;
&lt;p&gt;I get asked why I’m not more attached to writing code myself. My honest
answer, and honestly my answer to the whole debate:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why are you so fixed on writing code? I really don’t care.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I care about the idea, the product, the system that ends up existing in
the world. Code was always the means, it was never the point. And I
noticed that this sentence provokes developers way more than any benchmark
result does, which tells me we are not really arguing about tools here.&lt;/p&gt;
&lt;h2 id=&quot;treat-it-as-the-change-project-it-is&quot;&gt;Treat it as the change project it is&lt;/h2&gt;
&lt;p&gt;The funny part is that we already know the cure. It’s our own playbook,
the one we always wished management would apply to &lt;em&gt;our&lt;/em&gt; software
rollouts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don’t argue capability with people defending identity.&lt;/strong&gt; No benchmark
convinces someone whose real objection is unspoken. Address the actual
fear instead: your judgment gets &lt;em&gt;more&lt;/em&gt; valuable, not less.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wins over slides.&lt;/strong&gt; One team visibly shipping faster with agent loops
converts more colleagues than any all-hands deck.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meet the workflow where it is.&lt;/strong&gt; Users kept their Excel sheet because
the new tool ignored how they worked. Same here: forcing agent output
through unchanged human-sized ceremony guarantees it feels slower. Adapt
the process, not just the tooling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expect the dip.&lt;/strong&gt; Every adoption gets worse before it gets better.
Teams that quit in the dip “proved” it doesn’t work… the same proof our
users always brought us.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;you-were-never-paid-for-code&quot;&gt;You were never paid for code&lt;/h2&gt;
&lt;p&gt;No customer ever paid for keystrokes. They paid for working software:
problems solved, systems running, decisions encoded correctly. Everything
you actually bring (judgment, taste, architecture, knowing what &lt;em&gt;not&lt;/em&gt; to
build) becomes more valuable when the typing is free, not less. Even the
old quality instincts survive the shift, they just need a new definition
(more on that in &lt;a href=&quot;https://edhor.me/blog/maintainable-for-whom/&quot;&gt;Maintainable for whom?&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The adoption experts were right all along: resisting a platform shift
doesn’t stop it, it only decides how much say you have in how it plays
out. We knew that when it was about our users. Now it’s about us.&lt;/p&gt;</content:encoded><category>ai-agents</category><category>adoption</category><category>developer-culture</category><category>agentic-coding</category></item><item><title>We need to get over Git</title><link>https://edhor.me/blog/we-need-to-get-over-git/</link><guid isPermaLink="true">https://edhor.me/blog/we-need-to-get-over-git/</guid><description>Commits, branches, stashing, PRs: Git&apos;s ceremony is a coordination protocol for scarce human attention. Agents made work cheap and parallel, and suddenly the whole ritual feels like bureaucracy. Git the database survives; the ceremony has to go.</description><pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We need to get over Git.&lt;/p&gt;
&lt;p&gt;Last year it came into my mind: is Git really the best solution? We are
relying on it just because we’ve done it since ever, right? That was
before I created my first worktree, before this whole agentic coding era.
Even back then it somehow felt clunky, like bureaucracy: you need to
create commits (I never found a good strategy of scoping them), need to
push, somehow fight local changes against upstream, stashing, branching.
It suddenly just didn’t feel right anymore.&lt;/p&gt;
&lt;p&gt;It didn’t feel like a tool helping me build software anymore, more like
paperwork. Then agents arrived, and it got really obvious.&lt;/p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Git’s ceremony (commits, branches, stashes, PRs) is a coordination
protocol for a world where human work was expensive, serial and full of
handoffs&lt;/li&gt;
&lt;li&gt;Agents broke every one of those assumptions: work is cheap, parallel and
continuous. The ceremony didn’t adapt, it just became overhead&lt;/li&gt;
&lt;li&gt;Git the &lt;em&gt;database&lt;/em&gt; (content-addressed snapshots, distributed sync) is
fine and will survive&lt;/li&gt;
&lt;li&gt;Git the &lt;em&gt;workflow&lt;/em&gt; is what has to go, and agent harnesses are already
quietly replacing it with checkpoints, worktrees and review loops&lt;/li&gt;
&lt;li&gt;I built an experiment to test this: ChangeLedger, where the &lt;em&gt;change&lt;/em&gt; is
the primary object and a Git commit is just the export format&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-git-actually-is&quot;&gt;What Git actually is&lt;/h2&gt;
&lt;p&gt;Strip the habit away and Git is two things bolted together:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A database:&lt;/strong&gt; content-addressed snapshots of your tree, with cheap
diffing and distributed sync. This part is genuinely great.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A coordination protocol:&lt;/strong&gt; commits as units of human intention,
branches as units of human ownership, PRs as units of human review,
stashing as a workaround for humans doing one thing at a time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We treat the second part like a law of nature, but it’s just an
interface, designed around the constraints of 2005: human labor is
expensive, so
every change deserves a hand-written message. Humans work serially, so you
need stash and branch juggling. Handoffs between humans are the
bottleneck, so you build a whole ceremony (the PR) around them.&lt;/p&gt;
&lt;p&gt;Ever noticed that nobody actually has a good answer for how to scope a
commit? “Atomic, but not too small, logically complete, but reviewable.”
Twenty years and the best we have is vibes. For me that’s a sign the
concept itself doesn’t really fit the work.&lt;/p&gt;
&lt;h2 id=&quot;agents-broke-the-assumptions&quot;&gt;Agents broke the assumptions&lt;/h2&gt;
&lt;p&gt;Every constraint the ceremony was built for is gone:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Work was expensive → now it’s cheap.&lt;/strong&gt; When an agent produces hundreds
of changes an hour, hand-scoped commits with hand-written messages just
don’t scale anymore.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Work was serial → now it’s parallel.&lt;/strong&gt; My first worktree was the
moment this clicked for me: suddenly five agents work five tasks in the
same repo without fighting each other. Stashing (this whole “local vs.
upstream” wrestling) only exists because one human, one working copy,
one thing at a time. That world is over.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handoffs were the unit of review → now loops are.&lt;/strong&gt; Agent work gets
reviewed continuously by other agents while it happens, not once at the
end by a colleague who context-switches into a 40-file diff. The PR
boundary sits at the wrong place in the wrong rhythm. (I even skip
branches and PRs completely for fully agentic work, because the ceremony
protects a handoff that just doesn’t happen there.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What stays genuinely valuable is none of the ceremony: it’s checkpointing
(“return to any earlier state”), provenance (“which session changed this
and why”) and gating (“what’s allowed to reach production”). Git the
database does checkpointing well. The ceremony does provenance and gating
badly: a commit message is a worse record than the full agent transcript
that produced the change.&lt;/p&gt;
&lt;h2 id=&quot;its-already-happening&quot;&gt;It’s already happening&lt;/h2&gt;
&lt;p&gt;Look closely and the replacement is being built, just not announced as
one. Agent harnesses auto-checkpoint every step, so you can rewind without
ever having “committed”. Worktrees turned the one sacred working copy into
disposable parallel sandboxes. Stacked-diff tools like Graphite exist
because raw branch/PR mechanics already don’t fit how work flows. And
Jujutsu quietly made “every edit is automatically a snapshot, describe it
later, reshape history freely” feel normal, on top of Git’s database,
with Git’s ceremony removed.&lt;/p&gt;
&lt;p&gt;That’s the pattern I would bet on: nobody “replaces Git”. Git sinks one
level down and becomes plumbing (like TCP/IP: nobody thinks about it,
it’s just there). The layer we actually touch becomes: continuous
checkpoints, parallel sandboxes, session-level provenance and review loops
instead of review handoffs. The
&lt;a href=&quot;https://edhor.me/blog/the-adoption-experts-who-wont-adopt/&quot;&gt;resistance to this&lt;/a&gt; will be
loud, because Git fluency was hard-earned. I get that, mine was too.&lt;/p&gt;
&lt;h2 id=&quot;i-got-curious-enough-to-build-it&quot;&gt;I got curious enough to build it&lt;/h2&gt;
&lt;p&gt;At some point complaining wasn’t enough, so I started an experiment to see
what the layer above Git could look like. I call it &lt;strong&gt;ChangeLedger&lt;/strong&gt;:
change-native development infrastructure, where the &lt;em&gt;product change&lt;/em&gt; is
the primary object, not the commit.&lt;/p&gt;
&lt;p&gt;The model, in one line:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Intent -&gt; Change -&gt; Operations -&gt; Checkpoints -&gt; Evidence -&gt; Git export&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A change carries its goal, constraints, decisions and rollout state. Every
mutation is an attributed operation with a stated intent. Every checkpoint
is an immutable source tree, created continuously, never hand-scoped.
Verification results attach as typed &lt;em&gt;evidence&lt;/em&gt; to the claims they support
(“cancellation behavior is correct” → the test run that proves it). And
Git? Git is the &lt;em&gt;export format&lt;/em&gt;: one squashed synthetic commit per
approved, integration-ready change, generated at the end. Exactly the
demotion from the last section: workflow above, plumbing below.&lt;/p&gt;
&lt;p&gt;And look what dissolved on the way: nobody scopes commits (checkpoints are
continuous, the &lt;em&gt;change&lt;/em&gt; is the unit). Nobody writes commit prose (intent
was declared up front, evidence is attached, the message is derivable).
And nobody stashes (ordinary files are just a workspace projection of the
ledger’s objects).&lt;/p&gt;
&lt;p&gt;It’s a runnable local MVP, not a product. The point was never to ship a
Git killer, I wanted to check if the ceremony is actually load-bearing.
Spoiler: it isn’t. Everything valuable (checkpointing, provenance,
gating) got &lt;em&gt;stronger&lt;/em&gt; when intent and evidence became first-class and
commits became output.&lt;/p&gt;
&lt;h2 id=&quot;what-i-actually-do-today&quot;&gt;What I actually do today&lt;/h2&gt;
&lt;p&gt;I’m not waiting for the successor to be announced. The pragmatic version,
today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fully agentic work skips the ceremony.&lt;/strong&gt; No branch, no PR, no
hand-scoped commits: the agent loop with reviews &lt;em&gt;is&lt;/em&gt; the quality gate.
The ceremony only earns its cost where a real human handoff happens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worktrees by default&lt;/strong&gt; for anything parallel. The single working copy
is a habit, not a requirement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provenance over commit prose.&lt;/strong&gt; The session and its transcript are the
real record of why a change exists. Commit messages become labels,
nothing more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let the harness checkpoint.&lt;/strong&gt; I stopped creating safety commits “just
in case”, the tooling already snapshots continuously.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of this abandons Git. It demotes it, from workflow to storage.&lt;/p&gt;
&lt;p&gt;We don’t owe Git our workflow. It was built for a world where typing was
the expensive part, and that world is gone.&lt;/p&gt;</content:encoded><category>git</category><category>version-control</category><category>ai-agents</category><category>agentic-coding</category><category>developer-workflow</category></item><item><title>Be aware of the context window</title><link>https://edhor.me/blog/be-aware-of-the-context-window/</link><guid isPermaLink="true">https://edhor.me/blog/be-aware-of-the-context-window/</guid><description>Why Claude Code&apos;s auto-compaction quietly ruins long sessions, what context rot does to your results as the window fills up, and why the fix is awareness, not micro-managing every token.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The context window is the working memory of a coding agent, and the single
most underrated reason why long Claude Code sessions drift, forget, and
produce worse results over time. This post covers the two mechanisms behind
it, auto-compaction and context rot, and the low-effort habits that avoid both.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: This was originally written on March 31, 2026. Things move fast. Depending on when you read it, some parts may already be outdated. Since we have a Claude company license and most of us use Claude Code, this is fairly specific to Claude Code. General concepts like context rot apply just as much to other harnesses and models (Codex, Opencode; GPT, GLM, Kimi).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Keep an eye on the context window → statusline&lt;/li&gt;
&lt;li&gt;Try to avoid context compaction
&lt;ul&gt;
&lt;li&gt;or be prepared for it → keep state session-external&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A 1M context window is no workaround for compaction in long sessions&lt;/li&gt;
&lt;li&gt;Context rot: past a certain fill level, results get significantly worse → stay in the sweet spot&lt;/li&gt;
&lt;li&gt;Keep the context window small → avoid MCPs, a big CLAUDE.md, big compaction results&lt;/li&gt;
&lt;li&gt;Don’t overengineer context management. Just be aware of it.
&lt;ul&gt;
&lt;li&gt;Keep sessions small and short.&lt;/li&gt;
&lt;li&gt;Better to start a new session with a longer intro prompt than to stay in one long session.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-context-compaction&quot;&gt;What is context compaction?&lt;/h2&gt;
&lt;p&gt;Claude Code operates within a token context window. When the window fills up, Claude Code runs &lt;strong&gt;auto-compact&lt;/strong&gt;: it summarizes the entire conversation history into a compressed form and continues from that summary. It basically keeps the session alive. For details on how Claude Code handles compaction, &lt;a href=&quot;https://platform.claude.com/docs/en/build-with-claude/compaction&quot;&gt;see the docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, in my experience Claude Code’s auto-compaction is bad (especially compared to Codex). After compaction it forgets which files were modified, a plan from plan mode, parts of the todo list… you basically lose the flow. Ever wondered why results get worse during long sessions? That’s one answer.&lt;/p&gt;
&lt;p&gt;If you want to stay in a long session, you need to be aware of this and prepare accordingly. Use a session-external structure for planning (e.g. markdown files) that also tracks progress and survives compaction. In my experience, every time I hit compaction in a long-running session, the drift begins and strange behavior starts.&lt;/p&gt;
&lt;p&gt;It’s extremely frustrating and unproductive when this happens in the middle of a task, leaving you in a kind of broken state.&lt;/p&gt;
&lt;h3 id=&quot;compaction-is-expensive&quot;&gt;Compaction is expensive&lt;/h3&gt;
&lt;p&gt;The auto-compaction itself eats token usage. It’s hard to measure exactly what drives the cost, but in my early Claude Code days I could clearly see a percentage jump after major compactions. In the end it re-processes your complete history to compact it, and that costs tokens.&lt;/p&gt;
&lt;p&gt;On top of the compaction itself, the “where am I?” phase afterwards costs tokens too. The whole gap between “context full” and “next productive step” burns tokens while producing no output at all.&lt;/p&gt;
&lt;h3 id=&quot;compaction-itself-takes-context&quot;&gt;Compaction itself takes context&lt;/h3&gt;
&lt;p&gt;The result of the compaction gets added to the context, that’s the whole point of the concept. But be aware that this also increases your context usage from the start.&lt;/p&gt;
&lt;p&gt;You can see it in this little illustration:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://edhor.me/_astro/context-window-compaction.B5eDUw3F.png&quot; alt=&quot;Three context windows side by side: a fresh session containing only system prompt, CLAUDE.md, and tools; an active session where the growing conversation hits the compaction trigger; and a post-compaction session where a compaction result block already occupies part of the window.&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A session before, at, and after auto-compaction. Own illustration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After compaction you won’t start from 0% (you never do :D), but with roughly 5% additional used context from the compaction result, depending on the session.&lt;/p&gt;
&lt;h3 id=&quot;how-to-avoid-auto-compaction&quot;&gt;How to avoid auto-compaction&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Use more new sessions, or &lt;code&gt;/clear&lt;/code&gt;
&lt;ol&gt;
&lt;li&gt;Keep tasks short and scoped&lt;/li&gt;
&lt;li&gt;Personal tip: use a longer intro prompt that explains the rough context of the task: what’s already done, where we are, what’s next, a bit about the environment. Reuse this intro prompt and adjust it for each task.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/compact&lt;/code&gt; yourself when you’re in a “compact-safe” state, at logical breakpoints. You can also add a custom focus after the command to tell Claude what to prioritize in the summary.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;context-window&quot;&gt;Context window&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a topic of its own and would be too much for this post, so I’m leaving out things like MCPs, skills, and subagents.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Before you continue reading: run the &lt;code&gt;/context&lt;/code&gt; command in one of your active sessions. It shows exactly how your current session’s context is being used.&lt;/p&gt;
&lt;p&gt;You’ve maybe seen or already used the 1M context variants of Opus and Sonnet. Seems like the logical solution to all these problems, right? Right? &lt;strong&gt;No!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are use cases for such a large context, like working with lots of data or single big files (e.g. PDFs) that don’t fit into the normal window at all. But it’s not the solution for auto-compact.&lt;/p&gt;
&lt;p&gt;Why? → &lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/#what-is-context-rot&quot;&gt;Context rot&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One additional use case I can think of is avoiding auto-compaction. But then you really need to watch your context usage and manage it manually via &lt;code&gt;/clear&lt;/code&gt; or &lt;code&gt;/compact&lt;/code&gt; to not run into context rot.&lt;/p&gt;
&lt;p&gt;Also good to know: the 1M variants burn through your usage faster beyond the 200k base window. If you’re already struggling with strict limits, avoid them.&lt;/p&gt;
&lt;h3 id=&quot;what-is-context-rot&quot;&gt;What is context rot?&lt;/h3&gt;
&lt;p&gt;Context rot is a known problem where LLM results significantly worsen once the context fills past a certain level: the model gets measurably worse at using what’s in its window as the window grows.&lt;/p&gt;
&lt;p&gt;Maybe you’ve experienced it: you’re in a session, and the results get worse with every prompt. Perhaps you’re in a yelling-loop (a phenomenon where the next most likely answer is wrong, so the user yells again, just like in the last three prompts), or you’ve hit context rot. This graph from &lt;a href=&quot;https://research.trychroma.com/context-rot&quot;&gt;Chroma’s context rot research&lt;/a&gt; illustrates it well. Newer models are improving here, but it’s still a problem.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://edhor.me/_astro/context-rot-repeated-words.CLmz72Qu.png&quot; alt=&quot;Line chart of the &amp;#x22;Repeated Words&amp;#x22; benchmark: average normalized Levenshtein score by input length for Claude Sonnet 4, GPT-4.1, Qwen3-32B, and Gemini 2.5 Flash. Every model&amp;#x27;s score falls steeply as input length grows from a hundred to tens of thousands of tokens.&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Model accuracy against input length on the “Repeated Words” benchmark. Source: &lt;a href=&quot;https://research.trychroma.com/context-rot&quot;&gt;Chroma, Context Rot&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Anthropic says Opus 4.6 has significant long-context improvements, but it’s &lt;a href=&quot;https://claude.com/blog/1m-context-ga#:~:text=Long%20context%20that%20holds%20up&quot;&gt;still significantly worse at 1M than at 256k&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s hard to call exact numbers or pin down the tipping point for Opus or Sonnet, and I’m not aware of a published Claude-specific threshold. From my own sessions, the ~60% area is a working heuristic, not a measured number.&lt;/p&gt;
&lt;p&gt;On the 256k variant, the compaction trigger sits around 85–95% of the context window in the sessions I’ve watched. That leaves enough buffer to wrap up a session and prepare for a new one, or for a compaction.&lt;/p&gt;
&lt;p&gt;So if you want better results: try to stay in the sweet spot.&lt;/p&gt;
&lt;h2 id=&quot;micro-context-management&quot;&gt;Micro context management&lt;/h2&gt;
&lt;p&gt;Context management is a whole topic in itself. You might now think you have to be extremely careful not to create too much context, avoid auto-compact at all costs, and so on, just to stay in the sweet spot.&lt;/p&gt;
&lt;p&gt;No, it’s not worth the effort. That would only stop you from developing the right mindset for getting good results. Just avoid the big things: lots of MCPs, skills, or a &lt;a href=&quot;https://edhor.me/blog/how-to-claude-md/&quot;&gt;huge CLAUDE.md&lt;/a&gt;. It’s setup optimization, not agonizing over context with every single input.&lt;/p&gt;
&lt;p&gt;Being aware of the topic is enough.&lt;/p&gt;</content:encoded><category>claude-code</category><category>context-window</category><category>context-compaction</category><category>context-rot</category><category>ai-agents</category></item><item><title>How to CLAUDE.md</title><link>https://edhor.me/blog/how-to-claude-md/</link><guid isPermaLink="true">https://edhor.me/blog/how-to-claude-md/</guid><description>A recent study measured what CLAUDE.md and AGENTS.md files actually do: developer-written ones help a little, LLM-generated ones hurt results and raise cost. Keep yours tight.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CLAUDE.md (or AGENTS.md, by the way: just symlink them) is the context file
coding agents load into every session, and it’s easy to overuse. A recently
published study looked directly at this, so I want to share it here so we
stay aligned with the latest evidence.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2602.11988&quot;&gt;Study: arXiv 2602.11988&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=47034087&quot;&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/2602.12670&quot;&gt;Related paper: arXiv 2602.12670&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;There are also some videos about the topic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;AGENTS.md / CLAUDE.md files seem easy to overuse. The study found that
developer-written files produced only a modest average improvement
(&lt;del&gt;+4 percentage points), while LLM-generated &lt;code&gt;/init&lt;/code&gt;-style files slightly
&lt;em&gt;reduced&lt;/em&gt; success (&lt;/del&gt;−3 points) and increased cost by more than 20%, largely
because agents explored, tested, and reasoned more. Agents also tend to
follow these instructions quite literally.&lt;/p&gt;
&lt;h2 id=&quot;what-that-means-in-practice&quot;&gt;What that means in practice&lt;/h2&gt;
&lt;p&gt;From my personal experience, I can attest to that. Having a detailed
AGENTS.md / CLAUDE.md and constantly working on and adjusting it was worse
than having a super tight and focused one. The same goes for MCPs and skills.&lt;/p&gt;
&lt;p&gt;There are useful ones, like the
&lt;a href=&quot;https://github.com/anthropics/claude-code/blob/main/plugins/frontend-design/skills/frontend-design/SKILL.md&quot;&gt;frontend-design skill&lt;/a&gt;
from Anthropic itself, but they should be installed very selectively.&lt;/p&gt;
&lt;p&gt;Agents are now so good at searching for context on their own (e.g. via
Explore subagents) that an overly explicit context file that doesn’t match
100% of the time can mislead them and worsen results. On top of that, a big
CLAUDE.md occupies context in every single session, see
&lt;a href=&quot;https://edhor.me/blog/be-aware-of-the-context-window/&quot;&gt;Be aware of the context window&lt;/a&gt; for
why that matters.&lt;/p&gt;
&lt;p&gt;Since most of us use Claude, we don’t benefit from Codex 5.4’s ability to
strongly align with existing patterns in the codebase. So this is more of a
model-skill gap than something we’ll need to handle ourselves in the very
near future.&lt;/p&gt;</content:encoded><category>claude-code</category><category>claude-md</category><category>agents-md</category><category>context-window</category><category>ai-agents</category></item></channel></rss>