Beta 2: a fleet that heals itself, warm pools per image, and videos from your repo
Friday, October 16, 2026 · Alex Rabin
kinhin watches your CI queue and, for each queued job, starts a fresh VM or container on your Apple Silicon Mac, registers a one-job runner, lets it run, then deletes it. Nothing idles and nothing is left over. It is free, open source (Apache-2.0), and sends no telemetry.
Beta 2 is the release where the fleet looks after itself a little, the warm pools get finer-grained, and your repository can make its own launch videos. This post covers what is new, what has been run, and what has not.
What is new
A fleet that heals itself
Fleets break in dull ways: a warm VM gets deleted outside kinhin, a toolchain cache fills the disk, an account gets detached, or the Apple container system stops. The healing agent now fixes four of those on its own: a warm VM deleted out of band, a toolchain cache filling the disk, a detached account, and a stopped Apple container system.
Anything destructive waits for you. Pruning images or reinstalling a runtime goes into a journal:
kinhin healshows the journal.kinhin heal approve IDcarries out a fix you have reviewed.kinhin heal dismiss IDcloses an entry.- The app's Diagnostics sheet has a Healing card, and a notification fires when a fix succeeds.
- It is configured under
healing:. docs/healing.md describes each rule.
On macOS 26 with Apple Intelligence turned on, the on-device model can choose from the allowed fixes for a problem that no rule covers. It only chooses among fixes that are already allowed.
Warm pools per image
A warm pool keeps booted, unregistered VMs ready, so the next job skips the clone and the boot. Until now the pool covered only the top-level image:. Beta 2 adds warm_pool on any images: entry, so a job routed to a named image such as xcode gets a ready VM too. The top-level warm_pool still covers image:, and the two share max_runners.
Each image in the app's More images card has a stepper for its pool, and the Capacity view shows the base image's. Changes are saved once the stepper settles.
A warm VM costs RAM and disk, and it holds a max_runners slot while it waits. Turning a pool off, or removing an images: entry, recycles its VMs straight away.
Videos from your repository
kinhin video makes a narrated video of your own product from .kinhin/videos/*.yml. You do not copy the video suite into your repository: the build runs a published container image (Apple container or Docker) against your files.
kinhin video init,listandbuildcover the basics. Each build lands in its own folder under.kinhin/videos/out/.- Music, captions, themes and formats are config.
kinhin video theme newstarts a theme that extends a built-in one. kinhin video music searchfinds CC0 and public-domain tracks.--license cc-byalso offers CC BY tracks and writes the credit line.--on-fleetbuilds on a runner through a generated GitHub workflow.- The app's Fleet tab has a Make a Video… sheet that uses the same code, with live output.
- A
devicescene can show store screenshots as a cross-fading slideshow.
Recording a clip of your app
kinhin video record <app or title> records one window of an app as a clip, with the mouse pointer left out. --list-windows shows what can be recorded, and --window ID picks one. The first run needs Screen Recording permission for your terminal, which you grant once in System Settings.
Mobile releases and store screenshots
kinhin mobile init scaffolds release setup for iOS, Android, Flutter, React Native, native projects, Capacitor and Ionic, Kotlin Multiplatform and .NET MAUI, with lanes, a pinned Gemfile and a manual mobile-release workflow for kinhin-xcode. Expo gets EAS config. It is opt-in: a project that does not run it sees no change.
A screenshots lane captures iOS UI tests with snapshot and Android instrumented tests with screengrab, with optional device frames and upload.
--ci writes a pipeline for GitLab CI, Gitea and Forgejo Actions, Bitbucket Pipelines, Azure Pipelines or Buildkite as well as GitHub Actions. Those files run your mobile release on that system. kinhin does not scale runners for Buildkite, Azure Pipelines or Bitbucket Pipelines yet, which is beta-3 work. Treat the generated pipelines as untested on your project until a run of your own has passed.
Fleet safety and fixes
- An unreadable
fleet.json,project-images.jsonor scale-set session file is moved aside to<name>.corrupt-<timestamp>instead of being replaced. kinhin starts empty, and the app andkinhin statusname the kept copy. - "Reset everything" reports what it left behind, and
kinhin resetexits 1 in that case. - A large
images:image is checked against its own size before a Tart clone, not the base VM's. - A warm VM is recycled at once when its pool is turned off, instead of holding a slot for up to an hour.
- Commands that run a child process no longer lose the last lines of stderr under load.
- Video text wraps on whole words and shrinks to fit, so titles and captions stay inside the frame.
- The Capacity card's base-image rows fit their card again.
What changed under the hood
- A repository's config now lives at
.kinhin/config.yml. The older.kinhin.ymlis still read when the new file is absent. - Core toolchains (
node,go,python,ruby,swift) install a pinned default when listed without a version, so a re-bake reproduces the same versions. - The video image is pinned by digest, and Dependabot keeps it current.
What has been run
Here is what this release has been through, in the terms I use everywhere in this post. Run means it was executed for this release. Not yet means it has not been, and I am not claiming it.
- Run: the unit suite (3,377 tests, which need no VMs or network), the ThreadSanitizer run on the branch, the video suite's unit tests (81 of 81), and the release build's own check, which ran before signing.
- Run: the launch video was built from the same suite, with its size, loudness and caption checks passing.
- Run: the six healing scenarios on Gitea over Docker, through the end-to-end suite on 2026-10-14. The Tart warm-VM case has not run.
- Not yet: the end-to-end suite on this release, and its GitHub lane against a throwaway repository. The suite runs only in CI, and the CI runner for it is not registered yet.
- Not yet: upgrading from beta 1 on a Mac with real state.
- Not yet: the in-app updater has not been run against this release.
The beta-1 end-to-end results still stand for the forges as they were, but they have not been repeated on this release.
Try it
The release is published on GitHub. Install it with:
curl -fsSL https://github.com/RabinApps/kinhin/releases/latest/download/install.sh | bashYou need an Apple Silicon Mac on macOS 15 or newer with about 60 GB of free disk, and an access token for your forge. The Quick start goes from install to a running fleet.
Where I need help
I have one Mac and a finite supply of evenings. The most useful things to test are the ones I could not:
- The updater. Install beta 1, let it find this release, and tell me whether it installed the update.
- Upgrading with real state. Your fleet, project images and config, on beta 1, then beta 2. Tell me if anything was lost.
- The healing agent. Run
kinhin healon a real fleet and send me any journal entry that looks wrong. - Warm pools per image. Route a job to an
images:entry withwarm_poolset, and tell me whether the VM was ready. - Videos from your repo. Make one with
kinhin video initandbuild, and send me what you got. - Real projects on the supported forges. Your workflows, not my test jobs: GitHub, Gitea, Forgejo and GitLab CE.
One real job is a valuable report, including when it fails. Open a forge or runtime report and say what you ran and what went wrong. Attach the output of kinhin doctor --bundle after a glance through it, since it is redacted but not perfect.
Thank you
kinhin is free and Apache-2.0. If it saves you CI minutes, you can support it.
Alex
