How the no-mistakes Daemon Manages Disposable Git Worktrees for Secure CI Pipelines
The no-mistakes daemon creates isolated, disposable Git worktrees for every pipeline run by executing git worktree add --detach in a namespaced directory under $NM_HOME, then automatically removes them after execution or during periodic orphan recovery scans.
The no-mistakes daemon (from the repository kunchenguid/no-mistakes) orchestrates CI pipelines inside ephemeral, isolated environments to prevent accidental mutations to the user's primary repository. By leveraging disposable worktrees, the daemon ensures each execution runs in a clean, detached sandbox that exists only for the duration of the job.
Worktree Directory Structure and Naming Convention
All disposable worktrees reside under the daemon's data directory. The Paths helper in internal/paths/paths.go constructs absolute paths using a deterministic hierarchy:
// internal/paths/paths.go (lines 46-48)
func (p *Paths) WorktreeDir(repoID, runID string) string {
return filepath.Join(p.root, "worktrees", repoID, runID)
}
This generates a path like $NM_HOME/worktrees/<repoID>/<runID>/, ensuring complete filesystem isolation between repositories and individual runs.
Creating Worktrees via Git Commands
When Manager.startRun initiates a new pipeline, it materializes the worktree by invoking the Git CLI directly. The daemon executes git worktree add --detach to create a linked worktree that shares the bare gate repository's object database while maintaining an independent HEAD state.
According to internal/daemon/manager.go (lines 308-319), the creation flow follows this pattern:
// Conceptual excerpt from internal/daemon/manager.go
func (m *Manager) startRun(repo *Repo, headSHA string) (string, error) {
runID := generateRunID()
wtDir := m.paths.WorktreeDir(repo.ID, runID)
// Line 308: Create worktree from the gate bare repo
cmd := exec.CommandContext(ctx, "git", "worktree", "add", "--detach", wtDir, headSHA)
if out, err := cmd.CombinedOutput(); err != nil {
// Lines 312-319: Persist error and abort
m.db.UpdateRunError(runID, fmt.Sprintf("create worktree: %s", err))
return "", fmt.Errorf("create worktree: %w (%s)", err, out)
}
return runID, nil
}
If the command fails, the error is persisted via m.db.UpdateRunError and the run aborts immediately.
Configuration and Isolation Guarantees
Immediately after creation, the daemon configures a deterministic Git identity to ensure traceable commits. As implemented in internal/daemon/manager.go (lines 317-319), it sets user.name and user.email to bot-specific values to differentiate automated commits from user commits.
The worktree operates in detached HEAD state. The execution_context.go file (lines 5-21) documents that the .git entry inside the worktree is a pointer file linking back to the bare repository, preventing agents from accidentally writing to the user's original checkout. The executor explicitly warns agents to restrict all writes to this directory (internal/pipeline/executor.go, lines 111-119).
Before execution, the daemon fetches the remote's default branch into the worktree to provide a trusted view of the repository. If this fetch fails, the run proceeds with a warning but without the trusted configuration (manager.go lines 333-334).
Execution and Automatic Cleanup
The manager delegates pipeline execution to a background goroutine via executor.Run. Cleanup responsibility is tracked through trackStartFailure and trackStopFailure flags to ensure the manager knows when it owns the worktree removal.
When the pipeline terminates, the executor triggers removal via a deferred cleanup routine:
// Cleanup logic from internal/daemon/daemon.go (lines 287-292)
func (d *Daemon) cleanupWorktrees() {
// ...
if err := os.RemoveAll(worktreeDir); err != nil {
slog.Warn("failed to remove worktree", "path", worktreeDir, "error", err)
}
}
If the initial removal fails, the daemon falls back to os.RemoveAll and logs the failure without crashing the daemon process.
Orphan Detection and Crash Recovery
To handle crashes or unclean shutdowns, the daemon implements a recover-servers task that scans the worktrees directory during startup. As exercised in internal/daemon/subscribe_recover_test.go (lines 353-401), this routine:
- Lists all directories under
Paths.WorktreesDir() - Checks for corresponding active run entries in the database via
isRunActive() - Removes orphaned directories that lack active run records
This best-effort pruning prevents disk space exhaustion from abandoned worktrees left by previous daemon instances.
Summary
- Directory Structure: Worktrees are stored under
$NM_HOME/worktrees/<repoID>/<runID>/viaPaths.WorktreeDir()ininternal/paths/paths.go(lines 46-48). - Creation: The daemon invokes
git worktree add --detachinManager.startRun(manager.go lines 308-319) to create isolated, linked worktrees. - Isolation: Detached HEAD state and pointer-file
.gitentries prevent writes to the user's original checkout (execution_context.go lines 5-21). - Cleanup: Automatic removal occurs via deferred
os.RemoveAllafter pipeline completion, with fallback error logging (daemon.go lines 287-292). - Recovery: A periodic scan removes orphaned worktrees that persist after crashes (subscribe_recover_test.go lines 353-401).
Frequently Asked Questions
Where does the no-mistakes daemon store disposable worktrees?
The daemon stores all worktrees under the worktrees/ subdirectory of its data root ($NM_HOME). The Paths.WorktreeDir() function in internal/paths/paths.go (lines 46-48) constructs paths following the pattern $NM_HOME/worktrees/<repoID>/<runID>/, ensuring each run receives a unique filesystem location.
How does the daemon ensure worktrees are cleaned up after a crash?
The daemon runs an orphan detection routine during startup that scans Paths.WorktreesDir() for directories without corresponding active run entries in the database. As tested in internal/daemon/subscribe_recover_test.go (lines 353-401), this routine performs best-effort deletion of stale worktrees to reclaim disk space.
Why does no-mistakes use git worktree add --detach instead of a simple clone?
Using git worktree add --detach creates a linked worktree that shares the bare repository's object database, eliminating redundant storage of Git history while enforcing isolation through a detached HEAD state. This approach, documented in internal/pipeline/steps/execution_context.go (lines 5-21), prevents pipeline agents from accidentally pushing to or modifying the user's default branches.
What happens if the git worktree add command fails?
If the command fails, Manager.startRun captures the combined output, persists the error via m.db.UpdateRunError, and aborts the run immediately (manager.go lines 312-319). The error is surfaced to the user through the run's status, and no partial worktree directory is left behind because the Git command is atomic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →