> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oxen.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 📦 Workspaces

> Workspaces allow you to stage changes to a repository without having to download it locally.

A workspace is like a working directory that lives on the Oxen server. You can `add`, `rm`, and modify files in a workspace and then commit those changes in bulk, without ever cloning the repository to your local machine.

Under the hood, every workspace is pinned to a specific commit on a branch. All staged changes are computed relative to that commit. Staged changes survive server restarts, but they are **not** part of the repository's commit history until you commit the workspace, so they can be deleted without leaving a trace.

## Why use a workspace?

Reach for a workspace when you want to:

* **Edit a repository that's too large to clone.** Stage changes to a 100GB+ repo without copying it to your machine.
* **Bulk-import data without keeping a local copy.** `oxen workspace add` uploads directly to the server, so you don't pay the disk cost of writing every file into a local `.oxen` store first.
* **Batch many changes into a single commit.** Add, remove, and modify dozens of files server-side, then land them as one atomic commit.
* **Let multiple clients contribute to one staged commit.** A named workspace can be written to by several processes or users before anyone commits — useful for workflows like labeling UIs, ingestion services, or agents producing training data.
* **Keep a long-lived staging area across multiple commits.** Named workspaces persist after commit and fast-forward to the new commit, so the same workspace can be reused over and over.

If you're working in a repo small enough to clone and just want the normal `add → commit → push` flow, you don't need a workspace — see the [Version Control guide](/examples/data/versioning) instead.

## Quick start

### Add to an existing repo without cloning it

Imagine a repository with 1 million images. Instead of cloning the data, init an empty local repo, point it at the remote, and write directly to a workspace.

<CodeGroup>
  ```bash CLI theme={null}
  oxen init
  oxen config --set-remote origin https://hub.oxen.ai/ox/ImageNet-1k
  oxen workspace create --name add_image --branch main
  # Stage a single file into the images/ directory of the workspace
  oxen workspace add /path/to/my_images/image.jpg --directory images/ --workspace-name add_image
  # See what's staged
  oxen workspace status --workspace-name add_image
  # Commit the staged changes to main
  oxen workspace commit -m "Add new image to images/ directory" -n add_image -b main
  ```

  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/ImageNet-1k")  # Host defaults to 'hub.oxen.ai'
  workspace = Workspace(repo, "extra-images")
  workspace.add("new_images/")

  status = workspace.status()
  print(status.added_files())

  workspace.commit("Add new images to dataset")
  ```
</CodeGroup>

### Bulk-import data into a fresh repo

`oxen workspace add` never writes data to your local machine — files stream directly to the remote. This avoids the disk and time cost of `add → commit → push`, which would otherwise copy every file into a local `.oxen` store first.

<CodeGroup>
  ```bash CLI theme={null}
  oxen init
  oxen config --create-remote --host hub.oxen.ai --scheme https --name ox/ImageNet-1k
  oxen workspace create  # Create a workspace to import the data. This will return a workspace ID
  oxen workspace add images/ --workspace-id [WORKSPACE_ID]
  oxen workspace commit -m "Import 1 million images" -w [WORKSPACE_ID]
  ```

  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/ImageNet-1k", files="README.md")
  workspace = Workspace(repo)
  workspace.add("images/")

  status = workspace.status()
  print(status.added_files())

  workspace.commit("Import 1 million images")
  ```
</CodeGroup>

Workspaces can also be driven through the [HTTP API](/http-api/workspaces/get-or-create-workspace) — useful when you're building a custom client (labeling UI, ingestion daemon, agent, etc.) that needs to write to a repo without shipping the Oxen CLI or Python SDK.

## How it works

Every workspace references a specific commit, the same way a branch does. All your staged operations are recorded as a diff against that base commit.

When you commit a workspace:

