# June Update: Self-Healing CI Is On by Default

> May in review: self-heal reached production and became the default on every Latchkey runner. What it repairs, what it never touches, how to turn it off, where the platform is headed, and what is coming next.

Source: https://latchkey.dev/blog/self-healing-ci-on-by-default  
Kaveh Alemi  
Published 2026-06-01

**TL;DR** Self-healing is on by default on every Latchkey runner. It repairs environment failures and re-runs the step, sends unfamiliar failures to a Claude agent, never edits your code, and proposes permanent fixes as pull requests you review. It is one toggle to turn off.

## Shipped in May

- **Self-healing CI.** Failed steps on Latchkey runners are diagnosed on the runner, and environment problems are repaired and re-run while real failures stay red.
- **On by default.** Every organization gets self-heal automatically, with a single toggle in Settings to turn it off.
- **Claude agent for unfamiliar failures.** Failures that do not match a known fix get investigated by an agent that only repairs the environment when it is confident.
- **Heal reports.** A Self-Healing dashboard with trends, categories and a plain-language report for every heal, plus a heal indicator on workflow runs.
- **Heal PRs.** When a fix should be permanent, you get a pull request that changes CI or config files only, for you to review and merge.
- **Migrate runners.** Pick repositories and get one pull request each that moves supported jobs onto Latchkey runners.
- **Workspace controls.** You can now delete a workspace, and Send Feedback in the sidebar reaches us directly.

This update covers the biggest change to the platform so far: in May, self-healing went into production on May 12, and on May 20 it became the default on every Latchkey runner. It explains what self-heal repairs, what it never touches and how to turn it off, then where we think CI is going, everything else that shipped in May, and what we are working on next.

![Latchkey Ledger No. 06: Self-healing CI is on by default](/blog/images/ledger-2026-06-cover.png)

## Platform core: self-heal is on, and off is one click

If your organization runs jobs on Latchkey runners, self-healing is on. You do not add a step, install an action or change a workflow. New organizations start with it enabled, and existing ones were switched on in May unless they had explicitly opted out.

Turning it off is one toggle. Open **Settings**, go to the new **Self-Healing** tab, and switch off **Enable Self-Healing**. Owners and admins can change it, and it applies to every runner in the organization. With self-heal off, a failed step fails exactly as it would on any other runner, and we do not analyse or store anything about the failure.

![The Enable Self-Healing toggle in Settings, showing self-healing enabled for the organization](/blog/images/ledger-2026-06-self-heal-toggle.png)
*The toggle lives in the Self-Healing tab under Settings.*

Why default-on? A safety net you have to find and switch on protects nobody on the first day, and the first day is exactly when a new runner meets a workflow written for a different machine. The flip side is that a default-on system has to be conservative enough that nobody regrets it. Every part of self-heal follows three rules:

1. **Repair the environment, never the code.** A package registry returning errors, a full disk, a build running out of memory, a tool the runner image lacks: none of those is a defect in your repository. The right response is to fix the machine and run the step again. A compile error, a type error or a failing assertion is your build telling the truth, and we leave it alone.
2. **Never hide a failure.** A heal that does not work leaves the original failure standing. Nothing is silenced, no test is re-run until it happens to pass, and every heal is recorded with what was done.
3. **When unsure, do nothing.** A tool that guesses is worse than no tool, because then you can no longer trust either the green or the red.

In practice, the failures self-heal repairs fall into a few families you will recognise: **network** (registry timeouts, rate limits, DNS hiccups, flaky Docker pulls and git clones), **missing tools** (a command your workflow expects that the image does not ship), **dependency installs** (transient package manager failures and install-mode mismatches) and **resources** (a full disk, or a build that ran out of memory). The failures it never touches are compile and type errors, failing tests, lint and formatting failures, and application errors from your own code. Those pass straight through, and the step stays red.

## Platform core: how a failed step gets handled

When a step on a Latchkey runner fails, self-heal looks at it right there on the runner, while the machine that failed still exists. If the step passed, nothing happens at all.

![How self-heal handles a failed step: a known fix first, then a Claude agent for unfamiliar failures, ending in healed or stays red](/blog/images/ledger-2026-06-heal-flow.png)

**Known fixes first.** Most environment failures are ones we have seen many times: the same registry timeout, the same out-of-memory message, the same missing tool. For those, self-heal applies a fix we already trust and runs the step again. It is just as good at recognising the opposite case: when the log is clearly a compiler, a test runner or a linter reporting a real problem, it stands down immediately.

**A Claude agent for the unfamiliar.** Some failures do not look like anything we have catalogued: a tool missing inside a Makefile rather than at the shell, an unusual combination of errors, a message from a less common package manager. Those go to a Claude agent running on the same runner. It reads the logs, works out whether the environment is at fault, and repairs it only if it is confident. If it is not, it leaves the step red and says why. The agent can only take a small set of environment actions; it cannot edit your code, and it is held to the same three rules as everything else.

Either way, a heal ends in one of two places: the environment was repaired and the re-run passed, or the step stays red with its original error. A heal whose re-run still fails is recorded as failed, not quietly counted as a success.

