Repository navigation
claude: a fresh box per run, cloned not copied, deleted after - #1236
Merged
Merged
Conversation
onctl claude now creates a new box for every run, <project>-<slug>-<id> (the slug from --prompt, else an adjective-noun pair), and deletes it when Claude exits or setup fails -- after fetching its branches and uncommitted work here as box/*, the same fetch as onctl claude fetch; if that fetch fails the box is kept and the message says how to get the work and remove it. Detaching with Claude still running keeps the box, with the --box line that comes back to it. Ctrl-C during setup reaches the same end, so a half-made box goes too. A git repository with an origin is no longer copied: the box clones origin's default branch (a GitHub one over https, so the box's credential helper serves it -- the token is forwarded for the clone the way it is for an attach, on a connection of its own) and Claude works on a new branch, onctl/<slug>-<id>. Anything else is copied as before. cloneScript, shared with --repo, refuses a directory that's already there. --github store's token is stored before the clone, which may need it. --keep brings back the long-lived claude-<project> box, cloned onto onctl/<project> the first time; --box, --detach and --task imply it. In herdr an ephemeral session's pane stops the server after Claude, so the attached client returns and the run can end; a kept box's server lives on. --repo keeps its own box as before. After boxctl's 2d33da0 and 33625be, without its reconnect-on-drop. docs/plans/claude-ephemeral-and-ac-image.md is the plan this and the ac image work came from. Claude-Session: https://claude.ai/code/session_01FGfFdYSzrrKe3ySAVMPSNR
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1236 +/- ##
==========================================
- Coverage 47.71% 47.49% -0.23%
==========================================
Files 78 80 +2
Lines 9176 9326 +150
==========================================
+ Hits 4378 4429 +51
- Misses 4798 4897 +99 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
onctl claudestill had boxctl's first model: one long-livedclaude-<project>box, the project copied once and reused forever. boxctl moved on 2026-10-14 to a fresh box per run, and with the prebuilt claude-agent image (#1234) a new VM is cheap enough on every provider, ac included.Follows #1234 (merged); the first PR for this branch, #1235, was closed automatically when that base branch was deleted.
What
<project>-<slug>-<id>(cmd/boxname.go, ported from boxctl: the slug from--prompt, else an adjective-noun pair; 40-character cap; a taken name gets a new id, checked againstlistClaudeVMs).originis cloned on the box (cloneURLturns any GitHub origin into https for the credential helper) onto branchonctl/<slug>-<id>. The GitHub token is forwarded for the clone the way it is for an attach, over a connection of its own (runWith,forwardGitHubshared withattachClaude).--github storestores before the clone. A project without an origin is copied as before.fetchBox(the body ofonctl claude fetch, now reusable) brings branches and a wip snapshot here asbox/*. A failed fetch keeps the box and says how to fetch and destroy by hand. Setup failure or Ctrl-C (signal.NotifyContext) deletes it too; a failure insideopenClaudeBoxdeletes the box only if it got made (discardIfMade).--boxline to come back.--keep/-krestores the project box, cloned ontoonctl/<project>the first time;--box,--detach,--taskand--own-boximply it.--repois unchanged (its own box, kept) and listed as a follow-up.sh <cmd>; herdr server stop, so the attached client returns when Claude exits. A kept box's server lives on.docs/plans/claude-ephemeral-and-ac-image.mdis the plan.Not ported from boxctl: reconnect-on-drop, labels, goals, the 1 GiB copy cap.
Tests
TestTextSlug,TestGenerateName,TestEphemeralRun,TestCloneURL,TestSaveBoxWorkWithNothingToSave,TestRunWithArgs,TestHerdrStartEphemeral, and the "already exists" case inTestCloneScript.go test ./cmd/green.To verify by hand (ac, on this Mac, from a GUI terminal)
onctl -p ac claude --prompt "add a README line"→ a container<repo>-add-readme-line-xxxxon branchonctl/add-readme-line-xxxx; quitting Claude prints "Fetching…", leavesbox/onctl/…locally and removes the container. Detaching instead keeps it with the--boxhint.--keepgivesclaude-<repo>as before.🤖 Generated with Claude Code
https://claude.ai/code/session_01FGfFdYSzrrKe3ySAVMPSNR