home / blog

Making AI coding tools useful

Brief notes on Claude Code reliability, use in healthcare related software, good practice, and the gap between demos and usable code

AI coding tools are good enough to be useful, I don't think that is a question at all.

The actual question is how to make them reliable enough to use to their maximum capacity in the real world, especially concerning work with EHR records, production code, or communications with real humans. We need to consider how to avoid wasting time, generating garbage, or making a mess out of existing systems.

The common failiure modes look something like this:

It does 90% of the work, then chases its tail for an hour trying to solve what should be a very simple issue.
The code works great, but it's a thousand line script that no one is possibly reading or maintaining.
This generated email/landing page/documentation/whatever is full of BS and sounds like it was copied right from ChatGPT.
Trying to use AI in an existing codebase and it's touching things it shouldn't and making a mess.
Just playing around with the new Claude I spent $70 in three hours (true story).

1. Reliability

Claude likes to start by generating massive amounts of generally pretty good code. Boilerplate is easy, but often it hits a wall, then starts screwing around.

The pattern is:

  1. solve most of the task.
  2. one small issue remains.
  3. start aggressively patching.
  4. the patches create new problems.
  5. the session quickly gets worse.

This really sucks because the last 10% ends up eating all of the time the first 90% saved.

How do we fix it?

A huge ROI change is to write repo-specific rules. Claude Code will find these in a file called CLAUDE.md, Cursor will look for project rules in .cursor/rules, AGENTS.md is an open standard, consult the docs of your agent of choice.

There are a million good examples online of what to include and what not to include. [1], [2], [3].

I start with a template file which outlines general good practice and preferences, then add project particulars, things like architecture decisions, UI standards, language/tool preferences, style, etc.

After you have some hand written rules it is useful to ask your agent to review and update those rules itself. You can even add a rule to update the rules at any given checkpoint.

Rules are what keep agents from going off the deep end when things go unexpectedly. Whenever an agent misbehaves, or does something I don't like, I will solve the issue, then ask it to explain its fault and what things triggered it, then write a new rule to ensure the breakdown never repeats.

Claude Code has a command /init which you can use in an existing codebase to map the current architecture and design, then write appropriate rules to enforce the standard as Claude continues.

# example rules file

- propose a short plan before making changes and ask clarifying questions when unsure
- follow the existing architecture and design patterns
- do not create giant single-file implementations
- do not touch files X,Y,Z, and do not make any database migrations
- add or update tests when behavior changes
- if stuck after two failed attempts, stop and explain the blocker

Treat it like an intern, it doesn't know that there are any rules unless you tell it. You can't blame the poor thing, it learned all its manners from the internet.


2. Reviewability

A 1000 line bash script may run but it is probably not a useful piece of engineering that anyone can be expected to maintain or fix.

Bad AI output often looks like:

How do I avoid that?

Understand that Claude doesn't care about architecture or maintainability or reviewers unless you tell it to. Explaining your expectations for the final state of the codebase will nearly eliminate the entire issue.

There are a few super useful skills here to point your agent in the right direction from the start with only a little bit more setup required.

Most agents now have a built in planning mode or planning workflow. This allows you to generate a document containing all the design decisions you want made. I find it useful to ask the agent to end its plan with a granular todo list for it to follow. You can employ some specific phrasing like "write as many todos as you possibly need" to get Claude or Cursor to spit out a list of dozens of items encompassing everything from setting up, to actually writing, to reviewing, testing, documenting, etc.

There are also some great community skills for planning, I really like the super simple Claude skill grill-me. The purpose is stated to be to "reach a shared understanding" with the model which is nicely said but in practice, Claude will just ask you a bunch of questions. The less inferring you let an agent do, the better it's going to be.

If you just tell AI to get it done, it will just get it done. If you spend a little more time telling it how you want it done, it will do that too. Leverage its good listening skills before it makes a mess.


3. Context management and drift

