← Machine Coding

Configuring Your Coding Machine

The model is only part of the system; configure the whole machine that turns assignments into software.

Chapter 06 taught the reader how to give a machine meaningful work. This chapter teaches how to equip the machine to perform it. Chapter 03 decided which intelligence each responsibility deserves. What follows decides what that intelligence can actually accomplish once it is switched on.

My central claim is simple, and I mean it as an engineering statement rather than a slogan:

The model is not the coding machine.

A coding machine is the model plus everything around it: the instructions it receives, the knowledge it can reach, the skills and capabilities installed, the connections to the outside world, the agent runtime that executes its decisions, the environment in which that runtime operates, the permissions that bound it, and the feedback that returns. Two agents built on the same underlying model can perform very differently on the same work package, because their machines differ. Configuring that machine is itself a programming decision — and, I have found, one with as much influence on the outcome as the choice of model.

The model is not the machine

Consider what actually happens when I hand a work package to a coding agent. The model must operate through instructions telling it how this project works, context describing the relevant system, tool interfaces for reading and changing files, execution machinery for running commands, permissions deciding what is allowed, and feedback showing what happened. Remove any of these and the same intelligence produces a different result: no repository access, a different assistant; no test runner, unverifiable claims; no conventions, idiosyncratic code.

Human intention plus a work package enters at one end. Implementation, verification, and feedback emerge at the other. Everything between those points is the configured machine, and every element is a decision I am responsible for. A well-written package can still fail because the machine receiving it was never properly equipped — and that failure belongs to my configuration, not to the model I chose.

Chapter 03 allocated intelligence to responsibilities. This chapter equips each allocation to succeed.

Instructions: teach the machine how this project works

Every serious coding setup needs a place where the project tells the machine how work is done here: conventions, architectural invariants, approved patterns, test commands, code ownership, scope. The AGENTS.md convention has become the portable form of that place — a README-for-agents that participating tools discover automatically, with nested files letting each directory speak for itself and explicit task prompts overriding whatever the files say.

ALIVE’s own AGENTS.md shows what good looks like in practice, and it does not begin with commands. It begins with direction: what the product is for, which document governs, what to reuse before building, what counts as evidence. Only then do the tiers of verification follow — fast targeted checks for ordinary edits, integration checks as a separate tier, full-suite qualification as an explicit decision, never the default. The file even forbids its own misuse: no slow suites on a whim, no editing the test policy to dodge it. That is instruction as design, not instruction as accumulation.

Precedence matters as much as content, and it varies between tools, so I work within my project’s applicable instruction hierarchy rather than assuming universals: the nearest instruction file governs the files beneath it, explicit task instructions override standing files, and human directions in the conversation override both — while no repository instruction or task prompt overrides higher-priority system constraints, enforced security boundaries, or permissions the environment simply does not grant. Where two standing instructions conflict, the conflict itself is the finding, and I resolve it by editing the files, not by hoping the machine picks wisely. And I resist the archival impulse to pour all historical knowledge into one enormous instruction file: a repository manual that must be loaded for every typo fix is not guidance but tax, paid in context on work that never needed it.

Accumulation is the failure mode, and I have learned to treat it as the default outcome rather than the exception. An instruction that helped an older, weaker model — read three architecture documents before every edit — can become pure overhead once the model can find what it needs itself. OpenAI’s September 2026 guidance for its newest coding models makes exactly this point from the vendor side: revisit accumulated skills, AGENTS.md files, and prompts, because over-specific guidance that once helped can now hinder, and instructions that apply on every edit must each earn their place. I keep instructions concise, actionable, current, and grounded in the actual repository — and I re-read them the way I re-read code, because unlike code they fail silently, producing slightly worse work everywhere instead of an error anywhere.

Skills and reusable capabilities

Instructions tell the machine how to behave. Capabilities determine what it knows how to do — and these deserve sharper words than they usually get. A reusable instruction is guidance the model follows in prose. A tool is an action it can invoke with inputs, outputs, and failure modes. A workflow combines actions toward a result. A governed capability wraps all of that in a defined interface with permissions attached. They overlap constantly in conversation; they are not the same thing in engineering, and confusing them is how a team comes to believe a machine can do something it merely read about.

