Skip to content
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# Features

- [Workspaces](./workspaces.md)
- [Local](./local.md)
- [SSH](./ssh.md)
- [Forking](./fork.md)
- [Init Hooks](./init-hooks.md)
Expand Down
22 changes: 22 additions & 0 deletions docs/local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Local Workspaces

Local workspaces use [git worktrees](https://git-scm.com/docs/git-worktree) on your local machine. Worktrees share the `.git` directory with your main repository while maintaining independent working changes and checkout state.

## How Worktrees Work

A worktree is a separate directory on the same filesystem as the main repository that shares a `.git` but has independent working changes and checkout state. **All committed changes from any worktree are visible to all other worktrees including the main repository.**

It's important to note that a **worktree is not locked to a branch**. The agent can switch to new branches, enter a detached HEAD state, etc. When you create a workspace, the agent will begin at the selected branch but may switch freely in the course of the session. **We empower users to define their agent's branching strategy in AGENTS.md**

## Filesystem Layout

Local workspaces are stored in `~/.cmux/src/<project-name>/<workspace-name>`.

Example layout:

```
~/.cmux/src/
cmux-main/
improved-auth-ux/
fix-ci-flakes/
```
126 changes: 111 additions & 15 deletions docs/theme/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
--link-color: rgb(62, 140, 218);
--link-hover: var(--color-plan-mode-hover);
--content-max-width: 78ch;
--radius-lg: 10px;
--radius-md: 8px;
--radius-sm: 6px;
--radius-xs: 4px;
--radius-lg: 8px;
--radius-md: 6px;
--radius-sm: 4px;
--radius-xs: 3px;
--shadow-1: 0 1px 1px hsl(0 0% 0% / 0.25);
--shadow-2: 0 2px 10px hsl(0 0% 0% / 0.35);

Expand Down Expand Up @@ -233,12 +233,14 @@ p:has(+ ol) {
padding: 2px 6px;
font-family: var(--font-monospace);
font-size: 0.92em;
border-radius: var(--radius-xs);
}

/* Code blocks */
pre {
background: var(--color-background-secondary) !important;
border: 1px solid var(--color-border) !important;
border-radius: var(--radius-md);
box-shadow: var(--shadow-1);
overflow: auto;
margin: 1rem 0;
Expand All @@ -259,23 +261,52 @@ pre > code {

/* Tables */
table {
border-collapse: collapse;
border-collapse: separate;
border-spacing: 0;
width: 100%;
margin: 1.1em 0;
background: var(--color-background-secondary) !important;
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
overflow: hidden;
}
table thead {
background: color-mix(in srgb, var(--color-background-secondary), white 8%);
border-bottom: 2px solid var(--color-border) !important;
}
table thead tr:first-child th:first-child {
border-top-left-radius: var(--radius-md);
}
table thead tr:first-child th:last-child {
border-top-right-radius: var(--radius-md);
}
table tbody tr:last-child td:first-child {
border-bottom-left-radius: var(--radius-md);
}
table tbody tr:last-child td:last-child {
border-bottom-right-radius: var(--radius-md);
}
table th,
table td {
padding: 0.75em 1em;
border: 1px solid var(--color-border) !important;
border-right: 1px solid var(--color-border);
border-bottom: 1px solid var(--color-border);
text-align: left !important;
color: var(--color-text) !important;
}
table th:first-child,
table td:first-child {
border-left: none;
}
table th:last-child,
table td:last-child {
border-right: none;
}
table thead th {
border-bottom: 2px solid var(--color-border) !important;
}
table tbody tr:last-child td {
border-bottom: none;
}
table th {
font-weight: 700;
font-size: 1.05em;
Expand All @@ -291,17 +322,82 @@ table code {
font-size: 0.9em;
}

/* Blockquotes (callout style) */
/* Blockquotes with GitHub-style alerts support */
blockquote {
border: 1px solid var(--color-border) !important;
border-left: 4px solid var(--color-plan-mode) !important;
background: color-mix(in srgb, var(--color-background-secondary), white 1.5%) !important;
padding: 0.5rem 0.6rem;
margin: 1.2rem 0;
color: color-mix(in srgb, var(--color-text), white 6%) !important;
border-left: 3px solid var(--color-plan-mode);
background: color-mix(in srgb, var(--color-background-secondary), white 3%);
padding: 1rem 1.2rem;
margin: 1.5rem 0;
border-radius: var(--radius-md);
color: var(--color-text);
}

blockquote p {
margin: 0.5rem 0;
}

blockquote p:first-child {
margin-top: 0;
}

blockquote p:last-child {
margin-bottom: 0;
}

/* GitHub-style alert callouts */
/* NOTE: blue */
blockquote:has(p:first-child > strong:first-child:is([class*="Note"], [class*="note"])),
blockquote > p:first-child:has(strong:first-child:is([class*="Note"], [class*="note"])) {
border-left-color: hsl(210 70% 50%);
}
blockquote:has(p:first-child > strong:first-child:is([class*="Note"], [class*="note"])) p:first-child strong:first-child,
blockquote > p:first-child strong:first-child:is([class*="Note"], [class*="note"]) {
color: hsl(210 70% 60%) !important;
}

/* TIP: green */
blockquote:has(p:first-child > strong:first-child:is([class*="Tip"], [class*="TIP"])),
blockquote > p:first-child:has(strong:first-child:is([class*="Tip"], [class*="TIP"])) {
border-left-color: hsl(120 50% 45%);
}
blockquote:has(p:first-child > strong:first-child:is([class*="Tip"], [class*="TIP"])) p:first-child strong:first-child,
blockquote > p:first-child strong:first-child:is([class*="Tip"], [class*="TIP"]) {
color: hsl(120 50% 55%) !important;
}

/* IMPORTANT: purple */
blockquote:has(p:first-child > strong:first-child:is([class*="Important"], [class*="IMPORTANT"])),
blockquote > p:first-child:has(strong:first-child:is([class*="Important"], [class*="IMPORTANT"])) {
border-left-color: hsl(268 94% 60%);
}
blockquote:has(p:first-child > strong:first-child:is([class*="Important"], [class*="IMPORTANT"])) p:first-child strong:first-child,
blockquote > p:first-child strong:first-child:is([class*="Important"], [class*="IMPORTANT"]) {
color: hsl(268 94% 65%) !important;
}

/* WARNING: orange/yellow */
blockquote:has(p:first-child > strong:first-child:is([class*="Warning"], [class*="WARNING"])),
blockquote > p:first-child:has(strong:first-child:is([class*="Warning"], [class*="WARNING"])) {
border-left-color: hsl(38 92% 50%);
}
blockquote:has(p:first-child > strong:first-child:is([class*="Warning"], [class*="WARNING"])) p:first-child strong:first-child,
blockquote > p:first-child strong:first-child:is([class*="Warning"], [class*="WARNING"]) {
color: hsl(38 92% 60%) !important;
}

/* CAUTION: red */
blockquote:has(p:first-child > strong:first-child:is([class*="Caution"], [class*="CAUTION"])),
blockquote > p:first-child:has(strong:first-child:is([class*="Caution"], [class*="CAUTION"])) {
border-left-color: hsl(0 70% 55%);
}
blockquote:has(p:first-child > strong:first-child:is([class*="Caution"], [class*="CAUTION"])) p:first-child strong:first-child,
blockquote > p:first-child strong:first-child:is([class*="Caution"], [class*="CAUTION"]) {
color: hsl(0 70% 60%) !important;
}

/* Default strong styling in blockquotes */
blockquote strong {
color: var(--color-plan-mode) !important;
color: var(--color-plan-mode);
}

/* kbd (for keybinds page) */
Expand Down
67 changes: 29 additions & 38 deletions docs/workspaces.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,50 @@
# Workspaces

cmux supports multiple workspace backends for different use cases:
Workspaces in cmux provide isolated development environments for parallel agent work. Each workspace maintains its own Git state, allowing you to explore different approaches, run multiple tasks simultaneously, or test changes without affecting your main repository.

- **Local workspaces**: [git worktrees](https://git-scm.com/docs/git-worktree) on your local machine
- **SSH workspaces**: Regular git clones on a remote server accessed via SSH
## Workspace Types

The backend is selected based on your runtime configuration. Local workspaces use git worktrees which share the `.git` directory with your main repository, while SSH workspaces are independent git clones on the remote machine.
cmux supports two workspace backends:

## Basics of worktrees
- **[Local Workspaces](./local.md)**: Use [git worktrees](https://git-scm.com/docs/git-worktree) on your local machine. Worktrees share the `.git` directory with your main repository while maintaining independent working changes.

A worktree is a seperate directory on the same filesystem as the main repository that shares a `.git`
but has independent working changes and checkout state. **All committed changes from any worktree are
visible to all other worktrees including the main repository.**
- **[SSH Workspaces](./ssh.md)**: Regular git clones on a remote server accessed via SSH. These are completely independent repositories stored on the remote machine.

It's important to note that a **worktree is not locked to a branch**. The agent can switch to new
branches, enter a detached HEAD state, etc. When you create a workspace, the agent will
begin at the selected branch but may switch freely in the course of the session. **We empower users to define their agent's branching strategy in AGENTS.md**
## Choosing a Backend

## Reviewing code
The workspace backend is selected when you create a workspace:

Here are a few practical approaches to reviewing changes from workspaces,
depending on how much you want your agent to interact with `git`:
- **Local**: Best for fast iteration, local testing, and when you want to leverage your local machine's resources
- **SSH**: Ideal for heavy workloads, long-running tasks, or when you need access to remote infrastructure

## Key Concepts

- **Isolation**: Each workspace has independent working changes and Git state
- **Branch flexibility**: Workspaces can switch branches, enter detached HEAD state, or create new branches as needed
- **Parallel execution**: Run multiple workspaces simultaneously on different tasks
- **Shared commits**: Local workspaces (using worktrees) share commits with the main repository immediately

## Reviewing Code

Here are a few practical approaches to reviewing changes from workspaces, depending on how much you want your agent to interact with `git`:

- **Agent codes, commits, and pushes**: Ask agent to submit a PR and review changes in your git Web UI (GitHub, GitLab, etc.)
- Also see: [Agentic Git Identity](./agentic-git-identity.md)
- This is the preferred approach for `cmux` development but requires additional care with repository security.
- **Agent codes and commits**: Review changes from the main repository via `git diff <workspace-branch>`, push changes when deemed acceptable.
- **Agent codes**: enter worktree (click Terminal icon in workspace top bar), run `git add -p` and progressively accept changes into a commit.

## Reviewing functionality

Some changes (esp. UI ones) require the Human to determine acceptability. An effective approach
for this is:

1. Ask agent to commit WIP when its ready for Human review
1. Human, in main repository, checks out the workspace branch in a detached HEAD state: `git checkout --detach <workspace-branch>`
- **Agent codes**: Enter worktree (click Terminal icon in workspace top bar), run `git add -p` and progressively accept changes into a commit.

Note: this workflow uses the detached HEAD state because the branch is already
checked out in the workspace and you cannot check out the same branch multiple times
across worktrees.
## Reviewing Functionality

If you want faster iteration in between commits, you can hop into the worktree directory and run a
dev server (e.g. `bun dev`) there directly and observe the agent's work in real-time.
Some changes (especially UI ones) require the Human to determine acceptability. An effective approach for this is:

## Filesystem Layout
1. Ask agent to commit WIP when it's ready for Human review
2. Human, in main repository, checks out the workspace branch in a detached HEAD state: `git checkout --detach <workspace-branch>` (for local workspaces)

Local workspaces are stored in `~/.cmux/src/<project-name>/<workspace-name>`.
**Note**: For local workspaces, this workflow uses the detached HEAD state because the branch is already checked out in the workspace and you cannot check out the same branch multiple times across worktrees.

SSH workspaces are stored on the remote machine at `~/workspace/<project-name>/<workspace-name>` (or your configured remote path).
If you want faster iteration in between commits, you can hop into the workspace directory and run a dev server (e.g. `bun dev`) there directly and observe the agent's work in real-time.

Example layout:
---

```
~/.cmux/src/
cmux-main/
improved-auth-ux/
fix-ci-flakes/
```
See the specific workspace type pages for detailed setup and usage instructions.
5 changes: 5 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
bash
nixfmt-rfc-style

# Documentation
mdbook
mdbook-mermaid
mdbook-linkcheck

# Terminal bench
uv
asciinema
Expand Down
4 changes: 2 additions & 2 deletions scripts/docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ if [ ! -f "docs/mermaid-init.js" ] || [ ! -f "docs/mermaid.min.js" ]; then
cd ..
fi

# Serve the docs
cd docs && mdbook serve --open
# Serve the docs (bind to all hosts for remote access)
cd docs && mdbook serve --hostname 0.0.0.0 --open