flake-update-20260505

name: using-git-worktrees description: Creates isolated git worktrees in XDG data directory for parallel development. USE WHEN starting feature work that needs isolation from current workspace OR before executing implementation plans OR working on multiple branches simultaneously OR need clean test environment. Creates worktrees in ~/.local/share/worktrees///.

UsingGitWorktrees

Create isolated git workspaces for parallel development using XDG data directory layout.

Overview

Git worktrees create isolated working directories that share the same repository, allowing:

  • Work on multiple branches simultaneously
  • Isolated test environments
  • Clean baseline for new features
  • No stashing or switching required

Core principle: All worktrees live in ~/.local/share/worktrees/ following XDG conventions, consistent with lazyworktree.

Default tool: Use lazyworktree when available (preferred). Fall back to raw git worktree commands only when lazyworktree is not installed.

Announce at start: “I’m using the UsingGitWorktrees skill to set up an isolated workspace.”

XDG Data Layout

All worktrees are organized under ~/.local/share/worktrees/:

~/.local/share/worktrees/
├── vdemeester/
│   ├── home/
│   │   ├── main-lively-panda/
│   │   └── sakhalin-upgrade-bold-oak/
│   └── tektoncd-plumbing/
│       └── terraform-persistent-state/
└── tektoncd/
    └── pipeline/
        └── feature-new-resolver-calm-quartz/

Structure: ~/.local/share/worktrees/<org>/<repo>/<name>/

Note: lazyworktree auto-generates names like <branch>-<adjective>-<noun>. The org/repo is resolved automatically from the git remote.

Creating Worktrees with lazyworktree (Preferred)

Check availability

command -v lazyworktree >/dev/null 2>&1

Create a worktree

# Non-interactive creation — prints the worktree path to stdout
WORKTREE_PATH=$(lazyworktree create --from-branch <branch> --silent)
cd "$WORKTREE_PATH"

Examples:

# From an existing branch
WORKTREE_PATH=$(lazyworktree create --from-branch main --silent)
# → ~/.local/share/worktrees/public/home/main-lively-panda

# From a feature branch
WORKTREE_PATH=$(lazyworktree create --from-branch feature/sakhalin-upgrade --silent)
# → ~/.local/share/worktrees/public/home/feature-sakhalin-upgrade-bold-oak

# From a PR
WORKTREE_PATH=$(lazyworktree create --from-pr 42 --silent)

# Carry uncommitted changes to the new worktree
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --with-change --silent)

# With post-create setup command (runs inside new worktree)
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --silent --exec "go mod download")

Run commands in a worktree

# Execute a command inside a worktree without cd-ing
lazyworktree exec -w <worktree-name> "go test ./..."
lazyworktree exec -w <worktree-name> "make build"

List worktrees

# JSON output (richest — includes dirty, ahead/behind, last_active)
lazyworktree list --json

# Paths only (for scripting)
lazyworktree list --pristine

# Standard git output
git worktree list

# Interactive TUI
lazyworktree

Delete a worktree

# Removes worktree and cleans up the branch
lazyworktree delete --silent <worktree-path>

Rename a worktree

# From inside the worktree
lazyworktree rename <new-name> --silent

# Explicit worktree
lazyworktree rename <worktree-path> <new-name> --silent

Fallback: Raw Git Commands

Only use when lazyworktree is not available.

Determining Org and Repo

Extract organization and repository name from git remote:

REMOTE_URL=$(git remote get-url origin)

if [[ "$REMOTE_URL" =~ git@[^:]+:([^/]+)/([^/.]+) ]]; then
    ORG="${BASH_REMATCH[1]}"
    REPO="${BASH_REMATCH[2]}"
