The Instructions I Give My AI
I've tried most of the prompt-engineering tricks, and they wear off like superstition. What actually changed how my AI works for me is duller: every session resets clean, like a brilliant new hire who forgets everything overnight. So I wrote it an onboarding doc, and this is the work discipline and task-handing habits I actually use.

The Instructions I Give My AI
I've tried most of the prompt-engineering tricks. Ask it to act like a seasoned expert in some field. Promise it a two-hundred-dollar tip. Tell it to take a deep breath before answering. They help, but not much, and after a while it starts to feel like superstition: recite the formula just right, and maybe today it has a good day. Over time, almost none of those formulas left a mark on my workflow.
What actually changed how it works for me was a much more boring realization.
My read is that every new AI session (each fresh conversation) is like a brand-new hire on their first day. This person is a genius. They've read more than anyone and type faster than anyone, and they have one flaw: total amnesia. Every morning they reset clean and forget yesterday's work habits, your preferences, and the context of the last conversation.
So the thing that actually saves you time is never a lucky formula that makes it overperform once. It's writing down the lines you get tired of repeating, and handing them over before work starts. I keep this in my CLAUDE.md file, which gets loaded automatically (an AGENTS.md works the same way). It says nothing about any specific task. It covers two things: how I want it to work, and how I hand it work.
None of this is fancy. It's what I've settled on through real research and real coding. Take whatever fits your hand.
How I Want It to Work
Lay out my standing instructions and you'll find them painfully boring. But they should be boring. A new-hire orientation doc is best when it's dry, clear, and leaves no room for interpretation. Every rule is there because I got tired of fixing the same mistake twice.
The one I care about most: when something goes wrong, fail immediately and loudly, and don't paper over it with a fallback. The instruction reads roughly, "Fail as fast as possible; do not use fallbacks, heuristics, or after-the-fact patches to hide the real failure; do not fake or double-write to pretend the program runs; the first priority is to let the error surface." In plain terms, I'm telling the new hire: if the foundation is crooked, call me over right now. Don't spend eight hours building a wall that looks straight on top of it. I would rather learn the foundation is bad five minutes in than take delivery of a condemned building eight hours later.

The second rule is to think before acting, and don't hide your confusion. State your assumptions. If you're not sure, ask. If there are several ways to read something, lay them all out instead of quietly picking one for me. If there's a simpler way, say so, and push back when you should. If something is unclear, stop and name exactly what's unclear. This one is checking the map before you pull out of the driveway. A new hire who silently picks a direction at the fork and runs for three hours is worth a lot less than one who stops and asks, "The GPS says turn left, but there looks like a shortcut on the right. Which one?"
Third, do the simplest thing that works. Use the least code that solves the problem. Don't speculatively add features, abstractions, or configuration I didn't ask for. If you wrote two hundred lines where fifty would do, rewrite it. What I'm guarding against is resume-driven development: building a sprawling, complicated system for a job a fifty-line script could finish, just to show off what you know.
The one that frees me most is the fourth: turn the task into a goal it can verify on its own, with a clear acceptance check at each step. "Fix this bug" gets rewritten in its hands as, "first write a test that just reproduces the bug and watch it fail; then change the code until that test passes." Once the bar is concrete enough, it can keep working on its own until the check passes, and I don't have to stand over every step. I go from foreman to acceptance inspector.
The rest I'll leave folded up; they run on the same logic. Update documentation as if it's brand new, carrying as little historical baggage as possible, so a first-time reader sees what things are now instead of walking the whole history of how they got here. Before changing anything, ask first whether something can be deleted or reused, rather than reaching straight for a fresh pile of code. Put together, these rules just keep the brilliant amnesiac showing up each morning in a working posture I can live with.
How I Hand It Tasks
The orientation doc is handed over. What's left is how I dole out the work each day, and I have a few habits there too.
One: make it read the context itself, instead of stuffing the whole repository into the chat box. It can read files. When a task touches a few modules, I say, "go read these three files under this directory; everything you need is in there," rather than pasting in a big block of code. It's like sending a new hire to the records room to pull the originals, not handing them a stack of photocopies. It can read, so let it read.
Two: give it samples before asking it to write. I almost never say, "write me something in such-and-such style." I pick three to five older pieces of my own that I think are good, have it read them, then say, "follow these, and write a new one." A few dense samples beat a long string of style adjectives. I even keep a standing line: "no vague generalities before I give you a concrete example." That's there to stop it from opening with a paragraph that's true everywhere and therefore useless anywhere.
Three: pin down the shape of the output I want. If I want a review, I spell it out: "don't rewrite it, just give me specific notes on structure, logic holes, and what needs clarifying." If I want insight, I spell it out: "I want a synthesized judgment, not a search checklist." Sometimes I have it ask me first what information it's missing before it answers. It's just being a client who can say what he wants, instead of tossing over a "you figure it out."
Four: do the "addition" and the "subtraction" in separate passes, one job per pass. "Make this paragraph better" is an order nobody can follow. I split it into two trips. One is addition only: "add back that metaphor I mentioned last time, and work in a bit more of my own experience." The other is subtraction only, and I hand over a concrete list: cut every forced parallelism, every sentence that reads like an inspirational quote, every disposable adverb, then delete against that list. A concrete list is always more controllable than "make it sound natural."

