Problem
When Claude Code (or any agent) runs inside a git worktree rather than the main working tree, several built-in rules produce false positives. Worktrees are designed as disposable, isolated workspaces — discarding changes in a worktree doesn't risk the main branch's uncommitted work.
Commands that Safety Net currently blocks in worktrees:
| Command |
Rule |
Why it's safe in a worktree |
git restore <file> |
analyzeGitRestore |
Worktree is isolated; main tree is unaffected |
git restore --worktree <file> |
analyzeGitRestore (--worktree flag) |
Same — the worktree IS the disposable workspace |
git checkout -- <file> |
analyzeGitCheckout |
Discards changes only in the worktree |
git reset --hard |
analyzeGitReset |
Resets only the worktree, not the main tree |
git clean -f |
analyzeGitClean |
Cleans only the worktree |
These are routine operations when using worktree-based workflows like worktrunk or Claude Code's native --worktree flag, where the typical flow is: create worktree, make changes, merge or discard, remove worktree.
Impact
The blocking behavior forces the agent to either:
- Ask the user for manual intervention (defeats the purpose of autonomous agents)
- Work around the block with more complex alternatives
- Fail the task entirely
This is especially disruptive for parallel agent sessions where multiple worktrees are used simultaneously — the whole point is that each worktree is isolated and disposable.
Bonus irony: Filing this very issue was blocked by Safety Net because the issue body contains the text git restore as a string literal — the same class of false positive reported in #41.
Suggested fix
Detect whether the current working directory is inside a worktree (not the main working tree) and relax the change-discard rules accordingly.
Detection is straightforward:
# Returns "true" if inside a linked worktree (not the main working tree)
git rev-parse --is-inside-work-tree && [ "$(git rev-parse --git-common-dir)" != "$(git rev-parse --git-dir)" ]
Or in Node.js, check if .git is a file (not a directory) — linked worktrees have a .git file containing gitdir: /path/to/main/.git/worktrees/<name>:
import { statSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
function isLinkedWorktree(cwd: string): boolean {
try {
const dotGit = join(cwd, '.git');
const stat = statSync(dotGit);
if (stat.isFile()) {
const content = readFileSync(dotGit, 'utf-8');
return content.trimStart().startsWith('gitdir:');
}
return false;
} catch {
return false;
}
}
Rules to relax in worktrees
These rules protect against losing uncommitted work. In a linked worktree, that work is isolated by design:
git restore (with or without --worktree)
git checkout -- <files>
git reset --hard
git clean -f
Rules to keep in worktrees
These have effects beyond the local working tree and should remain blocked:
git push --force (affects remote)
git branch -D (affects shared branch refs)
git stash drop/clear (stash is shared across worktrees)
git worktree remove --force (could delete another worktree)
Environment
- Safety Net v0.5.1 (via cc-marketplace plugin)
- macOS (Darwin 25.3.0)
- Worktree workflow: worktrunk + Claude Code
--worktree
Related
Problem
When Claude Code (or any agent) runs inside a git worktree rather than the main working tree, several built-in rules produce false positives. Worktrees are designed as disposable, isolated workspaces — discarding changes in a worktree doesn't risk the main branch's uncommitted work.
Commands that Safety Net currently blocks in worktrees:
git restore <file>analyzeGitRestoregit restore --worktree <file>analyzeGitRestore(--worktree flag)git checkout -- <file>analyzeGitCheckoutgit reset --hardanalyzeGitResetgit clean -fanalyzeGitCleanThese are routine operations when using worktree-based workflows like worktrunk or Claude Code's native
--worktreeflag, where the typical flow is: create worktree, make changes, merge or discard, remove worktree.Impact
The blocking behavior forces the agent to either:
This is especially disruptive for parallel agent sessions where multiple worktrees are used simultaneously — the whole point is that each worktree is isolated and disposable.
Bonus irony: Filing this very issue was blocked by Safety Net because the issue body contains the text
git restoreas a string literal — the same class of false positive reported in #41.Suggested fix
Detect whether the current working directory is inside a worktree (not the main working tree) and relax the change-discard rules accordingly.
Detection is straightforward:
Or in Node.js, check if
.gitis a file (not a directory) — linked worktrees have a.gitfile containinggitdir: /path/to/main/.git/worktrees/<name>:Rules to relax in worktrees
These rules protect against losing uncommitted work. In a linked worktree, that work is isolated by design:
git restore(with or without--worktree)git checkout -- <files>git reset --hardgit clean -fRules to keep in worktrees
These have effects beyond the local working tree and should remain blocked:
git push --force(affects remote)git branch -D(affects shared branch refs)git stash drop/clear(stash is shared across worktrees)git worktree remove --force(could delete another worktree)Environment
--worktreeRelated