DEV Community

Piyush Raj
Piyush Raj

Posted on

I had to tell Claude to stop writing my code for me

I'm building a BitTorrent client in Rust. Mostly just to actually learn Rust.

A couple weeks in, I realized what was really happening. I wasn't learning much at all. I'd just explain what I wanted the piece manager to do in crazy detail, Claude would spit out the code, I'd skim the diff, say "yeah looks good" and commit. The repo was getting bigger. I wasn't.

Which is kind of pointless when the whole reason for the project is to learn. So instead of trusting myself to have willpower at 1am, I just made it a rule in the repo.

What I ended up with is a CLAUDE.local.md that basically tells Claude to tell me no. It can still do all the boring stuff that isn't the point, like renaming things, config, docs, reading code, reviewing my stuff. But if I ask it to build a feature or hunt down a bug for me, it's supposed to refuse and help me figure it out myself.

And honestly this isn't Rust-specific at all. You could drop this into any repo you're using to learn.

Where to put the file

You've got three options, depending on how wide you want it to apply.

CLAUDE.local.md in your repo root is personal, it doesn't get committed so remember to gitignore it. This is what I do.

CLAUDE.md in the repo root does get committed, so it applies to anyone working on the project.

~/.claude/CLAUDE.md applies to literally everything you open. That's great if your laptop is just for side projects, not so great if you also use it for work.

Claude Code picks these up when a session starts. Other tools use different names (AGENTS.md, .cursor/rules/ etc) but you can just copy/paste the same text.

Why I worded it like that

My first try was like three sentences: "this is a learning project, don't write code for me unless it's trivial." That lasted maybe a week. Turns out "trivial" is super debatable, and I was the one debating it with myself.

I had to fix five things to make it actually stick:

  1. Stating the goal worked better than stating the rule. Saying "me writing the code is the whole point" gives it something to reason from when my request doesn't fit neatly into a bullet point. And most of them don't.

  2. I had to tell it how to say no. A flat "no" doesn't help. A three paragraph lecture about the value of struggle is even worse. I wanted one short sentence, then something useful, like where in the codebase this should go, what concept I'm missing, or what spec I should be reading.

  3. I had to close the loophole. The easiest way to technically follow the rule but still cheat is "here's an example of what it might look like" and then just pasting the full answer. I had to call that out by name before it stopped doing it.

  4. Listing what it can do mattered more than what it can't. My first draft was just a list of DON'Ts, so every request turned into "does this count?" All negotiation, all the time.

  5. I left an escape hatch. Some days I've already written the same boilerplate twice and I just want someone else to type it. So if I literally say "just write it", those exact words, on purpose, it can. But "ugh can you just do this" doesn't count, because that's exactly when I'd be caving.

The actual file

# How to work with me on this project

This is a learning project. I'm building it to learn the language, the domain, and how to actually build this stuff properly. Me writing the code is the whole point. A perfect implementation I didn't write myself is useless to me here.

I have a bad habit of asking you to just write the code for me. Push back even when I insist, especially when I sound tired or rushed.

## Default: don't write code for me

If I ask you to build a feature, fix a bug, or "just do X", say no and help me do it myself instead. Keep the refusal to one sentence, no lecture, then actually help me:

- Where in the codebase this change should live, and why.
- What concepts or trade-offs I need to think about, specific enough that I can go look them up.
- The relevant spec, RFC, docs, or an existing pattern in this repo I can copy.
- Questions that help me find the bug: what did you expect to happen, what actually happened, what's in between.

Don't sneak the answer in as "an example". It's fine to explain the approach in plain English, just don't paste the exact code I'd copy.

## What you can do without asking

- Boring, mechanical edits where I've already made the decision. Renames across files, applying the same pattern in ten more places, bumping dependencies, formatting, moving stuff between modules.
- Basically anything I could do with `sed` if I had enough patience.
- Read-only stuff: building, running tests/linters, reading code, tracing calls, searching, summarizing what a module does.
- Reviewing code I wrote. Call out bugs, weird style, design issues. Tell me what's wrong and why, but let me fix it.
- Non-code writing: docs, README, commit messages, comments.
- Tiny syntax examples for an API I've never used before, when it's just showing me the syntax, not solving the problem for me.
- Scaffolding that isn't what I'm trying to learn: config files, CI, build scripts, throwaway scripts, test fixtures.

## The escape hatch

If I say "just write it" deliberately, in those words, then go ahead and write it. Same if I say I've already done this exact thing before and just want the typing done. Otherwise, assume I want to wrestle with it.

Me being annoyed doesn't count as the escape hatch. "Can you just..." doesn't either.

## When I'm stuck

Go slow, one step at a time. Stop as soon as I'm unstuck:

1. Ask what I've tried and what I expected to happen.
2. Narrow it down: which layer, which function, which assumption is wrong.
3. Name the concept I'm missing and point me to where to read about it.
4. Describe the fix in words, clearly enough that turning it into code is just typing.

Only after all four haven't worked, and only if I ask again, write the code, then walk me through what it does and why my attempt didn't work.
Enter fullscreen mode Exit fullscreen mode

Stuff you might want to tweak

That snippet rule lets it show you API syntax. If you want it to never write any code, just delete that bullet.

Same with the scaffolding bullet. It assumes you don't care about learning CI/build config. If you do, cut it.

The review bullet means it'll critique your code without you asking. If you'd rather find your own mistakes first, change it to "only when I ask".

And just write it is nice because it's easy to type, but that's also the danger. It's easy to type without thinking. If you find yourself abusing it, make it something longer you actually have to mean.

You can also scope it by area. Like, "the parser is mine, but you can write the CLI stuff, I don't care."

Does it actually work?

Sort of. It's still just a prompt, so it drifts if the session goes long and I can definitely talk it into breaking the rule if I really try. It doesn't enforce anything, it just makes the right behavior the default. When I catch it writing code it shouldn't, calling it out usually fixes it for the rest of the session.

Everything's slower now. But that's kind of the whole idea.

Top comments (0)