Migration numbers, claimed.
Two branches added 0011. The second was refused before it ran:
$ karts up # feature/discounts karts: migration 0011 is already taken by branch feature/refunds; renumber to 0012 or later
Early access, by invitation
Your agent runs karts up. The branch boots in its own micro-VM with a migrated, seeded copy of your database. Agents on different branches never share a database.
Works with
Today
0011. You find out after the merge.DROP COLUMN hits the shared database before anyone reads it.With Karts
0011 is refused, with the next free number.--allow-destructive.karts upClaims the branch's migration numbers.
Copies main's database. Applies the branch's migrations.
Boots your app in a micro-VM. Prints the URL.
karts downDestroys the VM and its database.
karts up does. Real output, not mockups.Two branches added 0011. The second was refused before it ran:
$ karts up # feature/discounts karts: migration 0011 is already taken by branch feature/refunds; renumber to 0012 or later
Refused until you pass --allow-destructive:
$ karts up # feature/cleanup karts: destructive migration refused … ALTER TABLE customers DROP COLUMN notes — drops column customers.notes and every value in it
Main's 10 migrations and seed built a template once, in 26.4 s. The next branch got its own copy, migrated, in 1.26 s.
Each branch is a Firecracker micro-VM. It restores from a snapshot in 10.7 ms (median of 100).
What is isolated todayTell it: read https://drivekarts.si/onboard.md. It writes karts.yml, runs karts up and fixes what fails.
$ claude mcp add karts -- karts mcp
List the outside services your app uses. Each branch gets stand-ins that answer like the real ones, in the cloud or on your Mac. They never call the real service, and they keep a record of what your app sent.
Mail sent through SendGrid, Resend, Postmark, Mailgun or the Gmail API lands in the branch's test inbox.
“Sign in with Google” or GitHub shows a test sign-in page with test users. Agents can sign in without a browser.
A Stripe stand-in: checkout, test cards (declines too), subscriptions and refunds. Your app gets signed webhooks.
Give it canned answers. A call nothing answers is caught, and the reply has the exact lines to add.
# karts.yml mail: true # the test inbox fakes: [sendgrid, google-login, stripe]
$ karts fakes calls # what your app sent, secrets removed
Some sign-in libraries need one line changed. How to set it up, and the limits
karts up. What else it does today.karts fork copies an app while it runs, with its memory and its data. The app pauses for about 0.1 s (66 ms to 134 ms, median 82 ms). Then each copy goes its own way.
$ karts fork
Set a key once. Each branch can have its own value. Your app gets it, the logs show ‹secret›, and it is stored encrypted.
$ karts secret set STRIPE_KEY
Runs on your machine. It reads your Postgres database without changing it, and swaps emails, names and other personal data for fakes. Links between tables still work. Only the masked copy is uploaded, and it is stored encrypted.
$ karts db snapshot
Not only Postgres. Each branch gets its own MySQL 8.4 or SQLite database. A MySQL branch was up in 4.8 s, a SQLite branch in 2.05 s.
database: mysql # karts.yml
Point Karts at your built folder and it serves it, with single-page app routing if you ask. You write no server.
kind: static # karts.yml
When Karts fails, your agent can send us a short report. It shows you the report and asks first. Keys and passwords it can spot are removed before it is stored.
$ karts report
The same karts.yml, with no account and nothing uploaded. Each branch gets its own database and a URL that stays the same. A repeat karts up --local keeps the rows you made and runs only new migrations. A front end in one repository finds its API in another. Needs Docker Desktop.
$ karts up --local http://<branch>.<project>.localhost:7400
2.2 s
from karts up to a public URL
Tiny Shop, one new migration, through the public API: 2.23 s on 28 Sep 2026, 2.59 s on 29 Sep 2026. First build, template included: 8.7 s to 13.7 s. Bigger installs take minutes.
How we measuredBring a web app that uses Postgres, MySQL or SQLite.
Free during early access
karts CLI and karts mcpkarts exec in every environmentkarts fork, secrets and masked copies of real datakarts up --local on your own MacMore in the docs FAQ.
One Firecracker micro-VM: 2 vCPU and 2 GB of memory unless you ask for up to 4 and 8 GB. It holds your branch's files, your app (up to eight processes, with Redis, a mail catcher and an S3 bucket if you ask) and its own database: Postgres, MySQL or SQLite. The build can reach the npm, PyPI, Go, RubyGems and Packagist registries, GitHub and a few download hosts. Your running app reaches nothing outside the VM unless your karts.yml turns on internet access. The VM in detail.
Not raw data. Environment URLs are public, with no sign-in, so anyone with the link can open the app. Use seed data, or a masked copy: karts db snapshot swaps personal data for fakes on your machine, and only the masked file is uploaded. Keep keys out of the repository with karts secret set. What to put in it.
Yes. karts up uploads the working tree, never .git/. What we store and how it is isolated.
No. The destructive check is rule-based: it catches dropped tables and columns and common data-wiping statements, not every one. Keep reviewing migrations.
Web apps on Postgres, MySQL 8.4 or SQLite, in Node, Python, Go, Ruby or PHP, with numbered SQL migrations or your own tool (Prisma, Knex, Django, Alembic, Rails). On 29–30 Sep 2026, 19 of 20 open-source apps ran on Karts: 18 with only a karts.yml, and one with one more step. What stops the last one.
On your Mac, yes: karts up --local runs the same karts.yml with no account and no upload. It needs Docker Desktop. On your own servers, not yet as a product: talk to us.
Early access is by invitation. New teams get environments once preview URLs move to their own domain.