format

The CodeInstances File Format Is Open JSON With a SHA-256 ID

The file is the product. A tool can be replaced, but a run you kept in a format only one tool reads is a run you’ll lose eventually. So the instance format is open JSON, written down in full in FORMAT.md for anyone who wants to read or write instances with their own tools.

Its name is codeinstances/0, and that string is the first member of every file. A reader that sees a format version it doesn’t know has to refuse the file, and readers ignore members they don’t recognise. A file that holds the same member twice, or a known member spelled in another case, is refused. That’s how the format can grow without breaking files that already exist.

What Is in a File

One run, one JSON object. It holds the command that was run, the result (exit code or the signal that killed it, how long it took, stdout and stderr), every call the program made in the order it arrived, and every clock or random value it asked for.

One run, one JSON file in the codeinstances/0 format. The format member says which version of the format. The id is the SHA-256 of the canonical JSON, so any edit shows. The command says what was run. The result says how it ended and what it printed. The calls hold every HTTP exchange in order, and the values hold clock and random values from the Go hook package.

Each call has a sequence number, the time it happened since the run started, the request (method, URL, headers, body) and either the response or the error the program got when no response came back. Bodies are stored as text when they’re valid UTF-8 and as base64 when they’re not. Headers that belong to one connection are dropped, and the ones that usually carry secrets are replaced with [redacted] by default.

The repository has a real one: a Python one-liner that fetched a small JSON file. It’s short enough to read in a minute, and a test checks it stays valid.

The ID

Every file carries an id: sha256: followed by the SHA-256 of the file’s canonical form. Canonical means the id member removed, every object’s members sorted by name, no whitespace, numbers exactly as written and strings escaped the minimal way. FORMAT.md gives the exact rules.

So reformatting a file, or reordering its members, leaves the id alone. Changing any value, or adding anything, changes it. codeinstances verify recomputes the id and exits 1 if the two don’t match.

That catches accidental edits and careless ones. It doesn’t tell you who recorded the file, because anyone can change one and write a new id. Signed instances are on the plan for a later version, and they’re meant to fit into this format as added members.

Why JSON

Instances are meant to be kept, read, diffed, attached to bug reports and processed by tools that don’t exist yet. JSON is dull, and every language reads it. A 23-call run from the demo comes to about 20 KB, which is small enough not to think about. If a compact binary form is ever needed, it can sit next to this one.

The reference explains how replay uses a file, and FORMAT.md has the same rules for any other tool that wants to replay instances.