Browse docsDevelopers
Give your boxes their tools
Write the fixed-labs.rift expression into your repository from inside a box, open the pull request, and claim the box that has your toolchain in it.
In Getting started with Rift your agent claimed a box built from your repository — the base system, with your checkout in it. This time you'll give that box your project's tools, and end with a fresh box where they're simply there.
The tools are declared in one place: a flake output in your repository named fixed-labs.rift. It says which packages go on the path, which environment variables every session gets, and which directories persist between calls. You won't write it from scratch: your agent reads Rift's own guide to the expression, writes it from a box, and opens the pull request — because a box never changes after it is built, and the way to change the next one is to change the repository.
Before you start you'll need everything from the first tutorial — Rift connected to your agent, a branch watched, a box you can claim — and a repository you can open a pull request against. About twenty minutes.
1. Claim a box, and hand the agent the guide
Open a task and claim a box on the branch you watch, exactly as before. Then tell the agent what you want: "add a Rift expression to this repository for its toolchain". Rift's server carries a resource, rift://nix-guide, that the agent is told to read before it touches the expression — it has the contract, a complete example, and the lifecycle from an edit to a merged pull request. A good agent reads it unprompted; it does no harm to ask.
2. What the agent writes
The expression is a flake output fixed-labs.rift.<system> in your repository's own flake.nix, with no inputs of Rift's. It's a plain attribute set with three things in it:
{
outputs = { self, nixpkgs, ... }: {
fixed-labs.rift.x86_64-linux =
let pkgs = nixpkgs.legacyPackages.x86_64-linux; in {
packages = with pkgs; [ nodejs_22 pnpm ripgrep ];
env = { NODE_ENV = "development"; };
};
};
}packagesgo on the login user's path, ahead of the base system's.envis the environment of every session.- The home persists for the life of the VM, so every tool's cache in it does: there is nothing to declare.
Nothing else is accepted — an unknown attribute fails the build with its name, so the expression can't quietly mean nothing. If your repository has no flake.nix yet, the agent creates one around exactly this.
Review it like a PR. The package list is the thing to read: does it match what your project needs to build and run? A missing tool is one more entry later, but this is the moment to catch the obvious gaps.
3. Check it, on the box
Evaluating the expression is safe on the box — it runs in Nix's sandbox and touches nothing — so the agent checks the shape before it pushes:
cd /home/dev/repo
git add flake.nix
nix eval .#fixed-labs.rift.x86_64-linuxSuccess prints the attribute set back. An error names the problem: most often a package attribute that doesn't exist, or an attribute the contract doesn't know. Fix and re-run until it evaluates.
If nix eval claims there is no flake.nix, it hasn't been git added yet — Nix ignores untracked files entirely. Staged is enough.
4. Push it, and open the pull request
git on the box is ordinary git, and everything local works: the branch, the commit. What needs GitHub is a verb — push, pr-create — that runs outside the jail as you, with your GitHub token, so the commit is yours and the pull request is yours. verbs lists them; each answers --help.
git checkout -b rift-expression
git commit -am "Add the Rift expression"
push --branch rift-expression
pr-create --title "Add the Rift expression" --body-file pr.mdA box builds and runs without your GitHub account connected; a push is the first thing that needs it. If push is refused because you haven't connected GitHub, the agent calls rift_github_login and shows you a URL and a code. Open the URL, enter the code, and tell the agent — it calls the tool again to check, then runs the verb again. The credential is fetched for each run, so the same box pushes the moment you're connected.
5. Merge, and let the pool rewarm
Merge the pull request. The push to your watched branch moves its head, and Rift's webhook hears it: the warm box at the old head is drained, and a new one warms at the new head — cloning, building the system your expression describes, and parking. rift_whoami shows the head the pool is at; the first build with real packages in it takes a few minutes.
6. Claim the box that has your tools
The box you've been working in is still the old one, and it won't change. Close the task, or destroy the box, and claim a fresh one:
rift_vm_destroy <task> <old box>
rift_vm_new <task> github:<you>/<repo> main
rift_bash <task> <box> "node --version && pnpm --version"That's the full loop: the repository declares its environment, Rift builds it at every push to the watched branch, and every box your agent claims boots ready to work.
🎉 Your boxes have their tools. Where to go next:
- Inside a box — the jail, the verbs, what persists between calls, and where secrets go.
- Secrets — the credentials your verbs need, given to each run outside the jail and never to the box.
- Warm pools — what a watched ref keeps warm, and when it rewarms.