Skip to content

Latest commit

 

History

History
818 lines (591 loc) · 28.5 KB

File metadata and controls

818 lines (591 loc) · 28.5 KB
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) but with many more QoL features.

Quick Start

# 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.

agent-cli dev new [BRANCH] [OPTIONS]

Arguments:

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

Options:

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

Examples:

# 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.

agent-cli dev list [OPTIONS]

Options

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

dev status

Show status of all dev environments with git status information.

agent-cli dev status [OPTIONS]

Options:

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 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:

# 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).

agent-cli dev rm NAME [OPTIONS]

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

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).

agent-cli dev path NAME

Example:

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

dev editor

Open a dev environment in an editor.

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

Options

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

dev agent

Start an AI coding agent in a dev environment.

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

Options:

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

Examples:

# 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.

agent-cli dev run NAME COMMAND...

Example:

# 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.

agent-cli dev clean [OPTIONS]

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

Examples:

# 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.

agent-cli dev doctor [OPTIONS]

Options

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

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

dev install-skill

Install Claude Code skill for parallel agent orchestration.

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:

Options

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

Example:

# 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:

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.

agent-cli dev agents [OPTIONS]

Options

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

dev editors

List available editors.

agent-cli dev editors [OPTIONS]

Options

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

dev terminals

List available terminal multiplexers.

agent-cli dev terminals [OPTIONS]

Options

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

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:

[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:

[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:

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:

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:

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:

# 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:

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:

# ~/.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