Worktree workflows
Git projects always use linked worktrees for additional workspaces; jj projects use native workspaces. This guide assumes shell integration is installed. Concepts and configuration are covered in Worktrees.
The daily flow
Section titled “The daily flow”# Start a new feature — worktree + isolated services + hooks, then auto-cddevflow switch -c feature/auth# → Created worktree for 'feature/auth' at ../my-project.feature_auth_fc659bd73585# → service workspace cloned from main# → Changed directory to: ../my-project.feature_auth_fc659bd73585
npm run migrate && npm test # work normally
# A PR review comes in — keep everything running, open a second worktreedevflow switch -c review/pr-417 --from main
# Jump back — instant, nothing was stopped or rebuiltdevflow switch feature/auth
# Forgot a name? Fuzzy picker:devflow switchEach worktree keeps its own build artifacts, env files, and database. Nothing is stashed, paused, or reset when you move between them.
Useful switch flags
Section titled “Useful switch flags”devflow switch -c feature/x --from develop # explicit code + data parentdevflow switch feature/x -x "npm run dev" # run a command in the worktree after switchingdevflow switch feature/x -x "npm run dev" -d # …in a detached tmux/zellij sessiondevflow switch feature/x -o # open an interactive multiplexer sessiondevflow switch -c tmp/spike --no-services # VCS only, skip service branchingdevflow switch feature/x --no-processes # skip process auto-startdevflow switch -c big --no-respect-gitignore # also copy gitignored entries this timedevflow switch feature/x --dry-run # print the plan (worktree path, services, processes, hooks)Multiplexer sessions auto-detect tmux, then zellij; configure a preference or a fully custom launcher:
execute: multiplexer: zellij # or "tmux" # detach_command: "screen -dmS {session} bash -c {cmd}" # {session} {dir} {cmd}To open a session automatically on every new workspace: devflow hook install multiplexer-session.
Seeing your worktrees
Section titled “Seeing your worktrees”devflow list # parent tree with paths, services, processes, and healthdevflow status # current workspace detailsdevflow --json list returns one versioned tree document with roots and workspace nodes. Each node includes its raw name, backend service_key (collision-safe for new workspaces), immutable parent, children, worktree_path, and health; agents use the path as their workdir.
Adopting worktrees you made by hand
Section titled “Adopting worktrees you made by hand”git worktree add ../myapp.hotfix hotfix is fully supported: the post-checkout hook detects the new worktree and sets it up (copies files, creates service workspaces, runs hooks). Manually:
cd ../myapp.hotfixdevflow worktree-setupFor VCS refs created outside devflow (without a worktree yet), devflow switch <name> materializes the worktree. devflow link <name> adopts an already materialized VCS workspace and can provision services.
Cleaning up
Section titled “Cleaning up”When a workspace is no longer needed, remove its worktree, VCS ref, and associated service instances:
devflow switch --template # leave the workspace being removeddevflow remove feature/auth # preflight, then hooks → processes → services → worktree/refdevflow remove feature/auth --force # explicitly accept dirty/partial-cleanup riskdevflow remove feature/auth --keep-servicesThe default and current workspaces are never removable, even with --force.
Pruning stale worktrees
Section titled “Pruning stale worktrees”If a worktree directory was deleted by hand, Git metadata lingers. devflow auto-prunes stale entries when recreating a workspace of the same name; the desktop GUI has a Prune worktrees button for bulk cleanup, and git worktree prune always works.
Troubleshooting
Section titled “Troubleshooting”- “Failed to create worktree” — usually a leftover directory at the target path or stale VCS metadata. Service keys are collision-safe, so separator/case variants do not share a generated path.
- Switch didn’t
cd— shell integration not installed in this shell; see Shell integration. devflow prints the path either way. - Copy flags seemed ignored — overrides like
--no-respect-gitignoreonly apply when the worktree is created; switching to an existing worktree reuses it as-is. .env.localmissing in a new worktree — add it toworktree.copy_files, or generate it with apost-create/post-switchwrite-env hook (preferred: values stay correct per workspace).