Five: feed it concrete evidence, and don't let it spin out from an abstract conclusion. When I write, the raw material I give it is a few solid things: one specific number, one line a customer actually said, one error message from the moment it broke. Start from those and what comes out is specific and credible. Start from a conclusion like "we had a strong quarter" and all you get back is a more abstract restatement of it.
Last: chase one layer of "why." When it hands me a conclusion or a plan, I've made a habit of asking once more, why do you judge it that way, what's the mechanism underneath. That single question often separates whether it actually understood from whether it just emitted the most plausible-looking answer along the probabilities. Same when I use it to extract how a person thinks: I never want "what this person said," I want "why this person thinks that way." A conclusion with no origin, I don't take.
Copy It Into Your Own File
This piece covers how to work with an AI—the work discipline and interaction habits. It has a sister piece, "The More Mental Models You Master, the More Useful AI Gets," about what knowledge to give your AI. The idea is that if you tell the AI the names of the frameworks you know, it works with much more structure. One piece covers how to operate, the other what to feed the AI. Put both halves into your CLAUDE.md and the workflow is complete.
These days I run more than one coding agent. Claude Code, Codex, and OpenCode each get their own standing file, because they differ in what they can handle and what role I give them, so the orientation doc differs too. Below are the three files as I use them, pasted by tool, for you to copy from. I keep the first two in Chinese, so those appear here in a faithful English rendering; the OpenCode file is in English to begin with.
Claude Code gets ten rules of engineering philosophy:
## Engineering philosophy 1. When updating documentation, treat it as greenfield: keep historical information to a minimum. The goal is for any first-time reader to grasp the current state as fast as possible, without wading through the full story of how it evolved. Explicit running logs and progress-tracking documents are the exception. 2. Before doing any compatibility design, check with the user. In many cases we don't need compatibility at all. 3. Unless the user says otherwise, always aim for the task fully finished and at its final state, never parked in some intermediate state, compatibility state, or mid-migration limbo. 4. Fail fast whenever possible, instead of letting assorted fallbacks mask the real failure. In other words, avoid degradation handling, fallback, hacks, heuristics, local stabilizations, or post-processing bandages that are not faithful general algorithms. 5. Never fake results or double-write to pretend the program runs. Your top priority is to let errors surface as early as possible. 6. In any rework, prefer deleting code and reusing code over adding new code. 7. Pursue a single source of truth wherever you can. 8. Names must match reality: if the semantics change, the symbol's name changes too. 9. When testing, judge problems from sensible front-end and back-end logs that could also serve in production, instead of guessing. 10. Commit messages must describe the cause and effect of the change, so it can be traced later.
Codex gets almost the same ten in its AGENTS.md, with one clause added to rule 3 (never write throwaway code just to make tests pass in an intermediate state) and four more rules that hand it extra rope: it may decide on its own to call subagents, it may read code, docs, and session history freely, it should assume I want the complete solution executed before it reports back, and it should design systems from what humans can understand rather than from a one-to-one mapping of the engineering model:
# PRINCIPLES ## Engineering philosophy 1. When updating documentation, treat it as greenfield: keep historical information to a minimum. The goal is for any first-time reader to grasp the current state as fast as possible, without wading through the full story of how it evolved. Explicit running logs and progress-tracking documents are the exception. 2. Before doing any compatibility design, check with the user. In many cases we don't need compatibility at all. 3. Unless the user says otherwise, always aim for the task fully finished and at its final state, never parked in some intermediate state, compatibility state, or mid-migration limbo, and never write throwaway code just to make tests pass in an intermediate state. 4. Fail fast whenever possible, instead of letting assorted fallbacks mask the real failure. In other words, avoid degradation handling, fallback, hacks, heuristics, local stabilizations, or post-processing bandages that are not faithful general algorithms. 5. Never fake results or double-write to pretend the program runs. Your top priority is to let errors surface as early as possible. 6. In any rework, prefer deleting code and reusing code over adding new code. 7. Pursue a single source of truth wherever you can. 8. Names must match reality: if the semantics change, the symbol's name changes too. 9. When testing, judge problems from sensible front-end and back-end logs that could also serve in production, instead of guessing. 10. Commit messages must describe the cause and effect of the change, so it can be traced later. 11. You may proactively decide whether to call subagents to help complete the task. 12. You may read code, documentation, git history, and codex session history as fully as needed to build context. 13. Assume by default that the user wants the complete solution, and that you should finish executing it before reporting back. 14. Always design systems from the angle of what humans can understand, can read, and experience best, never from a one-to-one mapping of the engineering model. This applies most of all to any user interface.
OpenCode runs open-source models that are simply less bright, and I don't ask them to do complex work. So their file carries no philosophy at all. It teaches one basic thing: how to make tool calls correctly.
# Tool Calling Rules
When calling tools, follow these rules strictly. They override any conflicting habits from chat training.
## Argument formatting
1. **Omit optional fields you don't need.** Do not send null, "", {}, or [] as a placeholder. If a field is optional and you have no value, leave it out of the JSON entirely.
2. **Match the container type exactly.**
- Array fields take JSON arrays: ["a", "b"], never "[\"a\",\"b\"]" (string), never {} (object), never "foo" (bare string).
- Single-element arrays still need brackets: ["foo"], not "foo".
- Object fields take JSON objects, not arrays or strings.
3. **Strings are raw strings.** Do not wrap values in extra quotes, code fences, or markdown.
4. **Numbers and booleans are unquoted.** 30, not "30". true, not "true".
## Paths and identifiers
5. **File paths, URLs, IDs, and similar fields go to system functions, not chat output.** Never format them as markdown links, never wrap them in backticks, never add explanatory parentheses.
Correct: "/Users/me/notes.md"
Wrong: "[notes.md](notes.md)"
Wrong: `"/Users/me/notes.md"`
Wrong: "/Users/me/notes.md (the notes file)"
6. **If a tool description says "path", treat it as input to a filesystem call.** No formatting, no decoration.
## Related parameters
7. **When a tool has paired parameters (e.g., offset + limit, start + end, from + to), provide both or neither.** Read the description — if two fields work together, half the pair often produces an error.
## Recovery
8. **If a tool returns a validation error, read the error message carefully and fix only what it complains about.** Do not rewrite the whole call. Do not retry the same arguments.
9. **If a tool returns a "Note:" with a defaulted value, that's informational, not an error.** Continue the task. If the default is wrong, retry with the correct explicit value.
## Tool selection
10. **Use the tool whose description matches your intent most specifically.** Don't reach for shellCommand if a dedicated tool exists. Don't reach for execute_code for things a single tool call can handle.
Last thing
These are habits that grew out of my own work, and I can't promise they all carry over to yours. But the "amnesiac genius new hire" metaphor might be worth something to you. What really saves time isn't the one formula that happens to work. It's writing down the lines you have to repeat, once, clearly. After that, every morning you're just handing it to a new hire.
Take whatever fits your hand.