← Back to Home

Why My Core Does Almost Nothing (And Why Yours Should Too)

In a single working session I designed four systems that have nothing to do with each other. A code-tidying tool. A neutral UI layer for a design system. A ledger for tracking value over time. And a fresh substrate for orchestrating AI agents. Different domains, different stakes, sketched hours apart.

They all came out the same shape.

Every one of them ended up as a small core that does almost nothing on its own, plus a ring of opinionated pieces bolted on the outside. The core held the mechanism. Everything that made each system specific, the conventions, the brand, the policy, the domain knowledge, lived outside the core, in something I could swap without touching the engine.

When the same shape shows up four times in an afternoon, across four unrelated problems, it isn't a coincidence. It's a principle asking to be named. So I named it: minimal, unopinionated core; opinionated capabilities as connectors. It's the same idea the textbooks call mechanism-not-policy, or microkernel, or ports-and-adapters. I just hadn't been applying it on purpose.

Mechanism, not policy

The whole discipline rests on one cut. You split every system into two kinds of thing, and you are ruthless about which side each piece lands on.

The core is mechanism. It does the irreducible work and holds the contract that everything else plugs into. It is generic, domain-agnostic, and stable. It is the part you trust, the part you test hard, the part you change rarely and deliberately.

The connectors carry the opinion: the policy, the domain knowledge, the taste, the things that make this system this system and not a generic one. Connectors are specific, swappable, and they churn freely. You add behavior by adding a connector, never by editing the core.

The test for which side a piece belongs on is a single question, and you ask it at every fork: is this mechanism, or is this policy? A scheduler is mechanism; the rule that night jobs run at 2am is policy. A renderer is mechanism; the brand's color palette is policy. Mechanism goes in the core. Policy, domain knowledge, anything opinionated, goes out to a connector. When you genuinely can't tell, it doesn't belong in the core. Default outward.

Three disciplines

First, ask the fork question until it's a reflex. Not "where should this go architecturally," not "what's cleanest." Just: is this thing a general capability, or is it an opinion about how the capability should be used? You keep cutting at that joint, decision after decision, and the partition draws itself.

Second, push opinion outward, aggressively. The instinct is to be helpful by baking convenience into the core. Resist it. Every opinion you absorb into the core is a future regret: it makes the core bigger, less general, harder to trust, and impossible to hand to anyone who holds a different opinion. Define the core as the smallest thing that's still genuinely useful, then shove everything else out. If a feature can live in a connector, it must.

Third, treat the connector contract as half the value. This is the part people skip. A minimal core is worthless if the only way to extend it is to fork it. The extension point, the contract that connectors plug into, is not an afterthought. It is half of what the core is for. A sharp, stable contract is the thing that lets all that opinion churn on the outside without ever reaching in and destabilizing the engine. Design the seam as carefully as you design the engine. Maybe more carefully, because the engine you can change later and the contract you mostly can't.

Four designs, one shape

The principle is abstract. The evidence isn't. Here are the four, and where each drew the line.

The agent substrate. This is the cleanest instance, the one that made the pattern obvious. The substrate is pure mechanism: it knows how to run agents, route messages, and hold the contract. It knows nothing about what capabilities exist. Capabilities are connectors, declared in a single file. You drop a connector into that file and you get a new capability with zero core change. No recompile of the engine, no regression sweep across the substrate, no risk to the part that has to stay trustworthy. New behavior ships as a connector, full stop. Once you've felt how cheap evolution gets, you start wanting every system to work this way.

The neutral UI layer. A design system splits the same way, and you can read the split straight off the file tree. The structural core is a tokens file: type scale, spacing, motion. It has no brand in it at all. The opinion lives in a brand theme, a separate file, which is where the actual colors, fonts, and identity sit. A voice guide rides alongside as a third, orthogonal connector governing what the copy says. Want a different brand? Swap the theme. The tokens, the templates, the components never move.

The value ledger. The ledger's core is a recording mechanism: a clean, generic way to capture and total units of value over time. What counts as value, how it's weighted, which categories matter, all of that is policy, and all of it belongs in config rather than in the ledger engine. The engine doesn't have a worldview about impact. The config does. Change your mind about how impact is scored and you edit config, not the thing that does the arithmetic. (This one is still a design on paper, and the first thing the design told me was to ship a deliberately tiny version before automating anything, which is the same discipline pointed at scope instead of structure.)

The tidy tool. Same cut, and this one is built. The core is a mechanism that walks, reads, and rewrites a codebase safely. It contains no knowledge of the specific project it runs on. The conventions, what "tidy" actually means here, live entirely outside the core as a config object the core consumes. The mental model is exactly an ESLint engine versus an eslintrc file: the engine is generic and sellable on its own; the rules are your opinion, dropped in from outside. The separation is enforced, not just intended. There's a test that greps the core for any project-specific reference and fails the build if it finds one. The core literally cannot learn an opinion by accident.

Four problems. One answer. The thing that varied was only ever where exactly the line fell, and that is the hard part.

The hard part is drawing the line

Everything above is easy to say and hard to do, because the entire skill is in where you cut. Both failure modes are real, and both are common.

Put too much in the core and you get a rigid, bespoke thing. Every new opinion forces a core change, so the core never stabilizes, never earns trust, and can't be handed to anyone who'd hold a different opinion. You've built a custom system and called it a platform.

Put too little in the core and the opposite hurts you. The core does nothing useful, so complexity floods the connectors. Every connector ends up re-implementing the mechanism that should have been shared. You've built a contract with no engine behind it, and now the duplication lives everywhere instead of nowhere.

There's no formula for the line. There's only the fork question, asked relentlessly, plus a willingness to correct: when a connector turns out to need a mechanism only the core can provide cleanly, you move that mechanism in, deliberately, and tighten the contract around it. The line is found, not declared.

Why a boring core sells

This isn't only an engineering argument. It's a business one, and for me that's the part that makes it non-negotiable.

A core that refuses to absorb opinion stays trustworthy. That matters most exactly where it's hardest: auth, money, destructive actions, anything irreversible. You want the part that can wipe data or move money to be the part that almost never changes. Opinion churning through it is how you get the 2am incident.

And a minimal, mechanism-only core is a product. The opinion that would make it bespoke, and therefore unsellable, is precisely the opinion you've already pushed out to connectors. A buyer swaps your connectors for their own and keeps your engine. That's the difference between selling a system and selling a one-off you happened to build for yourself. The tidy tool is the clearest case: because its core holds zero project-specific opinion, the engine is a sellable refactoring tool in its own right, and my conventions are just the first config that happens to run on it.

Cheap evolution falls out of the same property for free. New behavior is a new connector, not a core edit plus a regression sweep. The system gets faster to change the longer it lives, which is the opposite of how most systems age.

The discipline, restated

Strip it to three moves and it fits on an index card. At every design fork, ask: mechanism or policy? Mechanism in, policy out. The core is the smallest thing that's still genuinely useful; when unsure, it goes out. And the connector contract is half the value, so design the seam as carefully as the engine.

I didn't invent any of this. Microkernels and ports-and-adapters have been around longer than I have. What changed for me was applying it deliberately instead of stumbling into it, and noticing that when four unrelated designs converge on one shape in an afternoon, the shape is trying to tell you something. The core does almost nothing. That's the point. The less it does, the more it's worth.

If you build systems, try the cut on the next thing you design. Find the smallest core that's still useful, push everything opinionated outward, and obsess over the seam between them. I suspect you'll notice what I did: most of your system was never mechanism. It was opinion wearing a mechanism's clothes, and it belonged outside all along.