elif [[ "$REMOTE_URL" =~ https://[^/]+/([^/]+)/([^/.]+) ]]; then
    ORG="${BASH_REMATCH[1]}"
    REPO="${BASH_REMATCH[2]}"
fi
REPO="${REPO%.git}"

Create worktree manually

WORKTREE_BASE="$HOME/.local/share/worktrees"
BRANCH_NAME="feature/user-authentication"
BRANCH_PATH=$(echo "$BRANCH_NAME" | tr '/' '-')
WORKTREE_PATH="$WORKTREE_BASE/$ORG/$REPO/$BRANCH_PATH"

mkdir -p "$WORKTREE_BASE/$ORG/$REPO"
git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME"
cd "$WORKTREE_PATH"

Remove worktree manually

git worktree remove ~/.local/share/worktrees/<org>/<repo>/<name>
# Or force:
git worktree remove --force ~/.local/share/worktrees/<org>/<repo>/<name>

After Creation: Setup and Verify

Use --exec on create or exec -w after creation to run setup and verification.

Auto-Detect and Run Project Setup

Preferred: Use --exec during creation:

# Go
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --silent --exec "go mod download")

# Node.js
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --silent --exec "npm install")

# Python
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --silent --exec "uv sync")

# NixOS (home repository)
WORKTREE_PATH=$(lazyworktree create --from-branch feature-x --silent --exec "make dry-build")

Or after creation with exec:

lazyworktree exec -w <worktree-name> "go mod download"

Verify Clean Baseline

Run tests without switching directories:

lazyworktree exec -w <worktree-name> "go test ./..."
lazyworktree exec -w <worktree-name> "cargo test"
lazyworktree exec -w <worktree-name> "pytest"
lazyworktree exec -w <worktree-name> "npm test"
lazyworktree exec -w <worktree-name> "make build"

If tests fail:

  • Report failures clearly
  • Ask whether to proceed or investigate
  • Document known issues

If tests pass:

  • Report success, show test count and duration
  • Confirm ready for work

Report Worktree Ready

Worktree created successfully

Location: ~/.local/share/worktrees/myorg/myrepo/feature-auth-calm-willow
Branch: feature/auth
Tests: ✓ 47 passing (2.3s)

Ready to implement feature

Managing Worktrees

List All Worktrees

git worktree list
# Direct path
cd ~/.local/share/worktrees/myorg/myrepo/<name>

# Interactive selection via lazyworktree TUI
lazyworktree

Prune Deleted Worktrees

git worktree prune

Quick Reference

Situation lazyworktree Raw git
Create lazyworktree create --from-branch <b> --silent git worktree add <path> -b <b>
Create + setup lazyworktree create --from-branch <b> --silent --exec "cmd" N/A
Create from PR lazyworktree create --from-pr <n> --silent N/A
Exec in worktree lazyworktree exec -w <name> "cmd" cd <path> && cmd
List (JSON) lazyworktree list --json N/A
List (paths) lazyworktree list --pristine git worktree list
Delete lazyworktree delete --silent <path> git worktree remove <path>
Rename lazyworktree rename <new-name> --silent N/A
Navigate lazyworktree (TUI) cd <path>
Prune git worktree prune git worktree prune

Common Patterns for the Home Repository

Building a NixOS Configuration

cd ~/src/home
WORKTREE_PATH=$(lazyworktree create --from-branch feature/sakhalin-upgrade --silent)
cd "$WORKTREE_PATH"
make host/sakhalin/build

Working on Multiple Hosts

cd ~/src/home
WT1=$(lazyworktree create --from-branch feature/rhea-jellyfin --silent)
WT2=$(lazyworktree create --from-branch feature/aion-audio --silent)

cd "$WT1" && make host/rhea/build
cd "$WT2" && make host/aion/build

Working on Tekton Pipeline

cd ~/src/tektoncd/pipeline/main
WORKTREE_PATH=$(lazyworktree create --from-branch feature/new-resolver --silent)
cd "$WORKTREE_PATH"
go test ./...

Integration with Pi Extension

The pi git extension (~/.pi/agent/extensions/git/) provides:

  • Tool: git_worktree — AI can create/remove/list/exec in worktrees programmatically
    • action: "list" — lists worktrees with dirty/ahead/behind/last_active + notes from lazyworktree
    • action: "create" + exec: "cmd" — creates worktree and runs setup command
    • action: "exec" + branch: "<name>" + exec: "cmd" — runs command inside a worktree
    • action: "remove" — removes worktree (lazyworktree also cleans up the branch)
    • action: "note" — read/write worktree notes (see below)
  • Commands: /worktree or /wt — interactive worktree management

