claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Cannot work with git worktrees due to directory restriction

Open aewing opened this issue 6 months ago • 8 comments

Description

When working with git worktrees for feature development, Claude Code cannot navigate to worktree directories that are siblings to the main repository. This blocks a common development workflow.

Steps to Reproduce

  1. Have a main repository at /path/to/project
  2. Create git worktrees in /path/to/project-worktrees/
  3. Start Claude Code in the main repository
  4. Try to navigate to worktree: cd ../project-worktrees/feature-branch
  5. Get error: "For security, Claude Code may only change directories to child directories of the allowed working directories"

Expected Behavior

Should be able to work with git worktrees, which are a standard git feature for isolated development.

Actual Behavior

Cannot navigate to worktree directories, making it impossible to use Claude Code with git worktrees.

Workarounds Attempted

  • Adding directories via /add-dir slash command - directories are added but navigation still blocked
  • Adding "../", "../project-worktrees" to ".claude/settings.json" and "./claude/settings.local.json"
  • Starting from parent directory - not practical for project-specific work

Impact

This prevents using Claude Code for feature development workflows that rely on git worktrees for isolation. Worktrees are essential for:

  • Working on multiple features simultaneously
  • Keeping main branch clean
  • Testing changes in isolation

Related Issues

  • #1628 (general directory change request)

Suggested Solution

Either:

  1. Allow navigation to sibling directories that have been explicitly added via /add-dir
  2. Add specific support for git worktree directories
  3. Provide an explicit /cd command as suggested in #1628

aewing avatar Jul 02 '25 02:07 aewing

Additional Context: svelte-check Integration Issue

This limitation is particularly problematic when using TypeScript validation tools like svelte-check. The issue:

  1. svelte-check runs from main repository and detects changes in worktree directories
  2. Cannot configure svelte-check to ignore worktrees unless they're outside the main repo
  3. TypeScript errors from worktrees pollute main repo validation making it impossible to maintain clean TypeScript validation

aewing avatar Jul 02 '25 02:07 aewing

Technical Analysis & Root Cause

I've reverse-engineered the cd protection implementation from the compiled CLI and identified the exact root cause and solution.

Code Location & Implementation

The issue is in the cd validation logic around line 1578 in the compiled CLI. Here's what I found:

Path Validation Function (decompiled as isChildDirectory):

function isChildDirectory(targetPath, allowedPath) {
    let normalizedTarget = normalizePath(targetPath);
    let normalizedAllowed = normalizePath(allowedPath);
    if (\!normalizedTarget.startsWith(normalizedAllowed)) return false;
    let nextChar = normalizedTarget[normalizedAllowed.length];
    if (nextChar === undefined || nextChar === PATH_SEPARATOR) return true;
    return false;
}

Working Directories Function (decompiled as getAllowedDirs):

function getAllowedDirs(permissionContext) {
    return new Set([getCurrentWorkingDir(), ...permissionContext.additionalWorkingDirectories]);
}

Permission Check Function (decompiled as checkDirectoryPermission):

function checkDirectoryPermission(targetPath, permissionContext) {
    return Array.from(getAllowedDirs(permissionContext)).some(allowedDir => 
        isChildDirectory(targetPath, allowedDir)
    );
}

CD Command Validation (decompiled as validateCdCommand):

function validateCdCommand(command, currentDir, rootDir, permissionContext) {
    let subcommands = parseCommand(command.command);
    for (let cmd of subcommands) {
        let [baseCmd, ...args] = cmd.split(" ");
        if (baseCmd === "cd" && args.length > 0) {
            let targetDir = args.join(" ").replace(/^['"]|['"]$/g, "");
            let resolvedPath = isAbsolute(targetDir) ? targetDir : resolve(currentDir, targetDir);
            if (\!checkDirectoryPermission(resolvedPath, permissionContext)) {
                return {
                    behavior: "ask",
                    message: `cd to '${resolvedPath}' was blocked. For security, Claude Code may only change directories to child directories of the allowed working directories for this session (including '${rootDir}').`
                };
            }
        }
    }
    return { behavior: "allow", updatedInput: command };
}

The Bug

The isChildDirectory function only allows navigation to subdirectories of allowed working directories. However, directories added via /add-dir or additionalDirectories should be directly accessible, not just their children.

Current Logic: targetPath must be a child of an allowed directory
Needed Logic: targetPath can be a child of an allowed directory OR exactly match an allowed directory

The Fix

The checkDirectoryPermission function needs to be updated to allow both:

  1. Child directories of allowed working directories (current behavior)
  2. Direct navigation to additional working directories (missing behavior)

Proposed Fix:

function checkDirectoryPermission(targetPath, permissionContext) {
    let allowedDirs = getAllowedDirs(permissionContext);
    
    // Allow direct navigation to any additional working directory
    if (allowedDirs.has(normalizePath(targetPath))) {
        return true;
    }
    
    // Allow navigation to child directories (existing behavior)
    return Array.from(allowedDirs).some(allowedDir => 
        isChildDirectory(targetPath, allowedDir)
    );
}

Verification

This analysis is based on decompiled code from the CLI binary. The variable names are logical replacements for minified names, but the logic flow is exactly as implemented.

The fix would allow cd to work properly with:

  • Git worktree directories added via /add-dir
  • Directories specified in additionalDirectories configuration
  • CLI --add-dir argument directories

While maintaining security by still restricting access to child directories of the current working directory only.

aewing avatar Jul 02 '25 03:07 aewing

For the record this was all written by Claude, so I can't speak for the validity of the decompiled code or analysis (it seems flawed to me, because I do have a parent of a directory I'm trying to CD to in allowedDirectories). This is a very serious problem for me right now. I am also working on proposing a solution for the much larger problem in svelte-check, but it would be nice if these configuration options worked as expected within claude-code too.

aewing avatar Jul 02 '25 03:07 aewing

I have the same issue - no matter how I try to define additionalDirectories, my orchestrator Claude Code instance (in /repos/main-worktree) cannot access the worktree directories in /worktrees/.

sevagh avatar Aug 12 '25 11:08 sevagh

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/2180

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

github-actions[bot] avatar Aug 16 '25 04:08 github-actions[bot]

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/2180

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

This request is for worktrees OUTSIDE of the working directory and is therefore not duplicated

aewing avatar Aug 16 '25 21:08 aewing

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 05 '25 10:12 github-actions[bot]

This is still a valid request that would benefit at least a few users.

aewing avatar Dec 19 '25 21:12 aewing