The portable skill formats that have emerged — a SKILL.md file with metadata up top, instructions in the body, optional scripts and references alongside, loaded progressively so the agent sees the catalogue cheaply and the details only on demand — are a genuine advance in packaging reusable knowledge. They reduce duplicated instructions and travel between tools. But everything depends on the receiving end: whether the skill is discovered, how it is selected, what context its activation consumes, whether its scripts actually run in this environment, and whether anyone has tested the procedure it describes.

ALIVE’s skill_forge illustrates the disciplined end of this spectrum, and I cite only what its code supports: handlers owned by the host, no mechanism by which a model registers capabilities or grants itself power, an explicit owner request required before anything runs, bounded results. Installed is not invoked; invoked is not effective. The question I ask of every capability is not whether it exists in the setup but whether I have seen it selected for the right reason, used correctly, and producing a better outcome — in the retained tool calls and results, not in the model’s description of what it did. That means keeping evidence the model cannot grade itself on: which tools were actually called, with what inputs, what came back, and whether the outcome changed anything verifiable. A capability whose use leaves no such trace is a story the setup tells about itself, and I have learned to price stories accordingly.

Connections: what the machine may touch

A coding machine that cannot reach beyond its own context is safe and useless in equal measure; one that can reach anywhere is useful and dangerous in the same proportion. The Model Context Protocol has become the standardised way to connect AI applications to tools, resources, and reusable prompts — and its 2026 revision history, including a stateless core and a formal extension process, is itself evidence that this layer moves fast enough to date any specific advice I give about it. So I will not write a connection tutorial. The engineering questions are stable even as the answers change: what is exposed, which operations are permitted, what information crosses the connection, how failure is handled, and what evidence survives the exchange.

The distinctions that matter are about authority, not plumbing. Read-only access to an API specification is a different grant from permission to mutate production data, and a chapter that cannot tell those apart has no business configuring either. Failure modes differ accordingly: a dead read is an inconvenience the machine should report and route around, while a failed write may have changed the world halfway and must leave evidence of exactly how far it got. Authorising a connection is a Chapter 05 decision — a non-negotiable enforced by credentials, scopes, and approval mechanisms, never by the model’s willingness to behave. Within those bounds, connections are ordinary configuration: give the machine the sources its assignment requires, verify what it actually fetched, and treat every external dependency as a liability to be justified, not an asset to be collected.

Memory: continuity without confusion

A machine-coding project lives across sessions, and something must carry knowledge between them. But memory is several different things wearing one name: the context window’s current contents, retrieved documents, retained conversation records, persistent memories, and authoritative repository documentation. These are not interchangeable, and successful configuration keeps them distinct.

The tests I apply are practical. Can a future session recover the right knowledge? Does it know where that knowledge came from — a verified decision, a model’s suggestion, an observation nobody confirmed? Can it detect that the repository has changed since the knowledge was recorded? A remembered claim is not a verified description of the current codebase; provenance, freshness, and relevance decide whether a memory is an asset or a trap. Stale knowledge, confidently applied, damages more than ignorance, which at least asks questions.

Chapter 06’s durable records are my continuity bridge: the application map and package records are memory with provenance, updated by accepted changes rather than accumulated by conversation. Everything else I treat as untrusted until checked — useful, often, but never authoritative. Contradictions get the same treatment as staleness: when two retained claims disagree, neither wins by seniority, and the resolution — re-read the source, prefer the newer verified record, or mark both unknown — is itself recorded, so the next session inherits the adjudication rather than relitigating it.

The runtime: the machinery around the model

Beneath the model sits the part of the machine most developers never inspect: the agent harness and its execution environment. The harness decides how the model operates — how it reads files, executes commands, receives tool results, manages context, selects branches and working directories, hands work to subagents where supported, handles failure, and recovers. The environment underneath decides what those operations can actually touch.

