← Kumar Prateek

The code my agent writes is good. The decisions inside it aren't always mine.

Aug 2026 · Kumar Prateek

Not bugs. Choices. I described a problem, something came back that made sense, I read it, I shipped it. I write most of my code with Claude now; most of us do. This is about something that started happening to me because of it, and a small tool I built to deal with it.

The thing I noticed

I read about something. I nod. It makes sense. I close the tab. Two weeks later someone asks me about it, and what comes out of my mouth is a shape: the right words in roughly the right order, with nothing behind them. I knew of the thing. I didn't know it.

From the inside, those two states feel identical. That's the whole problem. There is no internal signal that separates "I understand this" from "I watched this get explained." So you can't catch it by being honest with yourself, or by being smart, or by trying harder. The feeling of understanding is not evidence of understanding.

What agents did to it

Getting code to run used to be the forcing function. You argued the choices out, or it didn't work. Repeat "it came back, it made sense, I shipped it" across a few PRs and something strange happens: the code has decisions in it that I approved in half a second and never actually made. How a retry behaves. What happens on the second delivery of the same message. Why a lock is taken there and not one line earlier. I've watched them work three times. I've never once had to know why.

And from the inside, "I decided this" and "I approved this in half a second" feel exactly the same. Shipping and understanding have come apart, and nothing replaced the gap. So you get people, and I'm one of them, building up huge surface area and much less depth than their commit history implies. Not because anyone's lazy. Because the thing that used to force the issue quietly stopped.

The idea: one question

So I built one. It's called grask, and it does one thing.

When you close a Claude Code session, it reads what happened. Most days it decides there's nothing worth asking. If you spent the session renaming variables and fixing CI, there's nothing to be hollow about, and asking anyway would just be nagging. Most sessions produce no question, and that silence is the point, not a failure to find something.

When there is something, one question is waiting the next time you type /grask:grask. The shape of it: you changed how a service handles a retry last week. The question asks what happens downstream the second time the same message arrives. Four options, one of them explaining why the code is written the way it is. If you know it, that's ten seconds and you move on. If you don't, better to notice now than in a review. A real one looks like this:

from 2026-08-08 · retry backoff in the
webhook dispatcher

Your retry loop sleeps 2**attempt seconds
between attempts. Why does adding random
jitter matter more as the number of
clients grows?

  a) Jitter reduces the total number of
     retries each client makes.
  b) Clients knocked out together retry
     together; jitter spreads them back out.
  c) Exponential backoff overflows without
     a random term to bound it.
  d) Jitter is what makes the sleep
     interruptible by a signal.

> b
✓ Backoff decides how long each client
waits. It does nothing about them all
waiting the same amount. Clients dropped
by one outage come back in lockstep, so
the recovering service takes the same
thundering herd on every cycle. Jitter
decorrelates the schedules.

Notice it isn't "what is a retry policy." You can answer that from memory, and it proves nothing. The only way to pick right is to have actually made the decision that's in your code, or to make it, late, right there.

Twenty seconds. Pick an option, or choose "Other" and type skip. Skipping is always free. If the question misreads what happened, type wrong: <what's off> instead; that ends it and logs a bug against grask, not against you.

Why multiple choice, and why no AI grades you

The first version asked you to explain your reasoning in your own words, and had a model grade the explanation. I killed that, because a grader can fail in two opposite ways and both are fatal.

Ask an LLM to judge your reasoning and it will usually tell you you're doing great. It accepts a vague answer, quietly fill in what you left out, congratulate you. A grask that flatters you is an expensive machine for making you feel smart.

The worse failure: the grader misreads your code, invents a bug you didn't write, and tells you, confidently, about your own code, in front of you, that you don't understand something you do. That gets the tool disabled forever, and it should. Trust is the whole product, and it's decided in the first ten interactions.

So there's no grader. Three or four options, one right, and the answer is written at the same moment as the question. Grading is just comparing two numbers. Nothing in the loop can flatter you and nothing can accuse you. And wrong: … is always a valid answer: the premise being off is grask's failure, not yours.

What I'm after isn't explanation. You can get one of idempotency anywhere in fifteen seconds. The scarce thing is calibration: the gap between how well you think you understand something and how well you do. A wrong answer you knew was a guess is fine. A wrong answer you'd have bet on is the whole point.

What it reads, which you should know before installing

A tool that asks about your code has to read your code, and I'd rather you hear the shape of that from me than find it out afterwards.

grask reads the transcripts Claude Code already writes to ~/.claude/projects/, and it is not scoped to the repo you're sitting in. It sees all of them. It sends transcript content to a model to work out what's worth asking about: your prompts, the agent's replies, the before-and-after of edits. It does that by shelling out to the claude binary you already have, so it runs under your existing Claude Code auth and whatever data policy your account already carries. There's no second API key, nothing goes anywhere else, and there's no telemetry. What it extracts, including verbatim quotes of things you typed, is stored locally in SQLite under ~/.claude/grask/.

Two consequences worth stating plainly. GRASK_HOME moves the database somewhere else if you want it somewhere else. And if any repository you work in is covered by an agreement that prohibits sending source to a model, don't install the hook. The session-end hook captures whatever session just ended and has no per-project exclusion.

Where it's at, honestly

It's alpha. It works end to end: sessions get read, most produce nothing, and the ones that don't put a single question in front of you inside Claude Code.

There is one check on the questions themselves. Before a probe ever reaches you, a separate stage re-reads the options cold, with no answer key, no explanation and no transcript, and judges each one true or false on its own. The probe survives only if exactly one option is true and it's the one the key names. In the probes generated so far that check has already thrown out several, including one whose key asserted a name collision that doesn't happen.

What that check can't catch is a question that's internally consistent and still tests nothing you could carry to another codebase. Which is the first of three things that aren't built, and they're the three that decide whether any of this was worth doing:

What I want to know

I'm sharing this partly because I don't know if it's a real product or just a good tool for a small number of people who happen to be wired like me. I'd rather find that out on purpose than by accident. It's alpha, and the README says what isn't built yet.

So, honestly:

If you want to try it, it needs the Claude Code CLI and a python3 (≥ 3.8), and nothing else. Inside Claude Code:

/plugin marketplace add imkp1/grask
/plugin install grask

Then /grask:grask when you want the question. The rest of the caveats are in the README: github.com/imkp1/grask

Tell me if it's stupid.