Git checkout API

Some competitor SDKs expose Git checkout as a named sandbox operation instead of asking callers to hand-roll git clone through commands.run. Coppice now has that convenience route on the gateway. It still executes Git inside the sandbox, so the template must include git; the value is API shape, path hygiene, and a receiptable workflow.

API shape

POST /sandboxes/:id/git/clone
content-type: application/json

{
  "repo": "https://github.com/example/project.git",
  "path": "/workspace/project",
  "branch": "main",
  "depth": 1,
  "singleBranch": true,
  "recurseSubmodules": false
}

Response:

{
  "sandboxID": "8f2ec9...",
  "repo": "https://github.com/example/project.git",
  "path": "/workspace/project",
  "branch": "main",
  "commit": "9a4e...",
  "stdout": "..."
}

If path is omitted, the gateway derives /workspace/<repo-tail>. Relative paths are rooted under /workspace. Paths containing parent traversal or control characters are rejected before the backend sees them.

Credential boundary

The route is intentionally small: it wraps the existing backend exec path and does not mint credentials by itself. Public repos work directly. Private repos should use one of the existing credential paths: inject an SSH deploy key into the sandbox, attach a named secret, or route HTTPS through the host-side credential proxy. A future SDK helper can combine these into a single git.checkout call without changing the substrate.

Receipt

benchmarks/rigs/git-checkout-api-smoke.sh creates a sandbox, constructs a local bare Git origin inside it, calls POST /sandboxes/:id/git/clone against that origin, then verifies the checked-out file contents and returned commit.

Run against honor:

mise run git-checkout-api:honor

Receipt target: benchmarks/results/git-checkout-api/latest.txt.