Copying the last repo's agent setup into a new one worked at first. It also copied product-specific assumptions. Once I had several active projects, there was no longer a single canonical repo I could copy from. Every improvement now had several places it could drift.
I was doing that across Codenames AI, a portfolio site, and a resume generator. Shared workflows for planning, editorial work, dependency upgrades, review, and repo bootstrap had accumulated around them. Some still lived inside product repos simply because that was where they had evolved.
I wanted the next repo to start with the methodology already available, without cloning the implementation details of the last product.
My first instinct was to solve that with an MCP-shaped architecture. Extract the shared behavior into a separate repository. Expose it through a remote tool boundary. Every repo could call the same capability when it needed merge-safe planning rules or editorial workflow guidance.
That felt rigorous. One service. One contract. One place to version policy.
Why the MCP-shaped instinct looked right
The idea lived in notes and conversation: treat portable agent policy the way you would treat a remote tool.
Building it would have bought a clean contract. It would also have attached the baggage that belongs to real tools:
- a runtime or service boundary
- an MCP contract and deployment story
- versioning and invocation decisions
- "when do we call this?" routing inside every agent session
That overhead makes sense when the capability is genuinely external: query Notion, pull PostHog metrics, deploy through Vercel. It does not make sense when the capability is mostly operating methodology: how to slice plans, when to stop after opening a PR, how to keep merge-safe invariants explicit.
Planning standards and merge-safe workflows are agent policy and procedure. They are not remote resources waiting behind a tool boundary.
I never built that service. I did not need to.
What shipped instead: four durable scopes
The decomposition was the work: what should follow me into every repo, what should stay behind a tool boundary, what should stay with me as procedure, and what must live in the repo itself. I happened to implement that split in Cursor (user-level rules, MCP config, installable skills, repo files). The architecture is the scopes:
| Scope | Role | What belongs here |
|---|---|---|
| Always-on policy | Invariants in every repo | Short rules: execution authority, repository topology, stop-after-open, tool preferences, pointer to planning methodology. |
| Shared tools | External tool boundaries | Notion, PostHog, Vercel after you authenticate the service. |
| Reusable procedures | Workflow installation | Full portable skills such as staged planning and new-repo bootstrap. |
| Repo files | What must live in the repo | Stable mechanics (local hooks, remote environment lifecycle, CI) and product knowledge (AGENTS.md, domain rules, product skills, review guides) |
Always-on policy kept a pointer to the planning methodology instead of a second copy of it. Copying one product repo's harness into another just to match would have recreated the drift.
Shared tools stay behind that authenticated service boundary.
Reusable procedures stay at user level. The new repo does not store those skills. I run bootstrap once to write stable mechanics into repo files. That step does not copy the skill into the repo, and it does not write product knowledge because it varies by product.
The scopes also have different update semantics: policy changes flow across existing repos, while bootstrap changes become the baseline for new ones unless I explicitly migrate older repos.
The interview showed what still had to be reconstructed
The first serious cold-start test was a timed AI-native product-build interview. I used the same scopes in a genuinely new repo under time pressure.
The interview proved the methodology did not depend on my existing repos. It also showed that too much generic setup still had to be reconstructed in an empty one. The agent put instructions in the README instead of AGENTS.md. Hooks that should have wired the remote agent environment were not reliably set up. Setup that was obvious in my established repos was not obvious when an agent had to invent it under time pressure.
Policy, procedures, and shared tools were already available. What failed was leaving stable repo mechanics to be rediscovered. An empty repo still has to run those hooks and that remote environment. The following week I converted more of that baseline into deterministic bootstrap: known-good scripts and templates for local hooks, remote environment lifecycle, CI, and other baseline infrastructure, not another round of agent redesign.
The goal is not zero bootstrap. It is to stop spending agent reasoning on decisions I have already made.
Takeaway: Splitting the problem by ownership and lifecycle showed I did not need an MCP-shaped architecture. Policy could stay always-on, procedures could stay at user level, stable mechanics could be materialized by running bootstrap, and the agent could spend its reasoning on the product.
Top comments (9)
This boundary feels right to me. Repo-local agent rules are good for product facts, but planning habits want the same treatment as editorconfig or a shared CI template. Copyable, inspectable, and boring enough that a new repo can disagree without deploying a service.
I like the shared CI analogy. The ability for a repo to deliberately disagree is an important part of the boundary too. The shared layer gives me the default methodology, while repo-local state stays explicit when the product genuinely needs something different. That feels much healthier than copying the whole harness and slowly losing track of which differences were intentional.
This maps to a risk I keep seeing with agent setups. The expensive boundary is not where the tool call lives. It is where policy changes propagate without dragging along old product assumptions. Treating bootstrap as deterministic repo mechanics, and methodology as user-level procedure, seems like the right split.
Exactly. I think the propagation behavior is the part I was underweighting at first. Once I separated “should update everywhere” from “should be materialized into the repo once,” the ownership boundaries became much easier to reason about. Glad that distinction landed.
We drew the same line between shared tools and reusable procedures, with one boundary placed differently: our procedures load only when a task matches them, never always-on, on the assumption that anything present on every turn is also paid for on turns that do not need it. The README-instead-of-AGENTS.md slip is the part I recognise — our fix was not a better prompt either, but a commit-gate test that fails when the instructions point at a file that is not there. Bootstrap ordering is the piece I have not solved: whatever runs first sits outside the thing it configures, so it gets trusted rather than checked.
I agree with the task-matched loading point too. That was part of what made the MCP-shaped approach feel increasingly wrong for this. I would have been exposing a shared tool surface broadly when much of the methodology only needs to exist for the repos or tasks that use it.
I suspect my current plugin is still a coarser packaging boundary than the eventual one. It could decompose into skills that are enabled only where they are useful. Bootstrap can disappear once it has materialized the repo mechanics, while something like planning can remain as a thin reusable procedure.
That last point is interesting to me too. I ended up at almost the same place after the cold-start failure. If bootstrap is responsible for establishing an invariant, checking for it afterwards is weaker than making the bootstrap deterministic enough that the invariant is true by construction. I like your commit-gate example too. It turns a missing instruction from something the agent has to notice into something the repo can reject.
The “wrong boundary” realization really resonated with me.
A really good reflection, and I’m glad you wrote it down and shared it. These are the kinds of lessons that are easy to overlook when you’re in the middle of building things.👍️
Thanks, really appreciate that. This one took a while to get to the actual lesson. I kept thinking the problem was “how do I centralize this?”, when it was really “which things should propagate, which should be installed once, and which should live with the repo.” Glad the “wrong boundary” framing resonated.
Sometimes a change in perspective makes everything click. That moment when you finally see the real problem is pretty satisfying. 👊