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

# aspect worktree path

> Print the directory a pooled worktree lives in, and nothing else, so a shell can step into it.

<Warning>
  New and experimental. File bugs and suggestions to [aspect-build/aspect-cli/issues](https://github.com/aspect-build/aspect-cli/issues).
</Warning>

Print the directory a pooled worktree lives in, and nothing else, so a shell can step into it.

```shell theme={null}
slot=$(aspect worktree path fix/login) && cd "$slot"
```

The two steps matter. `cd "$(aspect worktree path fix/login)"` returns 0 even when the command fails, because the substitution is empty and `cd ""` is a no-op, so a script carries on in whatever directory it was already in.

A task runs as a child process and cannot change its caller's directory, so this prints rather than moves. If you want one word, define a shell function:

```bash theme={null}
aspect-cd() { local d; d=$(aspect worktree path "$1") && cd "$d"; }
```

```shell theme={null}
aspect-cd fix/login
```

## Output

The directory goes to **stdout** with nothing else on it, which is what makes command substitution safe. Diagnostics go to stderr.

```shell theme={null}
$ aspect worktree path fix/login
/Users/you/.aspect/worktrees/github.com/acme/repo/aspect-worktree-18a11aa20e8d
```

A slot id works as well as a branch, since the id is the first column of [`aspect worktree list`](/docs/cli/worktrees/list); so does a unique prefix of four characters or more, the slot's directory, and for a detached slot the ref it was taken at:

```shell theme={null}
slot=$(aspect worktree path 18a11aa20e8d) && cd "$slot"
```

A name that resolves to nothing writes nothing to stdout and exits non-zero, naming what this clone does have out:

```
ERROR: no worktree or slot called fix/typo in this pool. This clone's slots answer to fix/login, spike/perf, and `aspect worktree list` prints the slot ids.
```

A free slot resolves, but there is no worktree in it to enter, so the refusal says so and names the one command that would give it one:

```
ERROR: slot f066bb8445cc is free, last holding fix/logout, so nothing is checked out there to
enter. `aspect worktree add fix/logout` takes the slot again, keeping the Bazel state it still
has.
```

## Refusals

| `error` | Exit | Meaning |
| - | - | - |
| `no_such_worktree` | 1 | Nothing in this pool answers to that branch or slot. The message says what this clone does have out. For a branch whose lease of your session ended in the last day, it says that lease ended, names the slot and how long ago, and suggests `aspect worktree add <branch>`; the facts carry those leases as `ended` |
| `owned_elsewhere` | 1 | The slot belongs to another clone of this repository that still exists, however it was named. Run it from there |
| `slot_stranded` | 1 | The slot is leased for a clone that is gone and that no clone here lists — or for this clone's path while this clone's git has no worktree there, the checkout of a clone that was here before it. A moved clone's slots are taken back by `path` itself, run from the clone where it is now. For a slot recorded for this clone's path, the message also allows that the checkout is this clone's own and damaged, and names `git worktree repair <path>` |
| `slot_not_leased` | 1 | It resolved to a free slot, which has no worktree in it |
| `slot_setting_up` | 1 | An `add` is still checking a worktree out into that slot. `retryable: false` once that `add` has stopped: `aspect worktree add <branch>` recovers it |
| `held_by_another_session` | 1 | The caller is an agent — detected, or named with `--agent-kind` / `--agent-id` or their variables — and the slot is another session's, a sibling subagent's, or — for a subagent — its parent session's. Only the session itself gets its subagents' slots, and a subagent gets only its own. A slot a person took at a terminal, with no agent recorded, is refused to an agent too; a person at a terminal, where no agent is detected, can enter any slot. Its facts name the `slot` and the holder, with `process` — `running`, `stopped`, or `unknown` where none was recorded — and `session_state`, but carry no `path`: the message says the checkout is "that agent's" — or, for a slot a person took, "that person's" — to work in. When the caller's session held the same branch in that slot earlier, the message adds that the lease ended — released, taken over, or taken back while its process was not running — and that its commits are on the branch |
| `invalid_agent` | 1 | `--agent-kind` / `ASPECT_AGENT_KIND` is not a name, or `--agent-id` / `ASPECT_AGENT_ID` is all spaces, longer than 128 characters, or has a character a terminal would act on or hide. Fix the value |
| `not_a_repository` | 1 | The working directory is not a repository |

Reading the pool does not wait for its lock, so `path` never returns `pool_busy`: it is safe to call while an `add` or a `prune` elsewhere is working. It tries the lock once only to take back a moved clone's slots, and answers from the pool as it stands when that is busy. Run by a resumed session from a new process, `path` for a slot it may enter also moves that session's leases off a stopped process onto its own, trying the lock once and leaving them for a later call when it is busy; see [agent detection](/docs/cli/worktrees/agents#what-makes-a-session-resumable-and-what-makes-a-slot-reclaimable).

## Flags

<ParamField path="branch" type="string" required>
  The branch checked out in the slot, the slot id [`aspect worktree list`](/docs/cli/worktrees/list) shows in its first column (or a unique prefix of four or more characters), or the slot's directory. A detached slot also answers to the ref it was taken at, while no other slot is at it. A free slot's last branch resolves too — to a refusal explaining that the slot is free, rather than to a path with nothing at it.
</ParamField>

<ParamField path="--agent-kind" type="string">
  The agent harness asking, as given to `add` with the same flag. Needed only when the lease was taken with `--agent-kind`; detected otherwise.
</ParamField>

<ParamField path="--agent-id" type="string">
  The session or subagent asking, as given to `add` with the same flag. Needed only when the lease was taken with `--agent-id`; detected otherwise.
</ParamField>

<ParamField path="--output" type="text | json" default="text">
  `text` writes only the directory to stdout, so a shell can step into it. `json` writes one document, which is how a harness gets a typed refusal rather than prose.
</ParamField>

## Knowing where you are

Once you are in a worktree, git will tell you which one. The slot directory is named by a hash, so the **branch** is the readable identity:

```bash theme={null}
# in a linked worktree these differ; in the main clone they match
[ "$(git rev-parse --absolute-git-dir)" != "$(git rev-parse --path-format=absolute --git-common-dir)" ]

git branch --show-current     # fix/login
```

`git worktree list` also reports the slot path, and does not mark the current entry.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.