The current architecture is website-centric: one Kite app, one linked repo, explicit sync endpoints, drafts and state baked into our database. This note proposes the opposite center of gravity: the team. Every team gets exactly one sandbox — the team's laptop in our cloud — where all drafts and the codebase live under plain git, and every operation happens on that laptop, nowhere else. The web UI becomes what Conductor is to a fleet of agents: a visualiser of a machine that is already the truth, not a second copy of it.
Three symptoms, one disease. Each new capability in v1 costs a disproportionate amount of plumbing, and the plumbing exists only to keep multiple copies of state agreeing with each other.
Sync, Pull, import, drafts — each shipped as an endpoint + queue + retries + UI state. Adding one user-visible operation costs a week of boilerplate before it delivers any product value.
The database, the app and the repo each hold state, and our sync code arbitrates between them. Drift and consistency bugs are a standing tax that grows with every new surface.
v1 is shaped around a website. Customers now work as a team with agents — many drafts, one codebase, shared context. We keep bending the old shape instead of changing it.
git status took ~10 seconds. One command, one repo, no real load. A network filesystem under every team's working set doesn't just make v1 slow — EFS will take us down. The laptop model puts each team's repo on the laptop's own local disk, where git is designed to run: milliseconds, not tens of seconds.One reason, three faces: complexity. We built boilerplate to control operations we can now simply ask an LLM to perform — and the LLM is easier to steer than our own orchestration code is to maintain.
Before, the unit of everything was a website. Now the unit is a team doing work — many drafts, one codebase, shared context. The architecture should be shaped like the new unit, not the old one.
Every operation we hard-coded (sync, pull, import, replace) is a workflow the agent can run itself with a prompt and a shell. Prompting an LLM is cheaper and more adaptable than maintaining bespoke endpoints.
Today state lives in the database and in the repo and in the app — kept consistent by sync code. One laptop with git on it makes the filesystem the only truth; consistency stops being our job.
The mental model is Conductor: agents work on real machines; the UI is a window onto them. Here the machine is the team's laptop — one sandbox per team — and Kite's web app is the window. Reads are views. Writes are prompts. Every operation happens on the laptop — no ceremony calls routed around it, no state mirrored out of it.
Only routing & identity: team → laptop, members, billing. No drafts, no code, no site state baked in. If the row and the laptop disagree, the laptop is right.
The laptop's repo has customer GitHub as an ordinary git remote. Push/pull is the agent running git push / git pull — not a product feature with its own endpoints.
Four paths cover the whole product, and all four end on the team's laptop. Reads translate a URL into a git command on the laptop and stream the answer back untouched. The preview is a reverse-proxy to a dev server already running there. Changes and sync are prompts the agent executes with a shell. The database appears in none of them.
The same architecture as a live stack — drag it to rotate, scroll or pinch to zoom, double-click to reset. The panel on the right walks one concrete request through the layers, in sync with the falling packet: the browser asks for the drafts list, the UI translates it to a git command, the team's laptop executes it on local disk — and the response climbs back up the other side, untouched. The database isn't a layer in the stack; it stands beside it, holding pointers.
A team's laptop — one dedicated sandbox — holds the codebase and every draft, versioned by plain git on local disk. A draft is not a database row; it's a branch (or worktree) in the team's repo. Creating, comparing, merging and discarding drafts are all operations git already does perfectly — we stop re-implementing them.
team/ ├── repo/ # the codebase · git │ ├── main # the live site │ ├── draft/hero-copy │ └── draft/pricing-page └── (agent + shell + toolchain)The web app reads the team's laptop and renders it, the way Conductor renders a workspace. Draft list, file contents, diff views, history — all derived live from git and the filesystem, never cached into our database as a second copy. The database keeps pointers (team → laptop) and identity, and that's all.
This is also the discipline on the write path: no unnecessary operation goes through extra layers. The UI doesn't proxy work through a backend that mirrors state — reads are direct views; every real operation (agent runs, git, builds) executes on the laptop.
Operations we shipped as product machinery become prompts to an agent that has a shell. Git operations happen on the laptop: "sync to GitHub" is the agent running git push; "pull latest" is git pull; "import that repo" is git clone plus a stack check the agent performs by reading the project. The product defines intent and guardrails; the LLM executes.
Concretely, against the shipped v1 model:
This is not free. The trade-offs, stated plainly so the decision is made with open eyes:
git status (§01); add ephemeral caches as views (never truth) and emit events for analytics.Two of the cons above are named but not mechanised: idle laptops cost compute (§08) and a dead laptop is a team outage (§08 → §10). E2B's filesystem-only snapshots give the mechanism — and they fit this model almost by definition.
A sandbox can pause two ways. A full snapshot also freezes RAM and running processes so it resumes instantly. A filesystem-only snapshot (pause({ keepMemory: false })) keeps only the disk: the box reboots from disk on resume — files survive, processes don't. Because P1 already declares the filesystem the only truth, throwing RAM away costs us nothing: the dev server, agent runtime and shell are all reconstructible by rebooting and re-running. The mode whose only downside is "processes die" is free here — and it's cheaper to store and quicker to pause than a full memory snapshot.
The lifecycle, end to end:
idle > timeout → onTimeout: pause(keepMemory:false) # compute billing stops; disk persists first request → DB pointer team→laptop → Sandbox.connect(id) → reboot from disk → re-start git/agent/dev-server → serve recovery → replacement laptop boots the persisted disk; git remote is the real backstopSet lifecycle: { onTimeout: { action: 'pause', keepMemory: false } }. An idle team's laptop pauses to disk after the timeout and stops billing compute; the disk is kept indefinitely. The cost model collapses from always-on compute per team to idle disk + a cold-start budget.
Resume is a reboot, not an instant restore, so the first request after idle pays boot + service-start on top of the exec. Mitigation: pre-warm on intent — connect() the laptop when the user opens the app, before they ask for the drafts list, so the reboot overlaps their attention. Boot-to-first-git status on a team-sized repo is a number the pilot must measure.
Pausing keeps the disk indefinitely, but it's still single-copy on E2B's infra — pause/resume, not a durable, multi-region backup. It cuts how often we cold-rebuild; it does not by itself answer §10. Git remotes remain the real recovery layer, and reboot-from-disk pushes secrets toward inject-at-boot (nothing in RAM survives), which is the cleaner answer to §10 anyway.
Two things this note deliberately does not answer. Both must be resolved before v2 is more than a direction.
If the whole team's state lives on one machine, that machine's death is the whole team's outage. §09 covers the planned pause/wake path; unplanned death and hard recovery are still not drilled.
A filesystem-only snapshot persists the disk (§09), but it's single-copy — so git remotes remain the real backstop if E2B loses the snapshot. Cold-start time, volume locking and partial-write corruption on reboot-from-disk are all still unexamined.
v1 keeps secrets in the vault, in the database. If nothing is baked in the DB and the laptop is the truth, where do env vars and credentials live — on the laptop's disk (then they die and leak with it), injected at boot from a vault we still run, or something else? Reboot-from-disk (§09) tilts this toward inject-at-boot, since nothing in RAM survives a wake anyway.
Also unanswered: keeping secrets out of git in a world where the agent freely commits, and scoping them per-draft vs per-team.
The bet is a single inversion: stop mirroring the world into our database and start pointing the UI at the world. One team, one laptop, git as the state model, prompts as the operation model. Everything we delete — sync endpoints, draft tables, consistency code — is bought with the risks in §08 and the two unknowns in §10. I'm not asking to rewrite the product; I'm asking to run the experiment that tells us whether we can.
Green-light a pilot: one internal team behind a flag. v1 stays untouched and remains the default. Two-week spike first, focused only on the §10 unknowns — recovery and secrets.
A kill-the-laptop drill recovers in minutes with zero data loss; wake-from-snapshot boot-to-first-git status stays inside the read budget (§09); the secrets design passes security review; local-disk reads beat today's EFS numbers for a team-sized repo.
We delete the sync endpoints, draft tables and consistency code — and every future operation ships as a prompt plus a guardrail, not a service. That's the payoff: v2 is mostly deletion.