MainSDK
Search⌘K
Docs

The repair loop

What mainsdk check --json --agent prints, how a coding agent reads each field, when it must ask a person, and how to use the same output in CI.

Planned for 0.3

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

A coding agent fixes what the check finds, runs the check again, and stops after three unresolved rounds on the same finding. This page shows the output it reads and what each field means. It takes about five minutes.

mainsdk check --json --agent is planned for 0.3 (spec fast-start). MainSDK is pre-release and the command does not run yet.

You need

  • A project with main.yaml (npx mainsdk init).
  • A coding agent that can run a shell command and read JSON.

1. Run the check in agent mode

bash
npx mainsdk check --json --agent

The output is the same document as mainsdk check --json, with the fix and the file on every finding and a hint for how many rounds to try. Exit codes: 0 passed, 1 a gate failed, 2 a usage or configuration error (with a MAIN-CONFIG- code).

jsonc
{ "version": 1, "project": "prj_01JC8Q…", "env": "prod", "passed": false,
  "gates": [{ "id": "secrets", "passed": false, "findings": [
    { "code": "MAIN-SECRET-0002", "severity": "critical", "file": "app/lib/pay.ts", "line": 3,
      "rule": "secrets.no_literal", "fix": "Move the key to secrets and use secret:STRIPE_KEY" } ] }] }

2. Read each field

FieldWhat the agent does with it
passedtrue means stop and report. false means there is at least one finding.
gates[].idThe gate that failed (secrets above). Fix the failed gates in the order printed.
codeThe finding. Run npx mainsdk explain <code> for the full explanation, offline.
severityHow serious it is. Fix every severity; do not skip low ones.
file and lineWhere to change code. Change only what the finding names.
ruleThe rule that fired. Never edit the rule to make the finding go away.
fixWhat to do. Apply it, then re-run.
askperson means stop. See step 4.

The max-iterations hint that --agent adds (its field name and place in the document) is not decided yet: the spec fixes the behaviour, not the field. Until it is fixed, count rounds yourself: stop at three.

3. An example of two rounds

Round 1. The agent runs the check and gets the finding above. It moves the key into main.yaml as secret:STRIPE_KEY and reads it through the interface, then runs the check again.

Round 2. The secret is gone, but a new finding in a different gate appears:

jsonc
{ "version": 1, "project": "prj_01JC8Q…", "env": "prod", "passed": false,
  "gates": [{ "id": "data", "passed": false, "findings": [
    { "code": "MAIN-DATA-0007", "severity": "critical", "file": "app/api/orders/route.ts", "line": 12,
      "rule": "[to be decided]", "fix": "Query with db.orders.for(user)" } ] }] }

The agent changes line 12 to db.orders.for(session.user).list() and runs the check a third time:

jsonc
{ "version": 1, "project": "prj_01JC8Q…", "env": "prod", "passed": true, "gates": [] }

Exit code 0. The agent reports what changed in main.yaml and the result. (The gates list for a passing run is shown empty here; its exact content on a pass is not decided yet.)

4. When the check says ask: person

If the same finding is still unresolved after three runs, the fourth run returns the finding with ask: person and no further fix text (fast-start.AC4). The agent stops editing. It tells the developer which finding is stuck, what it tried in each round, and what it thinks the blocker is.

jsonc
{ "code": "MAIN-DATA-0007", "severity": "critical", "file": "app/api/orders/route.ts", "line": 12,
  "ask": "person" }

The agent does not try a fourth fix, and it does not reach for an exception or raw(). A person decides: change the design, or accept the finding as an exception with an owner and an expiry date.

How the check knows a round is "the same finding" (by code and file, or code, file and line) and where it keeps the count is not decided yet.

5. Explain a code

bash
npx mainsdk explain MAIN-DATA-0007

explain takes a code or a trace id, and --json for machine output. It runs offline. Use it when a fix is not clear enough; do not use it to find a way around a rule.

6. Use it in CI

Run the same command on every pull request. A non-zero exit fails the build.

bash
npx mainsdk check --json --sarif out.sarif

--sarif <file> writes SARIF 2.1.0 so code scanning shows each finding inline at its file and line. --agent is the stable output for repair loops. --fail-on <severity> sets the severity that fails the run; the severity names are not decided yet.

Verify

bash
npx mainsdk check --json --agent

You should see "passed": true and exit code 0.

If it fails

CodeCauseFix
MAIN-CONFIG-… (exit 2)main.yaml or the command is wrongRead the code's fix, then run npx mainsdk explain <code>
MAIN-CHECK-0026An interface still resolves to a local driver in productionSet a real driver in main.env.prod.yaml
ask: personThree unresolved roundsStop and ask the developer

For agents

text
Goal:    Reach "passed": true without changing any rule.
Loop:    run `npx mainsdk check --json --agent`; for each finding open `file` at `line`,
         apply `fix`, run `npx mainsdk explain <code>` if unclear; run the check again.
Stop:    after three unresolved rounds on one finding, or when a finding has
         `ask: "person"`. Tell the developer the code, file, line and what you tried.
Never:   edit `rule`, lower a severity, add an exception, delete a test or use raw().

Next

Open questions

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet