Repo-first & git

run from a commit, and push-to-run

Three ways to give the platform your code

1 · Paste / upload — paste a snippet or upload a .zip/.tar.gz on Run. It lands in /work. Fastest way to try something.

2 · Point at a git ref — give a repo URL + ref inline; the agent clones it into /work. Public repos need nothing; private ones take a short-lived token.

3 · Stored git connection (repo-first) — your org stores a repo + its credential once, sealed at rest. Every run then just names the connection + a ref, and the orchestrator resolves the exact commit and clones it — you never handle the token again.

Connect a repo (stored connection)

Create a connection once (Forgejo, Gitea, GitLab, or GitHub). Two auth kinds: an HTTPS PAT, or an SSH deploy key the platform generates for you (add the returned public key to the repo). The API never echoes a stored secret back.

# create a connection (HTTPS PAT). The secret is write-only — stored sealed, never returned.
curl -X POST $BASE/v1/git/connections \
  -H "Authorization: Bearer slt_…" -H "content-type: application/json" \
  -d '{
    "provider": "github",
    "base_url": "https://github.com",
    "repo_url": "https://github.com/acme/sim-lab.git",
    "auth_kind": "https_pat",
    "secret": "ghp_…",
    "label": "sim-lab",
    "default_ref": "main"
  }'

# health-check it (ls-remote) and list its branches/tags
curl -X POST $BASE/v1/git/connections/<id>/test  -H "Authorization: Bearer slt_…"
curl "$BASE/v1/git/connections/<id>/refs?type=branch" -H "Authorization: Bearer slt_…"

Managing connections needs the git:connect scope; reading/testing needs git:read. Cross-tenant ids return 404.

Run from a commit

Submit a run whose source is the stored connection at a ref (branch, tag, or SHA). The orchestrator resolves the ref to an exact commit and synthesizes the workspace — don’t also send a raw workspace.

curl -X POST $BASE/v1/jobs \
  -H "Authorization: Bearer slt_…" -H "content-type: application/json" \
  -d '{
    "stack": "mujoco",
    "command": ["python", "train.py"],
    "source": { "type": "git", "connection_id": "<id>", "ref": "main" },
    "limits": { "cpu_cores": 4, "ram_gb": 8, "timeout_sec": 1800 }
  }'

Every run records the resolved commit, so a run is reproducible from its spec.

Push-to-run

Attach a run-on-push trigger to a connection: a run template (stack, command, config) that fires when a matching branch is pushed. Setting the trigger returns a webhook URL + signing secret once — paste them into the provider’s webhook settings.

curl -X PUT $BASE/v1/git/connections/<id>/trigger \
  -H "Authorization: Bearer slt_…" -H "content-type: application/json" \
  -d '{
    "enabled": true,
    "branch": "main",
    "stack": "mujoco",
    "command": ["python", "train.py"],
    "config": { "seed": 42 }
  }'
# → { "webhook_url": "https://…/v1/git/hooks/…", "webhook_secret": "whsec_…", ... }
# add that URL + secret as a webhook in GitHub/GitLab/Forgejo/Gitea.

Now every push to main launches the templated run automatically. Pair it with outgoing webhooks to get notified when the run finishes.

Commit-status mirror

When a run launched from a git commit changes phase, the orchestrator posts the outcome back to the provider’s commit-status API — so the commit shows a pending → success/failure check in GitHub, GitLab, Gitea, or Forgejo. This closes the loop: push → run → status on the commit. The status context is simolyot/<stack> and its target link points back at the run’s page; the description carries the phase plus one key metric.

It’s enabled by default and strictly best-effort — a provider outage or a failed POST never blocks, delays, or fails the run. It fires only for a run tied to a known connection at a pinned commit (a manual {source:{type:git}} HTTPS submit or a push-triggered run); anonymous, uploaded, and inline runs carry no commit to report to.

Opt a connection out with report_status: false at create time:

curl -X POST $BASE/v1/git/connections \
  -H "Authorization: Bearer slt_…" -H "content-type: application/json" \
  -d '{
    "provider": "gitlab",
    "base_url": "https://gitlab.com",
    "repo_url": "https://gitlab.com/acme/sim-lab.git",
    "auth_kind": "https_pat",
    "secret": "glpat_…",
    "report_status": false
  }'

The credential is decrypted transiently for each POST (never logged), the provider URL is SSRF-guarded at delivery, and redirects are never followed — so a public provider host can’t bounce to an internal one.

A stored connection keeps credentials out of every run request — the token lives once, sealed, and the platform clones on your behalf.