DaytonaDocs
Working with Sandboxes

Git Operations

Clone, branch, commit, push, and pull inside a sandbox.

Every sandbox exposes a Git API through sandbox.git, so you can drive repositories inside the sandbox without shelling in or scripting the git binary yourself. This is the backbone of agent workflows: clone a repo into the sandbox, let the agent edit, then commit and push the result — all from your orchestrating code. All path arguments are repository paths inside the sandbox.

Supported operations

OperationPythonTypeScript
Clone a repositoryclone(url, path, branch, commit_id, username, password)clone(url, path, branch?, commitId?, username?, password?)
Working-tree statusstatus(path)status(path)
List branchesbranches(path)branches(path)
Create a branchcreate_branch(path, name)createBranch(path, name)
Delete a branchdelete_branch(path, name)deleteBranch(path, name)
Check out a branchcheckout_branch(path, branch)checkoutBranch(path, branch)
Stage filesadd(path, files)add(path, files)
Commit staged changescommit(path, message, author, email)commit(path, message, author, email)
Pushpush(path, username, password)push(path, username?, password?)
Pullpull(path, username, password)pull(path, username?, password?)

clone can target a specific branch or pin an exact commit_id; commit returns the new commit hash.

Authenticating to private repositories

clone, push, and pull accept optional username/password parameters for HTTPS authentication. With hosting providers that use personal access tokens, pass the token as the password (for GitHub, any non-empty username works with a token):

Python
sandbox.git.clone(
    "https://github.com/acme/private-repo.git",
    "/workspace/repo",
    username="x-access-token",
    password=github_token,
)

Rather than embedding tokens in your orchestration code, you can also manage credentials as project secrets and provide them to the sandbox at create time.

Note: credentials passed to clone are used for that operation; pass them again on push/pull when the remote requires auth.

An agent loop: clone → edit → commit → push

The complete round trip, as an orchestrator would run it:

Python
repo = "/workspace/repo"
 
# 1. Clone the working branch.
sandbox.git.clone(
    "https://github.com/acme/app.git", repo,
    branch="main",
    username="x-access-token", password=token,
)
 
# 2. Create a task branch and let the agent edit files.
sandbox.git.create_branch(repo, "fix/issue-142")
sandbox.git.checkout_branch(repo, "fix/issue-142")
sandbox.process.exec("python agent_edit.py", cwd=repo)
 
# 3. Inspect what changed.
status = sandbox.git.status(repo)
print(status["currentBranch"], status.get("fileStatus"))
 
# 4. Stage, commit, push.
sandbox.git.add(repo, ["."])
result = sandbox.git.commit(
    repo, "Fix issue #142", author="Agent", email="agent@acme.dev")
print("committed", result["hash"])
sandbox.git.push(repo, username="x-access-token", password=token)
TypeScript
const repo = '/workspace/repo'
 
// 1. Clone the working branch.
await sandbox.git.clone(
  'https://github.com/acme/app.git', repo,
  'main', undefined,
  'x-access-token', token,
)
 
// 2. Create a task branch and let the agent edit files.
await sandbox.git.createBranch(repo, 'fix/issue-142')
await sandbox.git.checkoutBranch(repo, 'fix/issue-142')
await sandbox.process.executeCommand('python agent_edit.py', repo)
 
// 3. Inspect what changed.
const status = await sandbox.git.status(repo)
console.log(status.currentBranch, status.fileStatus)
 
// 4. Stage, commit, push.
await sandbox.git.add(repo, ['.'])
const result = await sandbox.git.commit(
  repo, 'Fix issue #142', 'Agent', 'agent@acme.dev')
console.log('committed', result.hash)
await sandbox.git.push(repo, 'x-access-token', token)

Status and branches

status returns the current branch, ahead/behind counts against the remote, and per-file staging/worktree states — enough to decide whether there's anything to commit. branches lists the branch names in the repository.

Python
status = sandbox.git.status("/workspace/repo")
if status.get("fileStatus"):
    print("dirty tree:", [f["name"] for f in status["fileStatus"]])
 
print(sandbox.git.branches("/workspace/repo")["branches"])

See also

  • Running Commands — for git operations the API doesn't cover, run git directly with exec.
  • Secrets — keep tokens out of your code.

On this page