Skip to content

claude: a fresh box per run, cloned not copied, deleted after - #1236

Merged
cdalar merged 1 commit into
mainfrom
claude-ephemeral
Oct 25, 2026
Merged

cdalar merged 1 commit into
mainfrom
claude-ephemeral

Conversation

@cdalar

@cdalar cdalar commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Why

onctl claude still had boxctl's first model: one long-lived claude-<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

  • A new box per run, named <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 against listClaudeVMs).
  • Cloned, not copied: a repository with an origin is cloned on the box (cloneURL turns any GitHub origin into https for the credential helper) onto branch onctl/<slug>-<id>. The GitHub token is forwarded for the clone the way it is for an attach, over a connection of its own (runWith, forwardGitHub shared with attachClaude). --github store stores before the clone. A project without an origin is copied as before.
  • Deleted when Claude exits, after fetchBox (the body of onctl claude fetch, now reusable) brings branches and a wip snapshot here as box/*. 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 inside openClaudeBox deletes the box only if it got made (discardIfMade).
  • Detaching keeps it: after the attach returns, a still-running session means the box is kept, with the --box line to come back.
  • --keep / -k restores the project box, cloned onto onctl/<project> the first time; --box, --detach, --task and --own-box imply it. --repo is unchanged (its own box, kept) and listed as a follow-up.
  • herdr: an ephemeral session's pane runs sh <cmd>; herdr server stop, so the attached client returns when Claude exits. A kept box's server lives on.
  • Help text and README describe the new default. docs/plans/claude-ephemeral-and-ac-image.md is 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 in TestCloneScript. 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-xxxx on branch onctl/add-readme-line-xxxx; quitting Claude prints "Fetching…", leaves box/onctl/… locally and removes the container. Detaching instead keeps it with the --box hint. --keep gives claude-<repo> as before.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FGfFdYSzrrKe3ySAVMPSNR

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

codecov Bot commented Oct 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 33.33333% with 116 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.49%. Comparing base (60b8a26) to head (662daf5).

Files with missing lines Patch % Lines
cmd/claude.go 6.77% 55 Missing ⚠️
cmd/claudeephemeral.go 6.81% 41 Missing ⚠️
cmd/boxname.go 78.26% 10 Missing ⚠️
cmd/claudecopy.go 59.09% 9 Missing ⚠️
cmd/claudegit.go 0.00% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cdalar
cdalar merged commit a4b016e into main Oct 25, 2026
13 checks passed
@cdalar
cdalar deleted the claude-ephemeral branch October 25, 2026 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

⌂ 换网址