---
icon: lucide/git-branch
---

# dev

Parallel development environment manager using git worktrees.

## Overview

The `dev` command helps you work on multiple features simultaneously by creating isolated git worktrees. Each dev environment is a separate working directory with its own branch, allowing you to:

- Switch between features without stashing changes
- Run multiple AI coding agents in parallel
- Keep your main branch clean while experimenting

Like [git-worktree-runner (gtr)](https://github.com/CodeRabbitAI/git-worktree-runner) but with many more QoL features.

## Quick Start

```bash
# Create a new dev environment (auto-generates a random branch name like "clever-fox")
agent-cli dev new

# Create a new dev environment with AI-generated branch name from the prompt
agent-cli dev new --branch-name-mode ai --prompt "Refactor auth flow"

# Create a dev environment with a specific branch name
agent-cli dev new my-feature

# Create a dev environment and open in editor + start AI agent
agent-cli dev new my-feature -e --start-agent

# Create a dev environment and launch the agent in a detached repo-scoped tmux session
agent-cli dev new my-feature --start-agent -m tmux

# Launch into a specific tmux session instead of the default repo-scoped one
agent-cli dev new my-feature --agent codex --tmux-session review-batch --prompt-file task.md

# List all dev environments
agent-cli dev list

# Remove a dev environment
agent-cli dev rm my-feature
```

## Subcommands

### `dev new`

Create a new parallel development environment.

```bash
agent-cli dev new [BRANCH] [OPTIONS]
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `BRANCH` | Branch name (auto-generated if not provided) |

**Options:**

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.new")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--from, -f` | - | Git ref (branch/tag/commit) to branch from. Defaults to origin/main or origin/master |
| `--editor, -e` | `false` | Open the worktree in an editor. Uses --with-editor, config default, or auto-detects |
| `--start-agent` | `false` | Start an AI coding agent in a new terminal tab without providing an initial prompt. Uses config default or auto-detects. |
| `--agent` | - | Which AI agent to start: claude, codex, gemini, aider, copilot, cn (Continue), opencode, cursor-agent, or auto. Implies starting the agent |
| `--with-editor` | - | Which editor to open: cursor, vscode, zed, nvim, vim, emacs, sublime, idea, pycharm, etc. |
| `--setup/--no-setup` | `true` | Run project setup after creation: npm/pnpm/yarn install, poetry/uv sync, cargo build, etc. Auto-detects project type |
| `--copy-env/--no-copy-env` | `true` | Copy .env, .env.local, .env.example from main repo to worktree |
| `--fetch/--no-fetch` | `true` | Run 'git fetch' before creating the worktree to ensure refs are up-to-date |
| `--branch-name-mode` | `random` | How to auto-name branches when BRANCH is omitted: random (default), auto (AI only when --prompt/--prompt-file is set), or ai (always try AI first) |
| `--branch-name-agent` | - | Headless agent for AI branch naming: claude, codex, or gemini. If omitted, uses --agent when supported, otherwise tries available agents in that order |
| `--branch-name-timeout` | `20.0` | Timeout in seconds for AI branch naming command |
| `--direnv/--no-direnv` | - | Generate .envrc based on project type and run 'direnv allow'. Auto-enabled if direnv is installed |
| `--agent-args` | - | Extra CLI args for the agent. Can be repeated. Example: --agent-args='--dangerously-skip-permissions' |
| `--prompt, -p` | - | Initial task for the AI agent. Saved to a unique file in .claude/ to avoid conflicts. Implies starting the agent. Example: --prompt='Fix the login bug' |
| `--prompt-file, -P` | - | Read the agent prompt from a file. Useful for long prompts to avoid shell quoting. Implies starting the agent |
| `--multiplexer, -m` | - | Launch the agent in a specific multiplexer. Currently supported: tmux. When started outside tmux, creates or reuses a detached session and reports the pane handle |
| `--tmux-session` | - | Reuse or create a specific tmux session for the agent. Implies --multiplexer tmux |
| `--hooks/--no-hooks` | `true` | Run built-in agent preparation (like Codex auto-trust) and configured pre-launch hooks before starting the agent |
| `--verbose, -v` | `false` | Stream output from setup commands instead of hiding it |


<!-- OUTPUT:END -->

**Examples:**

```bash
# Create dev environment from a specific commit
agent-cli dev new hotfix --from v1.2.3

# Create an interactive dev environment with Cursor and Claude
agent-cli dev new feature --with-editor cursor --agent claude

# Quick interactive dev environment with defaults from config
agent-cli dev new -e --start-agent

# Create dev environment with an initial prompt for the agent
agent-cli dev new fix-bug --prompt "Fix the login validation bug in auth.py"

# Use --prompt-file for long prompts (avoids shell quoting issues)
agent-cli dev new refactor --prompt-file task.md

# Launch the default agent interactively in tmux
agent-cli dev new feature --start-agent -m tmux

# Launch a specific agent in tmux with an initial task
agent-cli dev new feature --agent codex -m tmux --prompt-file task.md

# Override the default repo-scoped tmux session
agent-cli dev new feature --agent codex --tmux-session review-batch --prompt-file task.md
```

For automated or headless use, pass `--prompt` or `--prompt-file` so the agent starts working immediately. `--start-agent` is mainly useful when a human plans to attach and drive the session interactively. `--tmux-session` implies `-m tmux` and overrides the default repo-scoped tmux session name.

### `dev list`

List all dev environments (worktrees) for the current repository.

```bash
agent-cli dev list [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.list")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--json` | `false` | Output as JSON. Fields: name, path, branch, is_main, is_detached, is_locked, is_prunable |


<!-- OUTPUT:END -->

### `dev status`

Show status of all dev environments with git status information.

```bash
agent-cli dev status [OPTIONS]
```

**Options:**

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.status")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--stale-days, -s` | `7` | Mark worktrees as stale if inactive for N+ days (default: 7) |
| `--json` | `false` | Output as JSON with fields: name, branch, modified, staged, untracked, ahead, behind, last_commit_timestamp, is_stale |


<!-- OUTPUT:END -->

**Output columns:**

| Column | Description |
|--------|-------------|
| Name | Worktree directory name |
| Branch | Git branch name |
| Changes | File changes: `M` modified, `S` staged, `?` untracked |
| ↑/↓ | Commits ahead (+) / behind (-) upstream |
| Last Commit | Relative time since last commit |

**Examples:**

```bash
# Show status of all worktrees
agent-cli dev status

# Highlight worktrees inactive for 14+ days
agent-cli dev status --stale-days 14
```

**Example output:**

```
                          Dev Environment Status
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━━━━┓
┃ Name        ┃ Branch          ┃ Changes ┃ ↑/↓ ┃ Last Commit    ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━━━━┩
│ main        │ main            │      3M │  —  │ 24 minutes ago │
│ my-feature  │ feat/my-feature │   clean │  —  │ 9 days ago ⚠️   │
└─────────────┴─────────────────┴─────────┴─────┴────────────────┘

2 worktrees · 1 with uncommitted changes · 1 stale (>7 days)
```

**Legend:**
- `M` = Modified files (not staged)
- `S` = Staged files
- `?` = Untracked files
- `+N` = N commits ahead of upstream
- `-N` = N commits behind upstream
- `⚠️` = Stale worktree (inactive for longer than `--stale-days`)

### `dev rm`

Remove a dev environment (worktree).

```bash
agent-cli dev rm NAME [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.rm")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--force, -f` | `false` | Force removal even if worktree has uncommitted changes |
| `--delete-branch, -d` | `false` | Also delete the git branch (not just the worktree) |
| `--yes, -y` | `false` | Skip confirmation prompt |


<!-- OUTPUT:END -->

When a worktree was launched in tmux through `agent-cli`, `dev rm` also cleans up any tagged tmux windows for that worktree. If git removal succeeds but tmux cleanup is partial, the command warns and still removes the worktree.

### `dev path`

Print the path to a dev environment (for shell integration).

```bash
agent-cli dev path NAME
```

**Example:**

```bash
# Navigate to a dev environment
cd "$(agent-cli dev path my-feature)"
```

### `dev editor`

Open a dev environment in an editor.

```bash
agent-cli dev editor NAME [--editor/-e EDITOR]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.editor")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--editor, -e` | - | Override auto-detection. Options: cursor, vscode, zed, nvim, vim, emacs, sublime, idea, pycharm, etc. |


<!-- OUTPUT:END -->

### `dev agent`

Start an AI coding agent in a dev environment.

```bash
agent-cli dev agent NAME [--agent/-a AGENT] [--agent-args ARGS] [--prompt/-p PROMPT] [--multiplexer/-m tmux] [--tmux-session SESSION]
```

**Options:**

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.agent")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--agent, -a` | - | Which agent: claude, codex, gemini, aider, copilot, cn, opencode, cursor-agent. Auto-detects if omitted |
| `--agent-args` | - | Extra CLI args for the agent. Example: --agent-args='--dangerously-skip-permissions' |
| `--prompt, -p` | - | Initial task for the agent. Saved to a unique file in .claude/ to avoid conflicts. Example: --prompt='Add unit tests for auth' |
| `--prompt-file, -P` | - | Read the agent prompt from a file instead of command line |
| `--multiplexer, -m` | - | Launch the agent in a specific multiplexer instead of the current terminal. Currently supported: tmux |
| `--tmux-session` | - | Reuse or create a specific tmux session for the agent. Implies --multiplexer tmux |
| `--hooks/--no-hooks` | `true` | Run built-in agent preparation (like Codex auto-trust) and configured pre-launch hooks before starting the agent |


<!-- OUTPUT:END -->

**Examples:**

```bash
# Start Claude in an existing worktree with a prompt
agent-cli dev agent my-feature --prompt "Continue implementing the user settings page"

# Start aider with a specific task
agent-cli dev agent my-feature -a aider --prompt "Add unit tests for the auth module"

# Start an agent in a detached tmux session and get its pane handle
agent-cli dev agent my-feature -a codex -m tmux --prompt-file continue-task.md

# Reuse or create a specific tmux session for a shared review batch
agent-cli dev agent my-feature -a codex --tmux-session review-batch --prompt-file continue-task.md
```

For automated use, prefer `--prompt-file` or `--prompt`. Without either, the agent starts interactively and may wait for input. `--tmux-session` implies `-m tmux`, and tmux session names cannot contain `.` or `:`.

### `dev run`

Run a command in a dev environment.

```bash
agent-cli dev run NAME COMMAND...
```

**Example:**

```bash
# Run tests in the my-feature worktree
agent-cli dev run my-feature npm test

# Run multiple commands
agent-cli dev run my-feature bash -c "npm install && npm test"
```

### `dev clean`

Clean up stale worktrees and empty directories.

```bash
agent-cli dev clean [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.clean")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--merged` | `false` | Also remove worktrees whose GitHub PRs are merged (requires gh CLI and auth) |
| `--no-commits` | `false` | Also remove worktrees with 0 commits ahead of default branch (abandoned branches) |
| `--dry-run, -n` | `false` | Preview what would be removed without actually removing |
| `--yes, -y` | `false` | Skip confirmation prompts |
| `--force, -f` | `false` | Force removal of worktrees with modified or untracked files |


<!-- OUTPUT:END -->

**Examples:**

```bash
# Prune stale worktrees and remove empty directories
agent-cli dev clean

# Also remove worktrees whose PRs have been merged
agent-cli dev clean --merged

# Remove worktrees with no commits (abandoned or manually merged branches)
agent-cli dev clean --no-commits

# Preview what would be cleaned
agent-cli dev clean --merged --dry-run
```

Like `dev rm`, `dev clean` also removes tagged tmux windows for worktrees it deletes and warns if tmux cleanup is only partial.

### `dev doctor`

Check system requirements and available integrations.

```bash
agent-cli dev doctor [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.doctor")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--json` | `false` | Output as JSON with git, editors, agents, terminals status |


<!-- OUTPUT:END -->

Shows available editors, AI agents, and terminals with their detection status.

### `dev install-skill`

Install Claude Code skill for parallel agent orchestration.

```bash
agent-cli dev install-skill [OPTIONS]
```

Installs a skill that teaches Claude Code how to use `agent-cli dev` to spawn parallel AI coding agents in isolated git worktrees. The skill is installed to `.claude/skills/agent-cli-dev/` in the current repository.

**Options:**

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.install-skill")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--force, -f` | `false` | Overwrite existing skill files if already installed |


<!-- OUTPUT:END -->

**Example:**

```bash
# Install the skill in your project
agent-cli dev install-skill

# Force reinstall if files already exist
agent-cli dev install-skill --force
```

Once installed, Claude Code can automatically use the skill when you ask to work on multiple features or parallelize development tasks.

**Alternative: Plugin Marketplace**

You can also install the skill globally via the Claude Code plugin marketplace:

```bash
claude plugin marketplace add basnijholt/agent-cli
claude plugin install agent-cli-dev@agent-cli
```

This installs the skill globally so it's available in all projects without needing to run `dev install-skill` in each one.

## Discovery Commands

### `dev agents`

List available AI coding agents.

```bash
agent-cli dev agents [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.agents")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--json` | `false` | Output as JSON with name, command, is_available, is_current, install_url |


<!-- OUTPUT:END -->

### `dev editors`

List available editors.

```bash
agent-cli dev editors [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.editors")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--json` | `false` | Output as JSON with name, command, is_available, is_current, install_url |


<!-- OUTPUT:END -->

### `dev terminals`

List available terminal multiplexers.

```bash
agent-cli dev terminals [OPTIONS]
```

<!-- CODE:START -->
<!-- from agent_cli.docs_gen import all_options_for_docs -->
<!-- print(all_options_for_docs("dev.terminals")) -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--json` | `false` | Output as JSON with name, is_available, is_current |


<!-- OUTPUT:END -->

## Supported Integrations

### AI Coding Agents

| Agent | Command | Detection | Prompt Support |
|-------|---------|-----------|----------------|
| Claude Code | `claude` | `CLAUDECODE=1` env var | `claude "prompt"` |
| OpenAI Codex | `codex` | Parent process detection | `codex "prompt"` |
| Google Gemini CLI | `gemini` | Parent process detection | `gemini -i "prompt"` |
| Aider | `aider` | Parent process detection | `aider --message "prompt"` |
| GitHub Copilot CLI | `copilot` | Parent process detection | `copilot --prompt "prompt"` |
| Continue Dev | `cn` | Parent process detection | — |
| OpenCode | `opencode` | `OPENCODE=1` env var | — |
| Cursor Agent | `cursor-agent` | `CURSOR_AGENT` env var | — |

### Editors

| Editor | Command | Notes |
|--------|---------|-------|
| Cursor | `cursor` | AI-first editor |
| VS Code | `code` | |
| Zed | `zed` | Fast, modern editor |
| Neovim | `nvim` | Uses `cd && nvim .` pattern |
| Vim | `vim` | Uses `cd && vim .` pattern |
| Nano | `nano` | Uses `cd && nano .` pattern |
| Emacs | `emacs` | Runs in background |
| Sublime Text | `subl` | |
| IntelliJ IDEA | `idea` | |
| PyCharm | `pycharm` | |
| WebStorm | `webstorm` | |
| GoLand | `goland` | |
| RustRover | `rustrover` | |

### Terminals

| Terminal | Detection | New Tab Command |
|----------|-----------|-----------------|
| tmux | `TMUX` env var | `tmux new-window -c <path>` |
| Zellij | `ZELLIJ` env var | `zellij action new-tab --cwd <path>` |
| Kitty | `KITTY_WINDOW_ID` | `kitten @ launch --type=tab` |
| iTerm2 | `ITERM_SESSION_ID` | AppleScript |
| Terminal.app | `TERM_PROGRAM=Apple_Terminal` | AppleScript + System Events * |
| Warp | `TERM_PROGRAM=WarpTerminal` | URI scheme + Launch Configurations |
| GNOME Terminal | `GNOME_TERMINAL_SERVICE` | `gnome-terminal --tab` |

\* Requires accessibility permissions in System Preferences > Privacy & Security > Accessibility.

## Configuration

Add defaults to your `~/.config/agent-cli/config.toml`.
If you use `agent-cli config init`, the generated template already includes a
commented-out starter block for `[dev]`, `[dev.agent_args]`, and
`[dev.agent_env.<agent>]` settings like these:

```toml
[dev]
# Default flags for 'dev new' command
editor = true          # Always open editor (-e)
start_agent = true     # Always start agent (--start-agent)
auto_trust = true      # Auto-trust supported agents before launch
direnv = true          # Always generate .envrc (--direnv)

# Worktree creation behavior
setup = true           # Run project setup (npm install, etc.)
copy_env = true        # Copy .env files from main repo
fetch = true           # Git fetch before creating

# Branch naming behavior when BRANCH argument is omitted
branch_name_mode = "ai"        # random | auto | ai
branch_name_agent = "claude"   # claude | codex | gemini (optional)
branch_name_timeout = 20.0     # seconds

# Which editor/agent to use when flags are enabled
default_editor = "cursor"
default_agent = "claude"

# Per-agent arguments (applied automatically when launching agents)
[dev.agent_args]
claude = ["--dangerously-skip-permissions"]
codex = ["--dangerously-bypass-approvals-and-sandbox"]

# Per-agent environment variables (applied when launching agents)
[dev.agent_env.claude]
CLAUDE_CODE_USE_VERTEX = "1"
ANTHROPIC_MODEL = "claude-opus-4-5"

# Optional pre-launch hooks (run from the worktree directory)
[dev.hooks]
pre_launch = ["~/.config/agent-cli/hooks/pre-launch.sh"]

# Optional per-agent pre-launch hooks
[dev.hooks.codex]
pre_launch = ["~/.config/agent-cli/hooks/codex-setup.sh"]
```

Or per-project in `agent-cli-config.toml`:

```toml
[dev]
editor = true
start_agent = true
direnv = true
default_editor = "zed"
default_agent = "aider"

[dev.agent_args]
claude = ["--dangerously-skip-permissions", "--model", "opus"]

[dev.agent_env.claude]
ANTHROPIC_MODEL = "claude-sonnet-4-20250514"

[dev.hooks]
pre_launch = ["./scripts/prepare-worktree.sh"]
```

With this configuration, running `agent-cli dev new` will automatically open the editor, start the agent, and set up direnv.

## Automatic Features

### Project Setup

When creating a new dev environment, automatic setup is performed based on detected project type:

| Project Type | Detection | Setup Command |
|--------------|-----------|---------------|
| Python (uv) | `pyproject.toml` + `uv.lock` | `uv sync --all-extras` |
| Python (unidep) | `requirements.yaml` or `[tool.unidep]` | `unidep install -e . -n <env>` * |
| Python (unidep monorepo) | `requirements.yaml` in subdirs | `unidep install-all -e -n <env>` * |
| Python (poetry) | `pyproject.toml` + `poetry.lock` | `poetry install` |
| Python (pip) | `requirements.txt` | `pip install -r requirements.txt` |
| Node.js (pnpm) | `pnpm-lock.yaml` | `pnpm install` |
| Node.js (yarn) | `yarn.lock` | `yarn install` |
| Node.js (npm) | `package-lock.json` | `npm install` |
| Rust | `Cargo.toml` | `cargo build` |
| Go | `go.mod` | `go mod download` |
| Ruby | `Gemfile` or `Gemfile.lock` | `bundle install` |
| Pixi | `pixi.toml` or `pixi.lock` | `pixi install` |

\* For unidep projects, if `conda-lock.yml` is present, `-f conda-lock.yml` is also added.

### Git Submodules

Git submodules are automatically initialized and updated when creating a new dev environment:

```bash
git submodule update --init --recursive
```

This ensures all submodule dependencies are available in the worktree.

### Git LFS

If the repository uses Git LFS (detected via `filter=lfs` in `.gitattributes`), LFS files are automatically pulled:

```bash
git lfs pull
```

This ensures large files tracked by LFS are available in the worktree.

### Environment Files

The following files are automatically copied to new dev environments:

- `.env`
- `.env.local`
- `.env.example`
- `.envrc`

Use `--no-copy-env` to skip this.

### Direnv Integration

With `--direnv`, a `.envrc` file is automatically generated based on the detected project type:

| Project Type | Generated .envrc Content |
|--------------|-------------------------|
| Nix (flake.nix) | `use flake` |
| Nix (shell.nix) | `use nix` |
| Python (uv) | `source .venv/bin/activate` |
| Python (unidep) | `micromamba activate <dirname>` (with conda fallback) |
| Python (poetry) | `source "$(poetry env info --path)/bin/activate"` |
| Python (pip/venv) | `source .venv/bin/activate` (or detected venv path) |
| Node.js (with .nvmrc) | `use node` |
| Go | `layout go` |
| Ruby | `layout ruby` |
| Pixi | `watch_file pixi.lock` + `eval "$(pixi shell-hook)"` |

Multiple directives can be combined. For example, a Python project with `shell.nix` will get:
```bash
use nix
source .venv/bin/activate
```

The generated `.envrc` is automatically trusted with `direnv allow`.

### Agent Launch

When launching an AI agent, the dev command automatically:

1. Detects if you're in tmux/zellij and opens a new tab there
2. With `-m tmux`, creates or reuses a detached tmux session even when you're not already inside tmux
3. Outside tmux, uses a deterministic repo-scoped tmux session by default for explicit tmux launches
4. Inside tmux, opens a new window in the current tmux session unless `--tmux-session <name>` is provided
5. Returns the tmux pane handle and an attach command for explicit tmux launches
6. Falls back to supported terminals (kitty, iTerm2)
7. Prints instructions if no terminal is detected

Before launching an agent, `agent-cli dev` can also run launch preparation:

- Built-in preparation for supported agents. Currently this means Codex auto-trust: when `[dev].auto_trust = true` (the default), `agent-cli` ensures the repository root is trusted in `~/.codex/config.toml` before launch.
- User-defined `pre_launch` hooks from `[dev.hooks]` and `[dev.hooks.<agent>]`. Global hooks run first, then agent-specific hooks.
- Hook config follows the same config source as the rest of `dev`, including `agent-cli dev --config path/to/config.toml ...`.
- Hooks run synchronously in the worktree directory and receive:
  - `AGENT_CLI_AGENT`
  - `AGENT_CLI_WORKTREE`
  - `AGENT_CLI_REPO_ROOT`
  - `AGENT_CLI_BRANCH`
  - `AGENT_CLI_NAME`
  - `AGENT_CLI_TASK_FILE`
  - `AGENT_CLI_PROMPT_FILE` (alias of `AGENT_CLI_TASK_FILE`)
- Hook commands are executed directly, not through a shell. For pipelines or more complex setup, point `pre_launch` at a script.
- Use `--no-hooks` to bypass both built-in preparation and configured pre-launch hooks for a single launch.

### Multi-agent Workflows

Use `dev agent -m tmux` when you want multiple agents on the same worktree instead of multiple worktrees:

```bash
# Create the worktree once. This is setup only; no agent starts yet.
agent-cli dev new review-auth --from HEAD

# Launch multiple reviewers into the same worktree
agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-security.md
agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-performance.md
agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-tests.md
```

This is useful for:
- Multiple reviewers on the same branch
- Parallel validation agents working on one codebase
- Headless orchestration from scripts or other assistants

Outside tmux, explicit tmux launches for the same repository are grouped into the same deterministic tmux session (`agent-cli-<repo>-<hash>`), which keeps related windows together across headless or scripted launches.

When already inside tmux, `-m tmux` opens a new window in the current session unless you pass `--tmux-session <name>`. That flag reuses or creates a specific tmux session instead. tmux session names cannot contain `.` or `:`.

For fully headless orchestration, combine `--prompt-file` with `-m tmux`:

```bash
for section in 1 2 3 4; do
  agent-cli dev new "validate-$section" --from HEAD --agent codex -m tmux \
    --prompt-file ".claude/validate-$section.md"
done
```

If multiple agents share one worktree, do not have them all write to `.claude/REPORT.md` because they will overwrite each other. Instead, assign unique report paths such as `.claude/REPORT-security-<run-id>.md` and `.claude/REPORT-tests-<run-id>.md`. If you rerun the same prompt repeatedly, use a timestamp or other run id so later runs do not replace earlier results. Each agent launch also gets its own `.claude/TASK-{timestamp}-{hex}.md` file, so prompt files no longer overwrite each other.

## Shell Integration

Add a function to quickly navigate to dev environments:

```bash
# ~/.bashrc or ~/.zshrc
dcd() {
    cd "$(agent-cli dev path "$1")"
}

# Usage: dcd my-feature
```

## Tips

- Use `agent-cli dev new` without arguments for quick experimentation
- Run `agent-cli dev doctor` to verify your setup
- Combine `-e --start-agent` to immediately start coding with AI assistance
- Use `--from` to branch from a specific tag or commit
