The Alpha
The Alpha is the working prototype of the Preconfiguration engine: one Go program called preconfig, its tests, a few tools and a demo. It reads one short spec, preconfig.yaml, and writes the setup file each platform reads: a dev container, GitHub Copilot’s setup workflow, Cursor’s environment, cloud-init and a plain setup script. It checks the setup files a repository already has, drafts a spec from a repository, and proves a setup on a clean machine.
Everything so far ran on one Linux machine, a virtual machine with two CPUs. The demo’s repositories are samples written for it. The generated files pass each platform’s published schema and its own tools, and the setup script has run on a clean Ubuntu 24.04 container, but no coding agent platform has run them yet: Copilot, Cursor and Codespaces themselves are the job of the Beta.
Where it stands. A working compiler, checker and verifier, tested hard on one machine and proven on a clean one. Next it has to prove itself on the agent platforms themselves, with real repositories.
- 5 platforms: written from one
preconfig.yaml, and every generated file passes the schemas and tools that exist for it. - About 1 minute: from a clean Ubuntu 24.04 container to passing tests, with PostgreSQL and Redis running: 49.6 to 73.0 seconds over three runs.
- 32 of 32: deliberately planted bugs caught by the tests.
- 3.3 MB: the whole engine, one binary built on Go’s standard library alone.
On this page: In brief · How it is built · The spec · The targets · Check and detect · Verify · Tests · Speed and size · Features and limits · The demo · Where it stands
The Alpha in Brief
| Area | Status | Key figures |
|---|---|---|
| Engine | Complete for the Alpha scope | One Go program: 6,842 lines in 19 files, standard library only |
| Spec | Working | Node.js, Python and Go; pnpm, yarn, uv and Poetry; PostgreSQL and Redis; 28 checks with line and column |
| Targets | Five, generated and validated | Dev container, GitHub Copilot, Cursor, cloud-init, setup script. Every file passes the schemas and tools that exist for it |
| check and detect | Working | 28 kinds of finding: 22 on the four platforms’ formats, 6 on disagreements and drift. detect rebuilds all three sample specs from their repositories |
| verify | Working with Docker on Linux | A clean Ubuntu 24.04 container. READY in 49.6 to 73.0 s; a missing service caught at the ready step |
| Tests | Many kinds, on one machine | 110 test functions; 32 of 32 planted bugs caught; about 25 million fuzzed inputs; 90.5% of statements covered |
| Browser build | Working | The same engine compiled to WebAssembly: 1.0 MB, 373 KB compressed, with the same answers as the standard Go build and the same files as the command line |
| Readiness | TRL 4 | “Technology validated in lab”, on the European Commission’s scale |
How It Is Built
- One program. preconfig is one binary with no daemon and no account. It runs when you run it and leaves plain files behind.
- Go, standard library only. Go 1.24, with no third-party modules at all. That includes the file readers: preconfig carries its own strict YAML reader and its own JSON reader, both of which report the line and column of every problem.
- Deterministic. The same spec gives the same bytes every time. That is what lets check tell a file that drifted from one that was just built.
- Strict spec. Every spec carries a version number. An unknown key is an error, reported with its line, its column and, when it is a likely typo, the key that was probably meant.
- One knowledge base. The platform facts that change most, from the Copilot job name and its limits to the latest action versions and the versions each runtime and service can have, live in one file with the date they were last checked: September 29, 2026. The rest of each format lives in the generators and the checks.
- License. The engine is not public yet. The license will be chosen before the first public release. The plan is a proprietary engine, with an open-source branch under consideration. Until then the prototype is marked “all rights reserved”, and the live demo is the way to see it run.
| Part | Lines | What it does |
|---|---|---|
| cmd/preconfig | 369 | The command line: detect, build, check, verify, targets and version |
| spec | 798 | Reads preconfig.yaml and checks it: 28 checks on the spec, with hints |
| yaml | 1,231 | A strict YAML reader that keeps key order, lines and columns |
| jsonc | 365 | A JSON reader with comments and trailing commas as separate switches, as each platform needs |
| tree | 366 | The document tree, the JSON writer, YAML quoting and typo suggestions |
| kb | 202 | The knowledge base: action versions, feature versions, job names, keys, limits, the date |
| gen | 1,071 | The five targets, the setup script and the notes build prints |
| check | 1,087 | Format checks for each platform, cross-checks between files, and drift from the spec |
| detect | 611 | A draft spec from version files, manifests, lockfiles, compose files and example environment files |
| textdiff | 171 | The unified diffs check prints |
| verify | 472 | The clean-machine run, its events and its exit codes |
| cmd/wasm | 99 | The browser build: build, check and detect for the demo |
The Spec
preconfig.yaml says what a machine needs, not how each platform should install it. The orders-api sample, a Python service with PostgreSQL and Redis:
version: 1
name: orders-api
runtimes:
python: "3.12"
services:
postgres:
version: "16"
user: orders
password: orders
database: orders
redis: "7"
env:
DATABASE_URL: postgres://orders:orders@localhost:5432/orders
REDIS_URL: redis://localhost:6379/0
secrets:
- PAYMENTS_API_KEY
setup:
- python3 -m venv .venv
- .venv/bin/pip install -r requirements.txt
ready:
- .venv/bin/pytest -q
- Runtimes. Node.js 20, 22 and 24; Python 3.10 to 3.14; Go 1.24 to 1.27. Node.js 20 reached its end of life in April 2026, and the Beta’s first update to the knowledge base drops it.
- Tools. pnpm, yarn, uv and Poetry, with an optional version such as
pnpm@10. - Packages. Ubuntu packages by name, such as
libpq-dev. - Services. PostgreSQL 13 to 18, with a user, a password and a database; Redis 7 and 8. They answer on localhost on every target.
- Environment and secrets. Variables with values that are safe to commit, and secrets by name only.
- Setup and ready. The project’s own commands, and the check that proves the machine works, usually the tests.
- Targets, base and repo. Which files to write (all five by default), the base system (Ubuntu 24.04) and, for cloud-init, the repository to clone.
The spec is checked before anything is written. A few of the 28 checks:
| Code | What it catches | Example |
|---|---|---|
| S002 | An unknown key, with the likely one | runtime: → did you mean runtimes? |
| S021 | A Node.js release the Alpha doesn’t install | node: "21" |
| S030 | An unknown tool, with the likely one | pnmp → did you mean pnpm? |
| S050 | A service this version can’t set up | mysql: "8", planned |
| S061 | A secret’s value written in the file | NPM_TOKEN: abc123 under env |
| S062 | A variable pointing at a service nothing starts | REDIS_URL on localhost with no redis under services |
| S081 | No ready check, so verify can’t prove anything | a spec without ready |
| S082 | A setup command using a tool the spec doesn’t list | pnpm install without pnpm under tools |
The Five Targets
preconfig build writes these files. Every file except Cursor’s environment.json, which stays plain JSON, starts with a line saying preconfig wrote it and that changes belong in preconfig.yaml.
| Target | Files | What is in them | Checked with |
|---|---|---|---|
| Dev container | .devcontainer/devcontainer.json, and compose.yaml when there are services |
The Ubuntu 24.04 base image, the runtime features, the services beside the container on its localhost, the environment, the secrets by name, the setup commands | The dev container JSON schema, the devcontainers CLI 0.89.0, docker compose |
| GitHub Copilot | .github/workflows/copilot-setup-steps.yml |
A job named copilot-setup-steps on Ubuntu 24.04, the setup actions at their latest versions, the services, the setup commands, and the ready check when the workflow runs on its own | SchemaStore’s GitHub workflow schema, actionlint 1.7.12 |
| Cursor | .cursor/environment.json and .cursor/Dockerfile |
A Dockerfile that runs the setup script’s machine step, with install and start commands for the project and the services | Cursor’s environment schema; the Dockerfile, built for orders-api and started with its services |
| cloud-init | cloud-init.yaml |
The setup script, written to the new server and run once at first boot, and the clone when the spec names a repo | cloud-init’s schema, and cloud-init 26.1’s own schema check |
| Setup script | .preconfig/setup.sh |
Four steps, machine, services, project and ready, each printing a marker line; the base of cloud-init, Cursor and verify | shellcheck 0.9.0, bash -n, and runs on a clean machine |
The Copilot workflow runs on its own when the workflow file or preconfig.yaml changes, and then it ends with the ready check, so a pull request that breaks the setup fails there, before Copilot relies on it. The ready check is meant to be skipped when Copilot runs the job before a session. GitHub doesn’t document which event those runs report, so the Beta checks that on the platform.
Every value written into YAML reads back as the same string. A differential test sends 64,686 strings, the special characters of YAML and every value it reads as a number, a date or a boolean, through the engine’s quoting and reads them back with five YAML readers in four positions: PyYAML, which cloud-init uses, ruamel.yaml, the yaml package in its 1.2 and 1.1 modes, and js-yaml. None came back different.
Check and Detect
preconfig check reads the setup files a repository already has. It finds three kinds of problem:
- Mistakes that show up only when an agent starts. Copilot stops with an error when no job is named exactly copilot-setup-steps, and ignores job settings other than six; Cursor’s schema rejects keys it doesn’t define; a dev container needs something to start. Nothing flags these when the files are written, so the first sign is a session that goes nowhere.
- Files that disagree. Without a spec, check reads the versions each file installs and warns when they differ: Node.js 20 in the Copilot workflow and 22 in the dev container.
- Drift from the spec. With a spec, check builds every target in memory and compares it with the file in the repository, line by line.
--diffprints the difference.
| Code | Platform | What it catches |
|---|---|---|
| C002 | GitHub Copilot | No job named copilot-setup-steps. With one other job, check names it and still checks it |
| C004 | GitHub Copilot | A job setting Copilot ignores, such as env or container |
| C005 | GitHub Copilot | timeout-minutes above Copilot’s limit of 59 |
| C006 | GitHub Copilot | An Arm or macOS runner; Copilot runs on Ubuntu x64 and Windows x64 |
| C007 | GitHub Copilot | A workflow that never runs on its own, so a broken setup shows only in a session |
| C010 | GitHub Copilot | The file in a place Copilot never reads |
| K001 | Cursor | A trailing comma: Cursor’s schema allows comments but not trailing commas |
| K002 | Cursor | An unknown key, such as update where Cursor expects install |
| K004 | Cursor | A Dockerfile path that doesn’t exist, resolved as Cursor does, from the .cursor folder |
| D002 | Dev container | Nothing to start: no image, build or compose file |
| I001 | cloud-init | A first line other than #cloud-config, so cloud-init ignores the file |
| X002 | Every target | A file that differs from a fresh build |
| X003 | Every target | A file that installs another version than the spec |
| X004 | Every target | A file that doesn’t install something the spec needs, such as PostgreSQL |
preconfig detect drafts a spec from the files a repository already has: .nvmrc and .python-version, package.json and pyproject.toml, the lockfiles, go.mod, the compose file and .env.example. Comments in the draft name the file each part came from, and names that look like secrets go under secrets. It reads files and runs nothing. On the three sample repositories, the drafts load to exactly the specs written by hand.
Verify
preconfig verify starts a fresh container from the spec’s base image, copies the repository in, runs the generated setup script and then the ready check. The script prints a marker line at each step, so verify can report each step with its time, and name the step that broke with its exit code and the last lines it printed.
| Exit code | Meaning |
|---|---|
| 0 | Ready: the setup worked and the ready check passed |
| 1 | Not ready: the setup worked, the ready check failed |
| 2 | A setup step failed |
| 3 | verify couldn’t start a clean machine: no Docker, or no image |
| 4 | preconfig.yaml has errors |
The orders-api sample, run three times on a clean ubuntu:24.04 container, and three times more with Redis left out of the spec:
| Run | Result | Time | Detail |
|---|---|---|---|
| Full spec, 1 | READY | 49.6 s | Python 3.12.3, PostgreSQL 16.15, Redis 7.0.15; 4 tests passed |
| Full spec, 2 | READY | 68.7 s | Same versions and result |
| Full spec, 3 | READY | 73.0 s | Same versions and result |
| No Redis, 1 | NOT READY, exit 1 | 55.1 s | Failed at the ready step: 3 tests failed on a refused Redis connection |
| No Redis, 2 | NOT READY, exit 1 | 64.4 s | Same result |
| No Redis, 3 | NOT READY, exit 1 | 71.0 s | Same result |
Most of the spread is downloads: the system packages step took 14.8 to 24.0 seconds. In the fastest run the steps took 14.8 s for the system packages, 6.8 s for Python, 9.9 s for PostgreSQL, 3.6 s for Redis, 2.6 s to start the services, 6.9 s for the project and 0.5 s for the tests, and Docker took 3.6 s to remove the container.
On September 30, after the last changes to the engine, the full spec ran twice more: READY in 62.2 and 55.8 seconds, with the same versions and 4 tests passed. Without Redis it stopped at the ready step again, in 54.0 seconds.
The same setup built as Cursor’s Dockerfile took 45.4, 42.4 and 52.3 seconds in three builds, and after the last two, the image started PostgreSQL and Redis with the environment’s start command. On the test machine, which reaches the internet through a proxy that inspects TLS, verify ran with --network host and --ca-file, which makes the machine trust the proxy’s certificate.
Tests
| Kind | What it covers | Result |
|---|---|---|
| Unit and table tests | Every package: the readers, the spec checks, each target, each finding, detect, verify’s parsing, the command line | 110 test functions, all passing; two of them run from their scripts, the clean-machine run and the quoting dump |
| Golden files | The files of three sample repositories, compared byte for byte, and built twice to prove they don’t change | Identical |
| Platform schemas and tools | Seven specs, every target but Cursor’s Dockerfile: JSON schemas, actionlint, shellcheck, docker compose, the devcontainers CLI, cloud-init’s schema check | 28 of 28 schema checks, and every tool clean |
| The setup script, run for real | Setup and ready run under bash; a failing step named with its exit code; environment variables round-tripped | Passing |
| Clean machine | verify on ubuntu:24.04, with and without Redis | 3 of 3 ready; 3 of 3 not ready at the right step |
| Fuzzing | The YAML and JSON readers, the spec, check, detect and the quoting | About 25 million inputs with no failures, after one early find was fixed |
| Differential | YAML quoting read back by five YAML readers; the browser build against the command line | 0 of 64,686 strings changed; 39 of 39 answers and 21 of 21 files identical |
| Planted bugs | 32 small mistakes planted one at a time | 32 of 32 caught |
| Coverage | Statements run by each package’s own tests, over the engine’s packages | 90.5% |
Planted Bugs
A tool plants one realistic mistake at a time in the engine, runs every test and puts the code back. A mistake the tests don’t catch points at a missing test. All 32 were caught:
| Where | The planted mistake |
|---|---|
| Spec | Names with spaces allowed; a secret’s value in env let through; the Unicode line separator let through |
| Knowledge base | Node.js 21 counted as installable; the script left out of the default targets; Copilot’s timeout limit off by one; the wrong Copilot job name |
| YAML reader | A key written twice accepted; .5 read as text; the \N escape giving the wrong character; |+ dropping trailing blank lines |
| JSON reader | Trailing commas in objects accepted everywhere; comments accepted everywhere |
| Targets | No error trap in the script; pull requests not running the Copilot setup; Cursor’s build context wrong; the Node.js feature ignoring the version; a space in #cloud-config |
| Quoting | Values starting with a digit written without quotes; $ left unquoted in the shell |
| check | A timeout of exactly 59 flagged; Cursor’s trailing commas passed; only the major version compared; 22 and 22.11 counted as different; a file with preconfig’s header trusted without comparing |
| detect | pnpm installs ignoring the lockfile; names ending in TOKEN not treated as secrets; lts/iron mapped to the wrong Node.js |
| verify | A failed ready check counted as a failed setup; the test runner’s error lines missed in the summary |
| Diff and command line | The hunk header swapping old and new; check exiting with 1 instead of 4 on a broken spec |
Defects Found and Fixed
Testing found real defects, all fixed in the Alpha:
- A crash in check. A Copilot workflow whose job has no steps, and a cloud-init file with no files to write, made check crash. Unit tests found the first and fuzzing guards against both.
- Values read back as numbers or dates. Other YAML readers read some unquoted values, such as
1_000,.5or2026-09-30, as numbers or dates. The differential test found them, and fuzzing found one more,.0; now only values that start with a letter, an underscore, a slash or a dot before a letter go without quotes. - The browser build crashed on start. TinyGo’s default stack for WebAssembly is too small for the engine’s readers at their deepest nesting. The comparison harness found it; the build now uses a 512 KB stack, and the deepest inputs the readers accept are part of the test corpus.
- Findings pointed at the wrong place. A version read from the setup script inside cloud-init.yaml was reported at the script’s own line, and one read through Cursor’s Dockerfile or the dev container’s compose file was reported against the wrong file. The demo’s recordings showed it.
- An exit code misread. verify took any exit code of 125 to 127 as “docker couldn’t start the machine”, even when the setup script had started and then failed. A test with a stand-in for Docker now covers it.
- An unused variable. The setup script for a spec without services kept a variable shellcheck flagged. The platform tools found it.
- Control characters. A control character other than a tab, in an environment value, a command or the PostgreSQL password, could reach the generated YAML and shell. The spec now refuses them. The review before release found the password case.
What the Tests Do Not Cover Yet
- The platforms themselves. No Copilot, Cursor or Codespaces session has run the generated files. They were checked against each platform’s schema and tools, and the setup script ran on a clean machine.
- The Copilot and dev container install paths. verify runs the setup script, which cloud-init, the Cursor Dockerfile and agents that take a script also run. The Copilot workflow installs through GitHub’s setup actions and service containers, and the dev container through features and a compose file. Those passed their schemas and tools, but haven’t run.
- sudo and systemd. The script has run as root in containers without an init system. Runs with sudo, and on full machines with systemd, are still to come.
- Every install path. The test machine could reach Ubuntu’s archive and PyPI but not NodeSource, the PostgreSQL project’s archive, Redis’s packages or Go’s downloads. So Node.js, Go, PostgreSQL other than 16, Redis 8 and Python installed with uv are generated and checked, but haven’t run.
- Real repositories. detect and check ran on the samples and on synthetic cases, not yet on a large set of real projects.
- Other systems. verify has run on Linux only. The binaries for macOS, Windows and Arm Linux compile but haven’t run.
- cloud-init on a real server. The file passed cloud-init’s own schema check; no virtual machine booted with it yet.
Speed and Size
| Measure | Result |
|---|---|
| build, orders-api: read the spec and generate seven files, in memory | About 0.2 ms |
| check, orders-api’s seven files and spec | About 0.4 ms |
| detect, orders-api | About 0.05 ms |
| verify, orders-api, clean machine to READY | 49.6 to 73.0 s |
| The binary: Linux x86-64 / Arm, macOS x86-64 / Arm, Windows x86-64 | 3.3 / 3.1 / 3.3 / 3.1 / 3.4 MB |
| The browser build with TinyGo: size, compressed, start | 1.0 MB, 373 KB, 17 ms |
| The browser build, timed in Node.js 22: build, check, detect | 1.4 ms, 2.3 ms, 0.8 ms |
The engine’s time is too small to matter next to an agent session. What costs time is installing, and that is what verify measures.
Features and Limits
| Feature | Alpha | Next |
|---|---|---|
| Runtimes | Node.js, Python, Go | Java, Ruby, Rust, PHP, .NET |
| Services | PostgreSQL, Redis | MySQL, MongoDB and others |
| Base systems | Ubuntu 24.04 | More bases, Windows runners for Copilot |
| Targets | Dev container, Copilot, Cursor, cloud-init, setup script | More native targets as agents open repository files for setup |
| Proof | verify with Docker on Linux | The platforms themselves; hosted checks on every pull request |
| Secrets | By name, with notes on where to set them | Checks that each platform has them set |
| Knowledge | One dated file, September 29, 2026 | A regular check against each platform’s documents and schemas |
| Browser | build, check and detect | The same |
The Demo
The live demo plays six steps: detect drafts the orders-api spec, build writes every platform’s file, check finds 15 errors and 2 warnings in hand-written setup files, verify proves the setup on a clean machine, verify catches a missing service, and a one-line change to PostgreSQL 17 reaches every file that names it: check lists them, and build rewrites five. The terminal lines are what the Alpha printed; the two verify runs were recorded on a clean container on September 29, 2026 and play five times faster. Under the replay, the engine runs in your browser: you can edit a spec and see every platform’s file, or check a setup file of your own.
Where It Stands
Maturity by Part
| Part | Maturity | What is missing |
|---|---|---|
| Spec and readers | Solid | More runtimes and services; a published schema for editors |
| Targets | Working, validated structurally | Runs on the platforms themselves |
| check | Working | Real repositories at scale; more platforms’ rules |
| detect | Working on samples | Real repositories at scale |
| verify | Working with Docker on Linux | Other systems; hosted runs; caching |
| Knowledge base | Complete for five targets | A routine to keep it current |
| Browser build | Working | Nothing for its role in the demo |
Readiness Level
On the European Commission’s technology readiness scale, which runs from TRL 1 to TRL 9, the Alpha sits at TRL 4, “technology validated in lab”. The engine works and has been tested in a lab: one machine, sample repositories, containers standing in for the platforms. The Beta aims at TRL 5, “technology validated in relevant environment”: real repositories on the agent platforms themselves.
How Far From a First Release
An estimate, and only an estimate: the Alpha is perhaps a third of the way to a first production release. The hard parts of the design have working answers, and the engine is small and well tested. What remains is breadth and proof: running on each platform, more runtimes and services, real repositories, a routine for keeping up with the platforms, and pilots with teams. The Beta should take about 12 weeks with two people, and a first release about 4 to 6 months after that.
Against the Alternatives
| Preconfiguration Alpha | Devbox | agnostic-ai | devcontainer.json alone | |
|---|---|---|---|---|
| What it is | One spec compiled into each agent platform’s setup files, checked and verified | Isolated development shells from Nix packages | One source for AI tools’ rules, skills, agents, hooks and MCP settings | The open standard for container development setups |
| What it writes | Dev container, Copilot workflow, Cursor environment, cloud-init, setup script | A devcontainer.json and Dockerfile, a Dockerfile, direnv and readme files | The native files of 25 targets, the coding tools it supports; environment files too: Cursor’s cloud agent environment.json since early September 2026, Claude Code’s and Codex’s since late September | Itself |
| Where tools come from | Each platform’s usual way: Ubuntu packages, setup actions, dev container features | Nix, inside the environment | The platforms’ own settings | Images and features |
| Checks existing files | Yes: formats, cross-checks, drift | No | No | The CLI reads the file |
| Proves the setup | A ready check on a clean machine | Not documented | Not documented | No ready check of its own |
| License | Not chosen | Apache 2.0 | MIT | Open specification |
What the table shows: Devbox is mature and does more for a developer’s own machine, but it brings Nix into every environment and writes no Copilot or Cursor setup files. agnostic-ai covers far more agents for their instructions and has written environment files for about a month, Cursor’s among them, which makes it the nearest competitor to watch. A devcontainer.json is the right file for Codespaces and editors, but Copilot’s cloud agent runs its own workflow, apart from the dev container. Preconfiguration’s case rests on owning the machine layer across platforms and proving it on a clean machine. So far that is shown on one Linux machine. Sources: the Devbox README, devbox generate, the agnostic-ai README and its issues on environment files, from early September and late September, and a Microsoft project’s notes on Copilot and dev containers.
Technical Risks the Alpha Revealed
- Formats move. Each platform can change its file at any time, and some changes are silent. The knowledge base puts the facts that change most in one dated place, but keeping it current is a routine the project has to run for as long as it exists.
- Structure isn’t behavior. A file can pass a platform’s schema and still do the wrong thing there. Only runs on the platforms themselves settle that, which is the Beta’s first job.
- Networks differ. On the test machine half the install sources were out of reach, and TLS was inspected. Real companies have mirrors, proxies and blocked sources, so the setup script needs ways to use them.
- Services without systemd. Containers usually have no init system, so the script starts PostgreSQL and Redis directly there and through systemd elsewhere. Every platform has to be tried both ways.
- A ready check is only as good as the tests. verify proves that the ready check passes. A team whose tests don’t need the database would get READY on a machine without one. The spec warns when there is no ready check; the rest is the team’s.
- The spec’s edge. Real projects need things outside it: another language, a private package source, a service in a container. The escape hatches, packages and setup commands, may not be enough, and the spec must grow without becoming a second copy of each platform’s format.
Every figure on this page was measured on the Alpha code on September 29 and 30, 2026 unless it is marked as an estimate. The scripts that reproduce them are kept with the Alpha’s source.