This is where the distinction between model capability and effective capability becomes concrete. A stronger model in a poor harness — no test execution, clumsy context handling, no recovery — can easily lose to a weaker model whose environment lets it try, check, and correct. When I evaluate an agent setup, I ask which behaviours belong to the model, which to the harness, and which to the operating environment, because each has a different remedy when it fails.

ALIVE’s Pi runner is my standing example, and its source states the layering more precisely than my first draft did. The file calls Pi an untrusted child, and its launch flags — no tools, extensions, skills, prompt templates, context files, session, MCP, or automatic approval, offline — are described as defence in depth, explicitly not the security boundary. The boundary is structural: Pi never holds the real provider credential, only a run-scoped token for ALIVE’s own egress, and it cannot make ALIVE forward a request ALIVE has not approved. Four layers, each doing a different job: model instructions about allowed behaviour; harness-level feature restrictions; the operating environment’s own process constraints; and host-enforced authorisation with provider egress control. The flags reduce what a compromised or confused agent can reach for; the credential and forwarding design decides what can actually leave. My original telling blurred that distinction, implying the flags alone established the guarantee. They do not — and that is exactly the chapter’s lesson in miniature. Understanding a coding machine means looking past its visible settings to where enforcement really lives. The same scrutiny applies to the unglamorous choices: which directory and branch the agent starts in, what survives a crashed run, how a half-finished change is found and resumed or rolled back. A harness that cannot recover cleanly turns every transient failure into a corrupted workspace, and no amount of model intelligence compensates for a floor that collapses. Instructions say how the machine should behave; the harness decides what it can do. Chapter 05 established the principle; here is what it looks like in a launch command.

Configure for the work, not once for everything

Different tasks deserve different machines. Exploration may need broad but authorised research access and tolerance for long context; bounded implementation needs a well-defined repository scope and an executable test environment; independent review needs a separate context, adversarial evaluation tools, and restricted modification authority — a reviewer that can rewrite the code under review is not a reviewer. Chapter 03’s allocation of strong and economical intelligence only pays off if each allocation arrives in an environment suited to its job. An exploration agent benefits from broad, authorised read access and room for long context; an implementation agent wants the opposite — the narrowest scope that contains the task, with the test command ready and the network closed. A review agent gets a fresh context, the evidence but not the implementer’s narrative, and tools for adversarial checking with no authority to rewrite what it judges. Same underlying models, potentially; unrecognisably different machines.

I keep two levels. The stable baseline — repository conventions, standard capabilities, the execution environment, permissions — changes slowly and deliberately. The task-specific configuration — relevant context, enabled tools, the workflow for this package, its scope, and its verification requirements — is assembled per assignment and discarded or retained on merit. The rule that holds both together: task-specific configuration must never silently weaken established safety boundaries. Convenience for this task is not a reason to widen what the machine may touch; if the task genuinely needs more authority, that is a human decision, recorded in the charter, not a flag flipped for the afternoon.

When configuration makes things worse

This section exists because the failure it describes is the common one. More configuration is not better configuration. Overlong instructions that bury the three that matter. Conflicting rules from different eras of the project. Irrelevant skills whose descriptions consume context on every task. MCP connections nobody uses but everybody pays to list. Stale memories confidently misdirecting fresh work. Excessive retrieval drowning the relevant file. An execution environment with more authority than any task requires. Each addition once seemed helpful; together they make the machine slower, more confused, more expensive, and less safe.

A good coding machine may be deliberately simpler than one with dozens of instructions, skills, connections, and memory sources. Simplification is a legitimate configuration improvement, and I schedule it the way I schedule any maintenance: when failures start pointing at the setup rather than the task — the worker ignoring relevant guidance, loading irrelevant context, choosing wrong tools, or burning tokens wandering — I diagnose the evidence. The plausible causes sit at different layers: task design, missing context, instructions, capability selection, genuine model limitations, runtime, environment, or the implementation itself. A weaker model may truly lack what the task needs; a missing test runner is a configuration failure; a flawed work package is a task-design failure. I inspect what actually failed and pursue the most plausible layer first. The point is to identify the cause rather than retry blindly or reflexively swap the model — though I will note, as observed practice rather than measured frequency, that the configuration layers are the ones teams most often overlook.

A short illustration, explicitly hypothetical, shows the diagnostic habit in action. I assign the arcade game’s restart transition to a coding agent in a fresh checkout. It returns quickly with a plausible diff and a confident summary — but no test evidence: it reports that the test command is unavailable in its environment. The temptation is to conclude the model is weak and retry with a stronger one. Instead I check the machine. The repository contains a test script and the dependencies are installed — but the agent’s working directory was set to a parent folder where neither is reachable: a runtime misconfiguration, not a reasoning failure. I correct the working directory within the existing permissions, rerun the identical assignment, and this time the evidence comes back. The tests execute; one fails; and that failure exposes a genuine implementation defect in the transition’s edge handling — a separate matter, diagnosable precisely because the configuration defect is gone. Had I swapped models first, I would have paid a stronger intelligence to inherit the same broken floor. Before changing the model, understand which part of the coding machine failed. Configuration defects masquerade as model defects; the way to tell them apart is to inspect the environment before upgrading the intelligence. And note what making the tests available did not do: it guaranteed nothing about whether the implementation would pass them.

Test the coding machine

Here is the discipline that turns configuration from taste into engineering: compare environments against each other on the same work. The protocol I propose uses the recurring arcade-game repository from Chapter 06 and a bounded modification such as the restart fix. The model, the assignment, the starting repository state, the executable test runner, the permissions, and the baseline safety restrictions stay identical in both arms. Configuration A is a minimal, functioning agent environment: the repository, the test runner available, nothing else. Configuration B keeps that same runner and permissions and adds a selected package of verified repository instructions, relevant skill guidance, and curated context — and it may encourage or automate use of the existing test runner, which is a change in guidance, not a capability A lacks. Then compare what matters: correctness of the result, preservation of the invariants, integration success, correction effort, elapsed time, and token or resource use where measurable.

This is an illustrative protocol, not a completed experiment — no demo has been run, no outcomes are claimed. What it would establish, run honestly, is whether the configured environment outperforms the minimal one on this task, and by what margin on each measure. What it would not establish is which component deserves the credit: changing several variables together tests the bundle, not the causes. A follow-up experiment may isolate one variable at a time — instructions alone, then context, then tooling — with equivalent task instances and independent evaluation to reduce chance and evaluator bias. Whole-bundle comparisons tell you whether to keep the package; isolated comparisons tell you what to change next. Confusing the two is how teams adopt cargo-cult configurations, keeping every setting because something, somewhere, once helped.

A coding machine that evolves

Everything above decays. Models improve and yesterday’s scaffolding becomes today’s drag. Runtimes change what the harness can do. Context strategies evolve. Protocols are revised — the MCP changelog I cited will itself be history within a year. Skills appear, connections rot, memories go stale. A coding machine is not a setup; it is a garden, and the price of a good one is regular attention.

I keep that attention cheap with two habits. First, a lightweight Coding Machine Configuration Record: the model and provider, the agent runtime and version, applicable instruction sources, available capabilities, authorised connections, relevant memory and context sources, execution boundaries, and how the setup is verified. Enough to reproduce the working machine, never a place for credentials or secrets. Second, a cycle I run whenever anything important changes — configure, test, observe, adjust, retest — against representative work packages, keeping a known-good baseline and changing one important dimension at a time where practical. A new capability is adopted because it improved a measured outcome on my work, not because it exists.

What I am really maintaining is not a settings file but a correspondence: between the machine I think I have and the machine that actually shows up in the tool calls, the fetched context, and the verified results. When those two machines agree, configuration disappears into the background and the work flows. Keeping that agreement is itself a modern programming skill — and it is never finished, because neither are the machines.

With the machine equipped, the method’s present engineering is in place: foundations, intelligence, intent, system, packages, machine. Before turning to how we judge that machine and keep control of what it produces, the next chapter steps back to ask what all of this amounts to. That is the subject of A New Approach to Technology.