Building a Reusable Agent Setup You Actually Carry Between Projects
Stop re-teaching the agent your commit format on every new repo. Build a personal layer that travels with you, kept clean of the client's project layer.
You clone a repo on Monday morning and spend the first two hours teaching the agent things you have already taught it five times. That your commit subjects are imperative mood and under seventy-two characters. That you want the smallest change that passes, not a tidy-up of the neighbouring module whilst it happens to be open. That when a test fails you want the failing assertion printed before any fix is attempted.
None of that is knowledge about the repository. All of it is knowledge about you, and it is exactly the part you keep retyping.
The fix is a personal layer that travels with you, kept strictly separate from the project layer that belongs to whoever owns the code. Two layers, one boundary. The boundary is the whole trick.
What belongs where
The project layer holds facts about this codebase. The package manager is pnpm and the lockfile proves it. Tests run with pnpm vitest run --reporter=dot, and the watch mode is broken on this repo because of a symlinked workspace. Migrations live in db/migrations and are applied by scripts/migrate.sh, never by hand. Editing anything under src/api/generated/ is pointless because the next build overwrites it.
Those facts are true for everyone who touches the repo, including the client's own developers and whoever picks it up after you leave. They belong in the repository, committed, reviewed like any other file.
The personal layer holds how you want to work. Your commit message format. Your review checklist: error paths first, confirm the test actually fails without the fix, confirm nothing new appeared in the dependency list. Your preference for diffs under roughly eighty lines unless you explicitly ask for more. Your debugging procedure, which probably begins with reproducing the failure in a single command before anything is edited. Your scaffolding scripts.
None of that is a fact about the client's codebase. It is a fact about you.
Mixing the two bites at handover. You finish an engagement, push the final commit, and the repository now contains a file explaining that Sam prefers to reason out loud before editing and dislikes barrel files. The client's team reads it, has no idea who Sam is, and either follows instructions written for somebody else or deletes the file wholesale, including the genuinely useful project facts that were sitting three paragraphs down. Worse, your personal file may still carry preferences absorbed from a previous client's stack that you never pruned, and now those are sitting in this client's git history.
The test for which layer something belongs in is simple. If the sentence would still be true in a repo you have never seen, it is personal. If it would be false, it is project.
Start smaller than you think
Most people over-build this on day one. They design a template hierarchy, three levels of config merging, and a small CLI to manage it, before they have carried a single instruction between two projects and confirmed it was worth carrying. Then they maintain the machinery instead of the content.
Start with one file and a five-line script.
The file is a Markdown document of your working preferences. Twenty to forty lines is plenty. The script copies it into a target project and makes sure it can never be committed by accident:
#!/usr/bin/env bash
# ~/dev/agent-setup/bootstrap.sh
set -euo pipefail
target="${1:-$PWD}"
cp ~/dev/agent-setup/personal.md "$target/AGENT-PERSONAL.md"
grep -qxF 'AGENT-PERSONAL.md' "$target/.git/info/exclude" 2>/dev/null \
|| echo 'AGENT-PERSONAL.md' >> "$target/.git/info/exclude"
echo "personal layer installed in $target"
Note .git/info/exclude rather than .gitignore. .gitignore is a tracked file, so adding your personal filename to it is itself a commit that leaks your setup into the client's repo. info/exclude is local to your clone and nobody else ever sees it. That one line is the difference between a clean handover and an awkward question in code review.
Copy rather than symlink at the start. Symlinks let you edit once and have every project pick it up, which sounds better than it is: you will eventually make a project-specific tweak, forget it was a symlink, and quietly change your defaults for every other repo on the machine. Copy is dumb and predictable. Move to symlinks later if you genuinely want the shared-edit behaviour.
Run it, work for a week, and notice which lines you actually rely on. Delete the rest.
A layout that survives, once one file is not enough
When the single file stops being enough, and it will take longer than you expect, split by kind rather than by project:
~/dev/agent-setup/
personal.md # working preferences, still the core file
bootstrap.sh # installs into a target repo
checklists/
review.md
debug.md
scripts/
new-vitest-suite.sh
bisect-failing-test.sh
templates/
pr-description.md
CHANGELOG.md
Keep it in git, in its own private repository, with real commit messages. In six months you will look at a line and wonder why it is there, and the commit that added it will usually tell you which project made you write it.
Starter repo or layered config
Two shapes solve overlapping problems. The starter repo is a whole project skeleton you clone and rename: build config, lint rules, CI workflow, a test harness, all pre-wired. The layered config is a thin set of files you drop into a repo that already exists.
The starter repo is right when you own the project from the first commit and you build the same shape of thing repeatedly. It is wrong the moment you join an existing codebase, and it has a slow failure mode: you end up carrying a dependency tree and a CI workflow you stopped believing in eighteen months ago, because updating the template feels like busywork until the day it breaks a client build.
The layered config is right for most consulting work, because most consulting work is joining somebody else's repo on day one. It also degrades gracefully. If a project ignores half your layer, the other half still works.
Portability, so you are not stuck with one harness
Write the content in plain Markdown and plain shell. Not in a format owned by one tool. Whatever you use today, Claude Code, Cursor, Aider, Codex, Windsurf, Zed, Continue, or something that does not exist yet, the harness-specific part should be a thin adapter that points at your plain files rather than containing them. Then switching tools costs you an afternoon of adapters, not a rewrite of everything you know about how you work.
The same logic applies to your scripts. A shell script that runs the test suite and prints the first failure works everywhere. A tool-specific macro that does the same thing works in one place.
Only promote what has proved itself twice
The rule that keeps this from turning into landfill: nothing enters the reusable layer until it has been useful on two separate projects. One project is a coincidence. Two is a pattern.
This is harder than it sounds, because the moment something works you want to enshrine it. Resist. Keep a scratch section at the bottom of personal.md for candidates, dated, and promote them when the second project confirms them.
Prune on the same schedule you would prune anything else, which realistically means once a quarter, or whenever the file gets long enough to make you scroll. A setup that only ever grows becomes a liability, and the failure mode is specific: nine hundred lines of instructions, of which the agent reliably honours the first two hundred and treats the rest as background noise. You then spend an afternoon debugging why it ignored a rule you wrote, and the answer is that you buried it.
The best version of this is embarrassingly small. A file you could read aloud in ninety seconds, a script short enough to fit on screen, and a git log that tells you what you learned. Everything past that should have to earn its place twice.
Keep reading
Rules, Skills and Hooks: Which One for Which Job
Rules are a request, hooks are a guarantee, skills are the procedure in between. A decision table and three worked examples for choosing.
The Tools Worth Paying For, and the Ones That Are Not
A category-by-category verdict on the subscriptions in your stack, plus the cancel test and a worked monthly budget for a solo developer.