Skip to content

Configurable worktree include: bring git-ignored files in, carry untracked files back on merge #231

Description

@FourWindff

Background & motivation

A git worktree only contains tracked files, so ignored files never appear in a new worktree. Under AI-driven workflows this causes two pain points:

  1. Broken context: AI workflows often generate documents in the repo root (plans, design notes, context files). We usually don't want to commit them, so we ignore them via .gitignore — but agents working inside a worktree need exactly those documents to keep context consistent.
  2. Lost output: untracked files an agent newly creates inside a worktree (e.g. docs/xxx.md) are permanently lost when the task is merged and the worktree is removed.

Today parallel-code works around this with a hardcoded allowlist (SYMLINK_CANDIDATES, only 8 entries such as .env and node_modules) that gets symlinked into each worktree. It cannot cover user-defined ignored files.

Proposal

Make worktree creation and merge behavior configurable per task:

  1. On task creation: let the user check which ignored files/directories to bring into the worktree (e.g. .env, docs/), and choose how each entry is brought in:
    • Symlink: shared with the main checkout (good for large directories that don't need isolation, like node_modules);
    • Copy: an independent copy inside the worktree (good for documents the agent may modify, like .env).
  2. On task merge: optionally carry untracked files newly created inside the worktree (e.g. docs/xxx.md) back into the project root, so output isn't lost when the worktree is removed.

Relationship to Claude Code's .worktreeinclude

Claude Code's .worktreeinclude solves a similar problem, but it only copies ignored files one way, at creation time; they are deleted together with the worktree on cleanup and never carried back to the main checkout. This proposal extends that idea with:

  • a per-entry choice of symlink vs. copy (symlink avoids the copy cost of large directories like node_modules; copy guarantees isolation);
  • carrying untracked files created in the worktree back to the project root on merge, preventing output loss.

Implementation sketch

  • Enumeration: git ls-files --others --ignored --exclude-standard --directory, collapsed to top-level entries of the repo root. A single command covers all ignore mechanisms (.gitignore, nested gitignores, .git/info/exclude, global excludesFile) — no need to parse gitignore syntax ourselves. .worktrees/ and .git must be force-excluded (to avoid linking the worktree directory into itself).
  • Creation: symlink or copy each checked entry according to its config.
  • Merge: in mergeTask(), before removeWorktree, copy the entries marked as "carry back" from the worktree to the project root.
  • This feature can replace the existing hardcoded SYMLINK_CANDIDATES allowlist.

Open questions

  • Where should the configuration live: a .worktreeinclude-style file inside the repo (shareable via git, compatible with Claude Code conventions) vs. an in-app per-project setting?
  • On carry-back in copy mode, if the same file was also modified in the main checkout, how should conflicts be handled (overwrite / skip with a warning / keep both)?
  • Default selection policy (large ignored directories like dist/ should presumably not be copied by default?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions