Skip to main content
The environment is your project’s machine recipe: which setup scripts prepare a fresh machine, which commands the agent can run, and how big the VM is. It’s the highest-leverage configuration in Capy, because an agent that can’t run your tests can’t verify its work. On a machine where pnpm test works, the agent proves its changes; on a machine where nothing runs, it guesses and you find out in CI. Spend the twenty minutes. Every thread, task, and rebuilt machine in the project benefits, and a snapshot makes the result nearly free to boot.

Two ways to configure it

Open your project and go to Dev environment to edit machine size, per-repository setup scripts, and snapshots directly. Or ask Capy in any thread (“set up this project’s dev environment”) and it reads your manifests, writes the setup, and can verify it by running the scripts on its own machine. Agent edits and your edits land in the same configuration; every save creates a new version in one shared history. Setup is stored per repository. The shape, if you want to picture it:
Scripts are optional; leave a phase empty when it has no work to do.

The three setup phases

Every timeout is configurable from 60 to 3600 seconds. The selection is per repository: a fresh clone runs initialize then startup; a restored or reused checkout fetches and fast-forwards its branch, runs update_after_checkout only when HEAD actually moved, then runs startup. A failed initialize is retried on the existing checkout until a run succeeds.

initialize

Everything needed to make a clean clone usable: install dependencies, system packages, global tools, generated artifacts. It also runs during snapshot builds, so whatever it produces gets baked into the snapshot. If dependency installation needs a private registry, authenticate explicitly at the top of the script; a package-manager preinstall hook can’t authenticate the fetch that happens before it exists.

update_after_checkout

The repair phase: bring a prepared machine up to date after the checkout moves. Keep it fast and safe to rerun: sync dependencies from the lockfile, regenerate derived code. Don’t duplicate an expensive bootstrap here unless reused machines genuinely need it.

startup

Start the services the agent needs while working: dev servers, local databases. The script itself must exit, so background long-running processes and wait for readiness:
Make it idempotent. startup runs again when a machine wakes from sleep. Processes don’t survive sleep, so this script is what brings your services back, and a script that blindly starts a second server will trip over the first one’s port on reruns.

How scripts execute

Each script runs from its repository’s directory, in bash, under its timeout, as a user with passwordless sudo, with your environment variables loaded. A non-zero exit or a timeout fails the phase. A failed phase doesn’t kill the thread: the machine comes up, the thread gets a workspace warning naming the repository and phase, and the agent continues in a degraded workspace it will usually try to repair by hand. That self-repair costs you time and tokens on every machine; fix the script instead.

Commands

Commands are named, opt-in actions the agent can run while working: test, typecheck, build. They never run automatically; the agent reads them from setup and invokes them when relevant. Keep them executable and specific. Prose guidance like “always lint before committing” belongs in instructions, not here.

What the agent can do itself

Capy reads and replaces the whole setup through its environment tools, which is what makes “ask Capy to update your dev environment” work. Two boundaries hold regardless: the agent sees environment variable names and whether each has a value, never the values, and no tool can set a variable’s value. Values are yours to manage in the app; see secrets.
PR reviews run on their own machine with a fresh checkout pinned to the exact PR head, credentials read-only and pushes disabled. Shared project variables apply there; personal and thread variables never do.

Snapshots

A snapshot is your project’s post-setup filesystem (repositories cloned, dependencies installed, initialize already run) baked into a bootable image. A fresh machine that restores from one skips the clone and setup work entirely and starts where your setup scripts finished. Restoring from a snapshot takes roughly 1–2 seconds. Without one, every fresh machine pays your full setup time: clone plus however long initialize takes. Building a snapshot adds roughly 10–30 seconds on top of your setup scripts’ own runtime, paid once per build instead of once per machine. If your initialize takes five minutes, snapshots are the difference between an agent that starts working immediately and one that spends its first five minutes installing dependencies, on every thread, every task machine, every review. Snapshots never gate a fresh boot. Missing, stale, disabled, or failed, the fallback is always the same: a fresh machine runs your full setup. A snapshot is a cache of your setup, never a second source of truth: your configuration stays in charge, and the snapshot just caches the result of running it.

Turning it on

Enable snapshots in the Snapshots section of your project’s Dev environment page, or ask Capy to do it. Enabling doesn’t start a build by itself; the hourly check picks it up on its next pass. Trigger a build immediately from the same page, or ask Capy to build one now. There’s also a test lane that runs the full build without activating the result, useful for validating setup changes while snapshots stay disabled.

When snapshots rebuild

Every hour, Capy compares the frozen build input (the selected repositories at their current commits, the active setup version, the machine size) against what the current snapshot was built from. Anything moved, it rebuilds; nothing moved, it doesn’t. In practice:
  • New commits on a selected repository’s base branch trigger a rebuild within the hour.
  • Changing setup scripts or machine size triggers a rebuild within the hour.
  • Identical input never rebuilds, so a quiet project builds nothing.
  • A failed build leaves the previous snapshot serving and is retried on the next hourly pass. Machines fall back to full setup only when there’s no current snapshot at all.
A build runs on a dedicated build machine at your configured size, follows your setup exactly, and activates on success. Snapshot build machines aren’t billed to your organization.

Choosing what goes in

A snapshot contains a selected subset of the project’s repositories, not necessarily all of them. Repositories outside the selection stay in the catalog and clone on demand when a thread needs them; they just don’t get the instant-boot treatment. Selection is validated against the machine’s disk budget using each repository’s size from GitHub, and an over-budget selection is refused up front with a per-repo breakdown rather than failing halfway through a build. Each repository row on the Dev environment page carries an include-in-snapshot switch. A newly added project repository isn’t snapshotted until you select it.

Machine sizes and disk tiers

Disk size bakes into the image, so a snapshot serves one disk tier: 64 GB covers Small through Ultra, 128 GB is Hyper, 256 GB is Big Guy. Within a tier, one snapshot serves equal or smaller machines than it was built at; a thread requesting a bigger machine than the snapshot’s baked size falls back to fresh setup rather than silently booting undersized. If your setup size is on a bigger tier, the also snapshot smaller machine sizes option bakes the smaller tiers too, each built at that tier’s largest size.

Secrets in builds

Builds receive shared project variables so initialize can authenticate private registries, and Capy scrubs and verifies every platform-managed secret path before capture; a build that can’t prove the scrub fails. The one hole Capy can’t close is a setup script that writes a secret into the workspace; details in secrets.

When a build fails

Open the build from the Dev environment page’s build history: every build records per-step logs, and each setup phase’s output survives with the failing line intact. Or just ask Capy why the last snapshot build failed; it reads the same build history and logs, and can fix the setup and rebuild in one go. The failure costs you speed, not availability: machines keep booting fresh with full setup until a build succeeds.