Both the tool and commands use lazyworktree when available, falling back to raw git.

Worktree Notes

Worktree notes are short descriptions attached to worktrees via lazyworktree note. They serve as working memory — ephemeral context tied to a branch’s lifecycle — complementing the durable save_session/save_learning/save_plan tools.

How Notes Flow

Moment Direction What happens
Session starts in a worktree lazyworktree → AI Note is auto-injected as context on first turn (if a note exists)
AI browses worktrees lazyworktree → AI git_worktree list includes first line of each note
AI saves a session AI → lazyworktree save_session_to_history auto-updates the worktree note with session date + description
Worktree is deleted Note dies naturally; session/learning/plan persists in ~/.local/share/ai/

Reading Notes (AI tool)

# Read current worktree's note
git_worktree({ action: "note" })

# Read a specific worktree's note by name
git_worktree({ action: "note", branch: "bump-knative-pkg-and-k8s" })

Writing Notes (AI tool)

# Set a worktree note
git_worktree({ action: "note", branch: "my-worktree", exec: "Working on auth refactor\nBlocked on upstream PR #123" })

Auto-Update on save_session

When save_session_to_history is called, the extension automatically appends/updates a line in the worktree note:

🤖 pi (2026-03-17): bump-knative-pkg-k8s-035-tekton-pipeline

This preserves any manually written notes and only updates the AI session line. So when you open lazyworktree later, you can see at a glance what the AI last worked on in each worktree.

Best Practices for Notes

  • Keep notes short — they appear in the lazyworktree TUI, one-liners are best
  • Use notes for current state — “3 tests failing, waiting for upstream fix”
  • Use save_session for full story — the session summary captures the complete narrative
  • Write a note after creating a worktree — helps future AI sessions (and you) understand the worktree’s purpose

CLI Usage (for reference)

# Read
lazyworktree note show <worktree-name>

# Write (from stdin)
echo "Working on feature X" | lazyworktree note edit --input - <worktree-name>

# Write (opens editor)
lazyworktree note edit <worktree-name>

Integration with Other Skills

Before UsingGitWorktrees:

  • Use Brainstorming to clarify what feature needs isolation
  • Ensure design is validated before creating worktree

After UsingGitWorktrees:

  • Use WritingPlans to create implementation plan
  • Use TestDrivenDevelopment for implementation in worktree
  • Use Git skill for branching and commit workflows

Cleanup after work:

# From main repo, merge work back
git merge feature/user-authentication

# Remove worktree (lazyworktree also deletes the branch)
lazyworktree delete --silent ~/.local/share/worktrees/myorg/myrepo/<name>

# Or with raw git (branch cleanup is manual)
git worktree remove ~/.local/share/worktrees/myorg/myrepo/<name>
git branch -d feature/user-authentication

Common Mistakes

❌ Creating Worktrees in Random Locations

Problem: Worktrees scattered across filesystem Fix: Always use lazyworktree or ~/.local/share/worktrees/<org>/<repo>/

❌ Using raw git when lazyworktree is available

Problem: Inconsistent naming, no org/repo detection via gh/glab Fix: Default to lazyworktree create --from-branch <b> --silent

❌ Proceeding with Failing Tests

Problem: Can’t distinguish new bugs from pre-existing issues Fix: Report failures, get explicit permission to proceed

❌ Forgetting to Remove Old Worktrees

Problem: Disk space waste, confusion about active work Fix: Regularly run git worktree list and remove completed work

❌ Committing from Wrong Worktree

Problem: Changes go to wrong branch Fix: Always verify current branch before committing: git branch --show-current

Red Flags

Never:

  • Create worktrees outside ~/.local/share/worktrees/
  • Skip org/repo structure in path
  • Proceed with failing tests without explicit permission
  • Leave old worktrees around indefinitely
  • Commit to wrong branch (verify with git branch --show-current)

Always:

  • Prefer lazyworktree over raw git commands
  • Use --silent flag for non-interactive scripting
  • Capture the output path: WORKTREE_PATH=$(lazyworktree create ...)
  • Auto-detect and run project setup
  • Verify clean test baseline
  • Report clear status when worktree is ready
  • Clean up worktrees when work is merged