<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Mostly CI/test changes plus a small logging tweak; low production
impact, with main risk being altered test timing/flake behavior due to
new timeout defaults.
>
> **Overview**
> Improves release-candidate GitHub workflows by passing sanitized
`tag`/`preid` via step `env` vars and quoting them when running `npm
version`/`npm publish`, reducing the chance of input/expansion issues.
>
> Stabilizes sandbox internet-access tests in JS and Python by switching
the curl target to Google’s `generate_204` endpoint and updating
expected status codes. Python tests also tighten global `pytest` timeout
to 30s, remove per-sandbox default timeouts from fixtures, and add 180s
timeouts specifically for template test suites via new `conftest.py`
files.
>
> CLI sandbox status polling now logs the caught error when
`Sandbox.getInfo` fails (instead of silently returning `false`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
187849338dd46f9d0dd1adb0a070719ebad87309. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
# Sandbox Git Commands
Adds Git support to the sandbox class. This allows the sandbox to manage
git via standard clone, checkout, branch, add, pull, and push commands
without needing to use commands.run. The API mirrors common Git
workflows while handling sandbox-specific concerns like auth injection
and safe remote handling.
**Python example**
```python
from e2b import Sandbox
sandbox = Sandbox.create()
repo_path = '/home/user/my-repo'
# Optional: set author for commits
sandbox.git.configure_user('Your Name', 'you@example.com')
# Clone or init
sandbox.git.clone('https://github.com/org/repo.git', path=repo_path)
# or
sandbox.git.init(repo_path, initial_branch='main')
# Make a change
sandbox.files.write(f'{repo_path}/README.md', '# Hello\n')
# Commit
sandbox.git.add(repo_path, files=['README.md'])
sandbox.git.commit(repo_path, message='Initial commit')
# Branching
sandbox.git.create_branch(repo_path, 'feature1')
# or
sandbox.git.checkout_branch(repo_path, 'main')
# Push
sandbox.git.remote_add(repo_path, 'origin', 'https://github.com/org/repo.git', overwrite=True)
sandbox.git.push(repo_path, remote='origin', branch='main', set_upstream=True)
```
**JavaScript / TypeScript example**
```ts
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create()
const repoPath = '/home/user/my-repo'
await sandbox.git.configureUser('Your Name', 'you@example.com')
await sandbox.git.clone('https://github.com/org/repo.git', { path: repoPath })
// or
await sandbox.git.init(repoPath, { initialBranch: 'main' })
await sandbox.files.write(`${repoPath}/README.md`, '# Hello\n')
await sandbox.git.add(repoPath, { files: ['README.md'] })
await sandbox.git.commit(repoPath, { message: 'Initial commit' })
await sandbox.git.createBranch(repoPath, 'feature1')
await sandbox.git.checkoutBranch(repoPath, 'main')
await sandbox.git.remoteAdd(repoPath, 'origin', 'https://github.com/org/repo.git', {
overwrite: true,
})
await sandbox.git.push(repoPath, { remote: 'origin', branch: 'main', setUpstream: true })
```
**Main commands**
- `clone`: Clone a repo into the sandbox. Supports `branch`, `depth`,
optional `username` + `password` for private repos, and
`dangerously_store_credentials` / `dangerouslyStoreCredentials` to keep
credentials in the remote URL.
- `init`: Initialize a new repo. Supports `initial_branch` /
`initialBranch` and `bare`.
- `status`: Get parsed `git status --porcelain -b` info.
- `branches`: List branches and current branch.
- `create_branch` / `createBranch`: Create and check out a new branch.
- `checkout_branch` / `checkoutBranch`: Switch to an existing branch.
- `delete_branch` / `deleteBranch`: Delete a branch. Supports `force`.
- `add`: Stage files. Supports explicit files or `all`.
- `commit`: Create a commit. Supports author override and `allow_empty`.
- `reset` / `reset`: Reset `HEAD` (supports modes like `soft`, `mixed`,
`hard`, etc.) and optional paths.
- `restore` / `restore`: Restore files or unstage changes (`worktree` /
`staged`) from a source ref.
- `pull`: Pull from a remote. Supports `remote`, `branch`, and optional
auth.
- `push`: Push to a remote. Supports `remote`, `branch`, `set_upstream`,
and optional auth.
- `remote_add` / `remoteAdd`: Add a remote. Supports `overwrite` and
`fetch`.
- `remote_get` / `remoteGet`: Read a remote URL.
- `set_config` / `setConfig`: Set a git config value. Supports `scope`
(`global`, `local`, `system`), and `path` for local scope.
- `get_config` / `getConfig`: Read a git config value. Supports the same
`scope` options and returns `None` / `undefined` if unset.
- `dangerously_authenticate` / `dangerouslyAuthenticate`: Persist
credentials via the git credential helper (global).
- `configure_user` / `configureUser`: Set default `user.name` and
`user.email` for commits.
- `create_github_repo` (Python only): Create a GitHub repo from inside
the sandbox and optionally add it as a remote.
**Status shape**
- `status` returns a `GitStatus` with `current_branch` /
`currentBranch`, `upstream`, `ahead`, `behind`, `detached`, and
`file_status` / `fileStatus`.
- `file_status` entries include `name`, `status`, `index_status` /
`indexStatus`, `working_tree_status` / `workingTreeStatus`, `staged`,
and optional `renamed_from` / `renamedFrom`.
- Convenience helpers include: `is_clean` / `isClean`, `has_changes` /
`hasChanges`, `has_staged` / `hasStaged`, `has_untracked` /
`hasUntracked`, `has_conflicts` / `hasConflicts`, plus counts
(`total_count` / `totalCount`, `staged_count` / `stagedCount`,
`unstaged_count` / `unstagedCount`, `untracked_count` /
`untrackedCount`, `conflict_count` / `conflictCount`). In Python these
are properties on the `GitStatus` object; in JS they are fields on the
returned object.
**Notes**
- For private HTTPS remotes, pass `username` + `password` (token) on
`clone`, `pull`, or `push`.
- Use `remote_add` / `remoteAdd` with `overwrite=True` to update an
existing remote URL and `fetch=True` to fetch after.
- Use `dangerously_authenticate` / `dangerouslyAuthenticate` only when
you want to persist credentials globally on the sandbox.
- Individual tests must complete in less than 5 minutes
- Add a `make test` option that runs tests
- Upgrade poetry to 2.1.1 (the lock file was generated by this version,
so this just matches what we already expect)
Introduce beta submodule with beta features - pause and resume
Update Sandbox list to also return paused sandboxes
---------
Co-authored-by: Tomas Valenta <valenta.and.thomas@gmail.com>