.enki/copies/<task_id>. Copies include everything — build artifacts, node_modules, .gitignored files — so workers start with a warm build cache. Uses platform-appropriate copy-on-write for instant, space-efficient clones.
Why Full Copies?
Workers need everything, not just source code. If a test suite depends on compiled binaries, or a linter expectsnode_modules, workers must see those files. Enki’s copy-on-write approach gives workers the entire project state without doubling disk usage.
Copies are independent. Each worker modifies its own copy. When finished, changes are committed to a git branch, fetched back to the source repo, and merged. The source working tree is never directly modified by workers.
Copy-on-Write Cloning
Enki uses platform-specific CoW primitives:- macOS (APFS):
cp -Rc— instant cloning viaclonefile(2) - Linux (btrfs/XFS):
cp --reflink=auto -a— CoW where supported, regular copy otherwise - Other:
cp -a— regular recursive copy
Worker Filesystem Layout
Each worker gets a directory under.enki/copies/:
Copy Creation: Git vs Non-Git Projects
Enki handles both git-based projects and non-git directories.Git Projects
For projects that are git repositories:- Record the base commit (current
HEAD) and branch name - Clone each top-level entry except
.enki/into a temp directory using CoW - Atomically rename the temp directory to the final copy path
- Create a task branch inside the copy:
git checkout -b task/<task_id>
Non-Git Projects
For directories that aren’t git repos (e.g., a folder of scripts):- Clone each top-level entry except
.enki/ - Initialize git inside the copy:
git init, commit everything as a “baseline” commit - Create a task branch off the baseline:
task/<task_id>
Why git inside non-git copies? Workers use git for version control regardless of the source. This gives Enki a uniform interface: all changes are git commits, all merges follow the same flow (though non-git projects do filesystem merges instead of git merges).
Uncommitted Changes Are Visible
If you have uncommitted changes in your working tree, workers see them. Copies are created from the live filesystem, not fromHEAD.
Worker Changes: Commit and Fetch
When a worker finishes:- Auto-commit: Enki runs
git add -A && git commit -m "<title>"inside the copy - Fetch branch:
git fetch <copy_path> task/<id>:task/<id>brings the worker’s commits into the source repo - Merge: The refinery merges
task/<id>into the default branch - Cleanup: Copy directory is deleted, branch is deleted from source
What if a worker makes no file changes?
What if a worker makes no file changes?
If the worker completes without committing any file changes, Enki reports
WorkerOutcome::NoChanges. The task is retried (up to 3 times) or fails. Workers are expected to produce output.Platform-Specific Behavior
Enki adapts to the platform’s CoW capabilities:| Platform | Command | CoW Support |
|---|---|---|
| macOS (APFS) | cp -Rc | ✅ Full CoW via clonefile |
| Linux (btrfs) | cp --reflink=auto -a | ✅ Full CoW |
| Linux (ext4) | cp --reflink=auto -a | ⚠️ Falls back to regular copy |
| Linux (XFS) | cp --reflink=auto -a | ✅ Full CoW (recent kernels) |
| Other | cp -a | ❌ Regular copy |
Copy Lifecycle
CopyManager API
TheCopyManager struct (in core/src/copy.rs) handles all copy operations:
Git Identity
Copies inherit the user’s git identity from the source repo:user.name and user.email from the source repo’s git config on startup. All commits in worker copies use this identity.
If the source isn’t a git repo (or git config is missing), Enki uses a default identity:
"enki" <enki@localhost>.Example: Worker Copy Workflow
Here’s a real workflow from start to finish:Performance Characteristics
| Operation | APFS (macOS) | btrfs (Linux) | ext4 (Linux) |
|---|---|---|---|
| Create copy (10GB project) | ~100ms | ~200ms | ~30s |
| Disk usage (before modifications) | ~1MB (metadata) | ~1MB (metadata) | 10GB (full copy) |
| Worker modifies 10 files (1MB total) | +1MB | +1MB | +1MB |
Limitations and Trade-offs
Build artifacts are shared (until modified): If you have a 5GB
target/ directory from a Rust build, all workers share those blocks via CoW until they rebuild. The first worker to modify a file triggers a copy of that file.Next Steps
Merge Queue
Learn how the refinery merges worker branches
Roles
Understand agent roles and output modes