**Heal reports.** The runners page has a **Self-Healing** section with attempts, heals and success rate, a trend over time, a breakdown by kind of failure, and a table of recent heals. Healed workflow runs carry an indicator in the runs list, so you can tell at a glance which green builds needed help. Clicking a heal opens its report: for a known fix, a plain-language account such as "the npm registry timed out; retried with backoff"; for an agent heal, how it reasoned about the failure, what it checked, what it concluded and what it did. A heal you cannot inspect is a heal you have to take on faith, and CI should never ask for faith.

## Platform core: heal PRs, when a fix should be permanent

A heal fixes this run. Some failures will happen on every run until the workflow changes: a tool the runner image does not include, a job timeout that is simply too low, a Node version your `package.json` never pinned. Healing those forever would hide the real fix, so when the agent heals something that ought to be permanent, it proposes a pull request.

Take a docs job that calls `jq` from inside a Makefile. The runner image does not have `jq`, so the step fails. Self-heal installs it, re-runs the step and the job passes. Then a pull request arrives that adds an "Install jq" step to that workflow, with a description of what failed, why, and what the change does. If you merge it, future runs no longer need a heal; if you close it, nothing changes.

Heal PRs are deliberately narrow:

- **CI and config files only.** Workflow files and a small set of configuration such as the engines field in `package.json`. Never source code, secrets or anything else.
- **Only after a heal worked.** The fix was applied on a real run and the step then passed.
- **One at a time.** If the same fix is already open for a repository, you do not get a second copy.
- **No forks.** Runs triggered from forks never produce heal PRs.
- **You merge.** Nothing is committed to your default branch without you.

Temporary repairs happen on a machine that is about to be thrown away, and anything permanent arrives as a change you review.

## Moving to Latchkey in one PR

Self-heal only helps jobs that run on Latchkey, so we made the switch easier. The runners page has a new **Migrate runners** button. Pick from your monitored repositories and we open one pull request per repository that swaps each supported `runs-on:` label for a Latchkey runner.

![The Migrate runners modal: pick monitored repos, and Latchkey opens one PR per repo swapping supported runs-on labels](/blog/images/ledger-2026-06-migrate-modal.png)
*Pick repositories, get one migration PR each. Anything that cannot be mapped safely is left untouched.*

GitHub's standard `ubuntu-latest` maps to `runs-on: latchkey-small`, which is 2 vCPU and 8 GB at $0.0025 a minute, against GitHub's $0.006 per minute list price for its standard Linux runner. Larger and self-hosted labels map to the smallest Latchkey size that covers their CPU and memory. Anything we cannot map with confidence is left as it was: expressions, matrix values, Windows and macOS jobs. Because it is a pull request, you see every changed line before anything moves, and rolling back is reverting one commit.

On May 21 we moved Latchkey's own CI onto Latchkey the same way, through a migration pull request we reviewed and merged. If a heal ever surprises us, we will be the first to know.

## Platform vision: the third rung

In February we described a trust ladder for automation in CI: observe, recommend, act in a sandbox, act with a pull request. We shipped the PR rung first because nothing happens there until a person says yes. Acting inside a running job, before anyone has looked, was the rung that had to be earned. As of May, it is live and on by default.

The bet underneath is simple. More of the code reaching your pipeline is written by agents, and it arrives faster than anyone can babysit red builds. In that world a CI failure is really one of two different things. Either the machine let you down, and the fix is mechanical and should happen without a human in the loop. Or the code is wrong, and the fix is judgment that belongs to whoever owns the code. Most CI treats both the same way: it goes red and waits for someone to read a log.

We think a runner in the agent era has to separate those two cleanly and act only on the first. That is why we moved from analysing CI to running it: the runner is the only place where the environment can be repaired while the job is still alive, on a machine that is thrown away afterwards so a repair never leaks into the next job.

The second half is the part we have not built. A code failure should stay red, and it should also reach whoever can fix it, with everything the runner saw, instead of a truncated log. The owner of the code, or the agent they delegate to, stays in control. Our job is to make that handoff complete.

## Web Summit Vancouver

We had a booth at Web Summit Vancouver from May 11 to 14, and self-heal went live in the middle of it. We showed managed runners and live demo workflows that broke on purpose so people could watch self-heal repair the environment, alongside one that failed on a real test and stayed red. The second demo got as many questions as the first. Thank you to everyone who stopped by.

## Coming next

Self-heal as it stands answers one question: is this the environment's fault? When the answer is no, the step stays red and you are back to reading the log, which is correct but not very helpful. Most of what we are working on this month is about that red step.

**Handing code failures to your coding agent.** We want the failures self-heal will not touch to reach the coding agent you already use, over the Model Context Protocol, so it starts from a diagnosis and the full output the runner saw instead of whatever log you paste in. The rule does not move: we never change your code. Your agent works in your repository, and anything it changes arrives as a pull request you review.

**An explanation for every failure self-heal leaves red.** Today a step self-heal declines to repair can end without much said. We want every unhealed failure to come with a written account of what went wrong and why it was left alone, which is also what makes a handoff worth receiving.

**Faster job pickup.** We are working on getting jobs onto a machine sooner, on every plan.

**More environment failures recognised.** The families self-heal can repair will keep growing, with the same line between environment and code.

The next update will say what actually shipped.

Previous issue: [May Update: Latchkey Runners Are Live](/blog/managed-runners-launch) · Next issue: [July Update: Your Coding Agent Can Fix What Self-Healing Won't](/blog/self-healing-ci-and-the-mcp-handoff)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