1. Oxen applies your staged diff on top of the workspace's base commit to produce a new commit.
2. That new commit is added to a target branch on the remote (see [Committing changes](#committing-changes) for how the target is chosen).
3. If the target branch has advanced past the workspace's base commit, Oxen attempts to merge. Conflicts cause the commit to fail and you'll need to resolve them before retrying.

Because workspaces are commit-scoped, two workspaces created from the same branch at different times can see completely different views of the repo. That's intentional — it gives you isolation while staging — but it also means a long-lived workspace can drift from the branch tip and accumulate conflicts.

## Creating a workspace

A workspace is created against a remote repository, and optionally against a specific branch.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, "add-images")
  ```

  ```bash CLI theme={null}
  oxen workspace create -w my-workspace-name -b add-images
  ```
</CodeGroup>

If no branch is provided, the default branch (usually `main`) is used.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo)
  ```

  ```bash CLI theme={null}
  oxen workspace create
  ```
</CodeGroup>

The workspace is pinned to whatever commit the branch points at when you create it. You can only create workspaces from branches that already exist on the remote.

### Named vs. unnamed workspaces

Every workspace has an auto-generated **id**. You can optionally also give it a human-readable **name**.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, name="my-workspace-name")
  ```

  ```bash CLI theme={null}
  oxen workspace create -n my-workspace-name
  ```
</CodeGroup>

The name matters because of two behavioral differences:

|                       | Unnamed workspace                   | Named workspace                                            |
| --------------------- | ----------------------------------- | ---------------------------------------------------------- |
| Lifetime after commit | Deleted                             | Persists, fast-forwarded to the new commit                 |
| Best for              | One-shot imports, throwaway staging | Long-lived staging, multi-commit or multi-client workflows |

Use a **named** workspace when you expect to make multiple commits from the same workspace, or when several processes/users will share it. Use an **unnamed** workspace for one-off imports where you don't need it to stick around.

### Identifying a workspace in CLI commands

Most workspace commands need to know *which* workspace you're targeting. You can reference a workspace by either its id or its name:

* `--workspace-id <id>` (short: `-w`) — reference by the auto-generated id returned from `oxen workspace create`.
* `--workspace-name <name>` (short: `-n`) — reference by the name you set with `--name` at create time.

## Listing workspaces

List the workspaces on a remote with `oxen workspace list`.

```bash theme={null}
oxen workspace list -r my_remote  # Defaults to `origin` if no remote is provided
```

## Adding files

`oxen workspace add` streams a file's contents directly to the server and stages it on the workspace.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, "add-images")
  workspace.add("/path/to/image.png")
  status = workspace.status()
  print(status.added_files())
  ```

  ```bash CLI theme={null}
  oxen workspace add image.png -w my-workspace-id
  oxen workspace status -w my-workspace-id
  ```
</CodeGroup>

### Unstaging a file

To remove a file you've staged on the workspace (without touching the base repo), unstage it with `oxen workspace rm --staged`.

```bash CLI theme={null}
oxen workspace rm --staged image.jpg -w my-workspace-id
```

### Deleting a file from the base repo

<Warning>
  `oxen workspace rm` **without** `--staged` stages a deletion of a file that exists in the base repo. When you commit the workspace, that file will be removed from the branch. Use `--staged` if you only want to unstage a previously added file.
</Warning>

<CodeGroup>
  ```bash CLI theme={null}
  oxen workspace rm image.jpg -w my-workspace-id
  ```

  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, "add-images")
  workspace.rm("image.jpg")  # Stages a deletion of image.jpg from the base repo
  ```
</CodeGroup>

## Committing changes

Commit a workspace to land its staged changes as a new commit on the remote.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, "add_images")
  workspace.commit("adding an image using a workspace", "add_images")
  ```

  ```bash CLI theme={null}
  oxen workspace commit -m "adding an image" -w my-workspace-id -b add_images
  ```
</CodeGroup>

If you don't provide a target branch, the commit will be made to a new branch on the remote.

<CodeGroup>
  ```python Python theme={null}
  from oxen import RemoteRepo
  from oxen import Workspace

  repo = RemoteRepo("ox/CatDogBBox")
  workspace = Workspace(repo, "my_branch")
  workspace.commit("adding an image using a workspace")  # No branch is provided, so this will create a new branch
  ```

  ```bash CLI theme={null}
  oxen workspace commit -m "adding an image" -w my-workspace-id  # No branch is provided, so this will create a new branch
  ```
</CodeGroup>

After a successful commit:

* An **unnamed** workspace is deleted.
* A **named** workspace is fast-forwarded to point at the new commit, so you can keep using it.

If merge conflicts are detected (because the target branch has advanced past the workspace's base commit), the commit will fail. {/* TODO: how should users resolve a workspace merge conflict? Is there an `oxen workspace ...` command for this, or is the recommended fix to discard the workspace and re-create it off the latest commit, then re-stage? A short pointer here would help. */}