Context rot is an interesting concept that has implications in how the LLM itself performs as well as how the agent is able to work. The idea is that the more tokens you send off to an LLM, the more math it needs to do to generate more tokens. You can imagine that something you said 1000 words ago is not as important as what you said 2 words ago however the model must still consider both words for every new token it generates. It gets slower and actually dumber.

As far as the agent is concerned, the LLM is the engine, dumber and slower LLM is dumber and slower agent. But even before the actual LLM performance drops, the agent loses effectiveness because it remembers all its failed attempts, assumptions, old plans, irrelevant code and files. Why are we wasting energy remembering work we did that was wrong or so old it is irrelevant?

Nice visual: here

What are the options?

The person who solves this problem for good and enables us to have infinite context will be a billionaire and win a Nobel Prize but at this moment we resort to one of the following:

  1. just ignore it (don't do this)
  2. compact your current context
  3. start a fresh session

compact when

  • you are in the middle of one task
  • the current plan still makes sense
  • the model has not repeatedly failed
  • the context is mostly relevant

start over when

  • Claude has tried multiple bad fixes
  • the original goal is buried
  • the next step is really a new task
  • the session is full of failed attempts

knowing exactly when to compact is also important, Claude Code can compact context, and Cursor also has built-in context management. A decent practical standard is to start thinking about compaction well before the limit, around 60% of your context window. The /context command in Claude Code shows an exact breakdown of what's in your context, Cursor has a built in graph, and there are community made plugins for better visuals or proactive or theoretically better compaction. I find the default ones to be pretty solid.

One cool trick in Claude Code is you can use the /compact command with an argument like "save everything related to database", this does exactly what it sounds like, you can choose roughly what things to compact and what things to keep in context.

My recommendation is to start fresh as often as possible, only compact if you are mid task. An alternative I sometimes use is to ask "give me a summary of the last 5 changes to pass to a second coding agent" then I start a fresh agent and paste that summary right in.

The idea is to always be giving the agent exactly what it needs. Too little, it's going to make things up, too much, it gets sloppy.


4. Cost

Cost is one of the most interesting areas where there are lots of improvements to be made. I doubt this is the current case but there are teams spending millions of dollars monthly on tokens and I would bet they are doing something wrong.

What we can do

I already employ my own system to route simpler requests to smaller cheaper models like Kimi K2.5 or DeepSeek V4 Flash. For things like web search, summarization, or simple boilerplate, these models are marginally dumber for fractions of the cost of even the cheapest Claude models.

If cost is a concern there are a list of measures to reduce it, prompting better, using cheaper models, clearing/compacting frequently, installing plugins that do things such as sending less verbose bash outputs to agents. This is a rabbit hole which I have been down before and I can go down again.

small models

summaries, simple reviews, formatting, context cleanup, lightweight tool calls, docs cleanup

big models

implementation, hard debugging, architecture decisions, security review, difficult refactors

You can save a lot by truncating what you send to the model, and choosing the right model for the job.


5. When to not use AI

There are some tasks that are simply not fit for AI either for safety, capability, or authenticity reasons.

good uses

  • regular coding tasks
  • summarizing docs
  • drafting communications
  • reviewing non-sensitive data

definitely not

  • sending your boss or clients an email
  • running commands unsupervised
  • making UI/UX desciscions without humans
  • accessing PII or PHI

What I would do

I would start by reviewing current usage. Agents should be running in sandboxes and never on production servers. I would look into tools which run locally to catch PII or other sensitive credentials before you send them off to LLMs. I would also advise caution from developers when using AI in general for all those important things from code to writing emails. At the end of the day, a human needs to know they are responsible for anything they push or send, whether an LLM wrote it or they did.


Where will I start?

In my opinion, the reliability issues are the most pressing. No point optimizing costs if it's all junk anyway.

Order of operations looks something like this to me:

Once we have a reliable and convincing pipeline for safe and useful AI, then we can talk about optimizing our use. Things like subagents, autonomous review, agents who do whatever, anything is possible!


Some resources:

Research and benchmarks

Security and healthcare safety

Agent workflows and tools

Videos


back home