Skip to main content
Three ways to use a coding agent on one repository. A devbox you SSH into to work alongside Claude Code or Codex. A GitHub webhook that hands each issue labeled agent to Claude Code in its own sandbox and opens a pull request with the result. And a nightly eval that runs the agent on five small tasks in parallel sandboxes and posts the pass rate and spend.

How it fits together

The coding-agents map holds the snapshot record and a claim per issue in progress. Each secret reaches only the workloads that use it; GITHUB_WEBHOOK_SECRET reaches only the webhook. With no labeled issues and no SSH session, only the map and the devbox disk cost anything, plus one eval a night, and AGENT_MAX_BUDGET_USD caps each run’s model spend at $5.

Run it

1

Download

The CLI installs once with uv tool install lazycloud-client. The commands below download a standalone project and install its dependencies; no repository checkout is needed. The guide then runs from that directory through uv run, which uses the project’s pinned SDK.
2

Configure

Set REPOSITORY in coding_agents/settings.py; SETUP_COMMAND and TEST_COMMAND default to a uv project with pytest. The script asks for an Anthropic API key, a GitHub token with read and write access to contents, issues and pull requests, and a webhook secret such as openssl rand -hex 32.
3

Deploy

The deploy prints the webhook URL. In the repository’s settings, add a webhook with that URL followed by /github, content type application/json, the secret you stored, and Issues events only.
4

Use

Create an agent label, open an issue, and apply the label. A pull request from agent/issue-<number> follows, with the agent’s summary, the test verdict, the turns and the spend.
uv run lazycloud devbox agent-box ssh connects to the devbox; inside, clone the repository, start tmux and run claude or codex. uv run lazycloud run coding_agents.app:nightly_eval runs the eval now instead of waiting for 06:00 UTC.

A devbox with a disk

A devbox is a container you SSH into; the secrets arrive as environment variables, so claude and gh work on the first connection, and the idle window counts from your last SSH connection.
coding_agents/app.py

Sandboxes that reach only the model API

A sandbox runs the agent’s commands; allow_list holds address ranges, DNS included, so the function pins api.anthropic.com in the sandbox’s /etc/hosts, and the agent runs as an unprivileged user that cannot change it. The issue sandbox is the same with image=Image.from_id(snapshot.image_id), declared at run time.
coding_agents/app.py

A filesystem image as the snapshot

A sandbox’s filesystem can become an image, which is how the repository and its dependencies reach offline sandboxes.
coding_agents/snapshot.py

A claim in a map, then spawn

A map entry with a two-hour TTL claims the issue before .spawn(), so a relabel or a redelivery keeps the run already going. The webhook is authorized=False, since GitHub cannot send a LazyCloud token; every delivery carries the secret’s signature instead.
coding_agents/app.py

A schedule that fans out

A schedule is a function with cron; spawn_map starts one eval-task call per task, and call.result(wait=True) collects each outcome, with a failed call counted as a failed task.
coding_agents/app.py

Adapt it

  • Another stack needs its tools in agent_image and its commands in SETUP_COMMAND and TEST_COMMAND, for example npm ci and npm test.
  • AGENT_MODEL takes opus or a full model name; the eval is the place to compare models on cost and pass rate before switching.
  • A CI job that runs uv run python -m coding_agents.snapshot after each merge keeps pull requests close to the default branch.

Clean up

Remove the webhook in the repository’s settings, and delete the agent/issue-* branches you no longer need. Snapshot images stay in the workspace, since the CLI has no command to delete an image. deployment stop nightly-eval pauses only the eval.