From 988f5027786b763db60fff761efce7408f0413ab Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Thu, 26 Mar 2026 10:51:12 -0500 Subject: [PATCH 1/4] Add --worktree=create: mode to auto-create worktrees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows `yolo --worktree=create:fix-issue-99` to create a git worktree as a sibling directory, cd into it, and launch with bind mode — keeping the main working tree untouched while an agent works on an issue. Co-Authored-By: Claude Opus 4.6 (1M context) --- bin/yolo | 22 ++++++++++++++++++++-- tests/yolo.bats | 12 ++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/bin/yolo b/bin/yolo index f4fe95a..abb7c70 100755 --- a/bin/yolo +++ b/bin/yolo @@ -210,9 +210,9 @@ while [ $# -gt 0 ]; do --worktree=*) WORKTREE_MODE="${1#--worktree=}" # Validate worktree mode - if [[ ! "$WORKTREE_MODE" =~ ^(ask|bind|skip|error)$ ]]; then + if [[ ! "$WORKTREE_MODE" =~ ^(ask|bind|skip|error|create(:.+)?)$ ]]; then echo "Error: Invalid --worktree value: $WORKTREE_MODE" >&2 - echo "Valid values are: ask, bind, skip, error" >&2 + echo "Valid values are: ask, bind, skip, error, create:" >&2 exit 1 fi shift @@ -342,6 +342,24 @@ CLAUDE_HOME_DIR="$HOME/.claude" # must exist but might not if first start on that box mkdir -p "$CLAUDE_HOME_DIR" +# Handle --worktree=create:: create a new worktree and cd into it +if [[ "$WORKTREE_MODE" == "create" ]]; then + echo "Error: --worktree=create requires a branch name, e.g. --worktree=create:fix-issue-99" >&2 + exit 1 +elif [[ "$WORKTREE_MODE" =~ ^create:(.+)$ ]]; then + create_branch="${BASH_REMATCH[1]}" + worktree_dir="$(dirname "$(pwd)")/$create_branch" + + echo "Creating worktree at $worktree_dir (branch: $create_branch)..." >&2 + git worktree add "$worktree_dir" -b "$create_branch" || exit 1 + cd "$worktree_dir" || exit 1 + + # Regenerate container name for the new directory + name=$( echo "$PWD-$$" | sed -e "s,^$HOME/,,g" -e "s,[^a-zA-Z0-9_.-],_,g" -e "s,^[._]*,," ) + + WORKTREE_MODE="bind" +fi + # Detect if we're in a git worktree and find the original repo WORKTREE_MOUNTS=() gitdir_path="" diff --git a/tests/yolo.bats b/tests/yolo.bats index b95964b..b47c470 100644 --- a/tests/yolo.bats +++ b/tests/yolo.bats @@ -79,6 +79,18 @@ EOF assert_output --partial "Invalid --worktree value" } +@test "--worktree=create: bare create exits with error" { + run_yolo --worktree=create + assert_failure + assert_output --partial "requires a branch name" +} + +@test "--worktree=create:branch: passes validation" { + run_yolo --worktree=create:test-branch + # Will fail at git worktree add (not a real repo), but should NOT fail validation + refute_output --partial "Invalid --worktree value" +} + # ── Separator (--) and argument routing ─────────────────────────── @test "separator: args after -- become claude container args" { From 6b89225dae1320065f535135a0fcdd9065016ce9 Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Thu, 26 Mar 2026 10:53:31 -0500 Subject: [PATCH 2/4] Update docs for --worktree=create: mode Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 4 ++++ bin/yolo | 3 ++- config.example | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c88cb3..cf97555 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ When running in a git worktree, `yolo` can detect and optionally bind mount the - `--worktree=bind`: Automatically bind mounts the original repo - `--worktree=skip`: Skip bind mounting and continue normally - `--worktree=error`: Exit with error if running in a worktree +- `--worktree=create:`: Create a new worktree and branch, then launch with bind mode ```bash # Prompt for bind mount decision (default) @@ -50,6 +51,9 @@ yolo --worktree=skip # Disallow running in worktrees yolo --worktree=error + +# Create an isolated worktree for an agent to work in +yolo --worktree=create:fix-issue-99 ``` **Security note**: Bind mounting the original repo exposes more files and allows modifications. The prompt helps prevent unintended access. diff --git a/bin/yolo b/bin/yolo index abb7c70..765ab61 100755 --- a/bin/yolo +++ b/bin/yolo @@ -12,7 +12,8 @@ OPTIONS: --anonymized-paths Use anonymized paths (/claude, /workspace) instead of preserving host paths --entrypoint=CMD Override the container entrypoint (default: claude) - --worktree=MODE Git worktree handling: ask, bind, skip, error + --worktree=MODE Git worktree handling: ask, bind, skip, error, + create: (default: ask) --nvidia Enable NVIDIA GPU passthrough via CDI Requires nvidia-container-toolkit on host diff --git a/config.example b/config.example index 8810e09..279a042 100644 --- a/config.example +++ b/config.example @@ -67,7 +67,7 @@ YOLO_CLAUDE_ARGS=( # Enable NVIDIA GPU passthrough by default (requires nvidia-container-toolkit) # USE_NVIDIA=0 -# Git worktree handling mode: ask (default), bind, skip, or error +# Git worktree handling mode: ask (default), bind, skip, error, or create: # WORKTREE_MODE="ask" # ============================================================================ From dd3d8b30d4a59be92b5ff510ff5192964e27b9bc Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Sat, 4 Apr 2026 15:46:05 -0500 Subject: [PATCH 3/4] Spec --create-worktree as separate flag with WORKTREE_DIR config Redesign worktree creation per PR #57 review feedback: - Separate --create-worktree=BRANCH from --worktree=MODE (orthogonal) - Support base:branch syntax for specifying base ref - Resume existing worktrees if directory exists - Add WORKTREE_DIR config (default .git/my-worktrees, relative paths only) - Add CLAUDE.md formatting rule for human-readable tables Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 5 +++++ SPEC.md | 58 +++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 885085b..4e97e62 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,3 +10,8 @@ The spec and tests must be kept in sync with the code. ## Branching `main` is the primary branch. `enhs` is used for enhancement batches. + +## Formatting + +Markdown tables must be human-readable in a plain text editor — pad columns +with spaces so they align evenly. diff --git a/SPEC.md b/SPEC.md index 5d881c8..705fff5 100644 --- a/SPEC.md +++ b/SPEC.md @@ -30,16 +30,17 @@ claude. If no `--` is present, all positional arguments go to claude. ### Flags -| Flag | Default | Description | -|----------------------|----------|--------------------------------------------------------------| -| `-h`, `--help` | — | Show help and exit | -| `--anonymized-paths` | off | Use `/claude` and `/workspace` instead of host paths | -| `--entrypoint=CMD` | `claude` | Override container entrypoint | -| `--entrypoint CMD` | `claude` | Same, space-separated form | -| `--worktree=MODE` | `ask` | Git worktree handling: `ask`, `bind`, `skip`, `error` | -| `--nvidia` | off | Enable NVIDIA GPU passthrough via CDI | -| `--no-config` | off | Ignore all configuration files | -| `--install-config` | — | Create or display `.git/yolo/config` template, then exit | +| Flag | Default | Description | +|------------------------------|----------|----------------------------------------------------------| +| `-h`, `--help` | — | Show help and exit | +| `--anonymized-paths` | off | Use `/claude` and `/workspace` instead of host paths | +| `--entrypoint=CMD` | `claude` | Override container entrypoint | +| `--entrypoint CMD` | `claude` | Same, space-separated form | +| `--worktree=MODE` | `ask` | Git worktree handling: `ask`, `bind`, `skip`, `error` | +| `--create-worktree=BRANCH` | — | Create or resume a worktree (see §5) | +| `--nvidia` | off | Enable NVIDIA GPU passthrough via CDI | +| `--no-config` | off | Ignore all configuration files | +| `--install-config` | — | Create or display `.git/yolo/config` template, then exit | ### Argument Routing @@ -80,11 +81,12 @@ User-wide and project arrays are concatenated (user-wide first). #### Scalars (project overrides user-wide; CLI overrides both) -| Key | Type | Default | Description | -|------------------------|----------|---------|--------------------------------| -| `USE_ANONYMIZED_PATHS` | `0\|1` | `0` | Use anonymized container paths | -| `USE_NVIDIA` | `0\|1` | `0` | Enable NVIDIA GPU passthrough | -| `WORKTREE_MODE` | `string` | `ask` | Git worktree handling mode | +| Key | Type | Default | Description | +|------------------------|----------|---------------------|--------------------------------------------| +| `USE_ANONYMIZED_PATHS` | `0\|1` | `0` | Use anonymized container paths | +| `USE_NVIDIA` | `0\|1` | `0` | Enable NVIDIA GPU passthrough | +| `WORKTREE_MODE` | `string` | `ask` | Git worktree handling mode | +| `WORKTREE_DIR` | `string` | `.git/my-worktrees` | Worktree directory (relative to repo root) | ### Loading Order @@ -176,6 +178,32 @@ All projects appear at `/workspace`, enabling cross-project session context. When mounted, the original repo is bind-mounted at its host path with `:z`. +### Creation (`--create-worktree`) + +Syntax: `--create-worktree=` or `--create-worktree=:`. + +| Form | Base ref | New branch | +|-------------------|----------|--------------| +| `feature-x` | HEAD | `feature-x` | +| `main:feature-x` | `main` | `feature-x` | + +Bare `--create-worktree` (no value) is an error. + +#### Behavior + +1. If `WORKTREE_DIR/` exists on disk, `cd` into it (resume). +2. Otherwise, create via `git worktree add WORKTREE_DIR/ -b []`. +3. If `` exists as a git branch but not as a worktree, exit with error. +4. After `cd`, normal worktree detection and `--worktree` mode handling applies. + +### Worktree Directory + +| Key | Default | Description | +|----------------|---------------------|------------------------------------------| +| `WORKTREE_DIR` | `.git/my-worktrees` | Worktree location, relative to repo root | + +Only relative paths are supported. + --- ## 6. Container Naming From 96896b7306d6602f8df140c8ce7515f6988ee8c4 Mon Sep 17 00:00:00 2001 From: Austin Macdonald Date: Sun, 5 Apr 2026 10:02:48 -0500 Subject: [PATCH 4/4] Trigger CI for PR-scout