AWT (Agent WorkTrees) is a CLI tool that enables multiple AI agents to safely create, use, and hand off Git worktrees for concurrent development workflows.
AWT solves the problem of multiple AI agents (like Claude Code, Codex, Factory, etc.) working on the same Git repository simultaneously. It provides:
- Isolated Worktrees: Each agent gets its own working directory
- Global Worktree Storage: Worktrees are stored in
~/.awt/by default, preventing agents from seeing each other's work - Task Lifecycle: Track tasks from creation through handoff
- Branch Management: Automatic branch creation and cleanup
- Metadata Tracking: Persistent task state and history
- Command isolation: You can run commands within the worktrees without checking out the branch
There are many great tools like Conductor or HumanLayer that let you manage multiple worktrees if you want to adopt a new tool. This is built to just be a tool the agent themselves can use. This is what I put in my AGENTS.md to prompt usage of it:
# Starting a new task
- When you begin working on a new task, use `awt task start --title "xxx" --agent "your_name"` with an appropriate title
- When you need to commit changes, use `awt task commit`, do not navigate into the cwd and use git manually.
- When the user asks you to handoff the task, use the `awt task handoff` command with your task ID.
- Always give the user your task ID so they can also run commands.
All AWT commands are in ./docs/AWT_USAGE.md.
brew install kernel-labs-ai/tap/awt# Download the latest release
curl -LO https://github.com/kernel-labs-ai/awt/releases/latest/download/awt_<VERSION>_<OS>_<ARCH>.tar.gz
# Extract and install
tar xzf awt_*.tar.gz
sudo mv awt /usr/local/bin/
# Verify installation
awt versiongit clone https://github.com/kernel-labs-ai/awt.git
cd awt
go build -o awt ./cmd/awt
sudo mv awt /usr/local/bin/# Initialize AWT in your repository
cd /path/to/your/repo
awt init
# Start a new task
awt task start --agent=claude --title="Add user authentication"
# Output: Task ID, branch name, worktree path
# Work in the worktree (located at ~/.awt/<project-id>/<task-id>)
cd ~/.awt/<project-id>/<task-id>
# Make changes...
# Run dev server for the worktree
awt task exec <task-id> -- npm run dev
# Commit changes
awt task commit <task-id> -m "Implement login endpoint"
# Pull in changes from main with a rebase
awt task sync <task-id>
# Complete and hand off (push + create PR)
awt task handoff <task-id>
# List all tasks
awt list
# Clean up orphaned tasks
awt pruneInitialize AWT in a Git repository. Creates necessary directories and version file.
awt init [--repo=<path>]Start a new task with isolated worktree. The --agent flag allows you to delegate the same task to multiple agents at once and choose the best output.
awt task start --agent=<name> --title="<description>" [options]
Options:
--agent string Agent name (required)
--title string Task title (required)
--base string Base branch (default: origin/main)
--id string Custom task ID (auto-generated if not provided)
--no-fetch Skip git fetch
--json Output as JSONShow task status and metadata.
awt task status [task-id] [--branch=<name>] [--json]Commit changes in a task's worktree.
awt task commit [task-id] -m "<message>" [options]
Options:
-m, --message string Commit message
-a, --all Stage all modified files
--signoff Add Signed-off-by trailer
--gpg-sign string GPG sign commitRebase task branch with base branch.
awt task sync [task-id] [options]
Options:
--merge Use merge instead of rebase
--no-fetch Skip fetching remoteComplete task and hand off (push + create PR + detach worktree).
awt task handoff [task-id] [options]
Options:
--no-push Don't push to remote
--no-pr Don't create pull request
--keep-worktree Keep worktree after handoff
--force-remove Remove worktree even if CWD is inside itExecute a command in task's worktree.
awt task exec <task-id> -- <command> [args...]Checkout existing task for review.
awt task checkout <task-id> [--path=<path>]Adopt an existing Git branch as AWT task.
awt task adopt <branch> --agent=<name> [--title="<title>"]Unlock a task branch by detaching worktrees.
awt task unlock <task-id> [--remove]List all tasks with status.
awt list [--json]Clean up orphaned tasks and stale locks.
awt prune [--dry-run] [--json]Show all configuration settings.
awt config list [--json]Get a configuration value.
awt config get <key>Set a configuration value.
awt config set <key> <value> [--scope=user|repo|system]Unset a configuration value.
awt config unset <key> [--scope=user|repo|system]Show configuration file path.
awt config path [--scope=user|repo|system]AWT supports multi-level configuration with the following precedence (highest to lowest):
- Environment variables (highest)
- Repository config (
.git/awt/config.json) - User config (
~/.config/awt/config.json) - System config (
/etc/awt/config.json)
| Setting | Description | Default | Env Variable |
|---|---|---|---|
default_agent |
Default agent name | unknown |
AWT_DEFAULT_AGENT |
branch_prefix |
Branch prefix | awt |
AWT_BRANCH_PREFIX |
worktree_dir |
Worktree directory | ~/.awt |
AWT_WORKTREE_DIR |
rebase_default |
Use rebase for sync | true |
AWT_REBASE_DEFAULT |
auto_push |
Auto-push on handoff | true |
AWT_AUTO_PUSH |
auto_pr |
Auto-create PR on handoff | true |
AWT_AUTO_PR |
remote_name |
Default remote | origin |
AWT_REMOTE_NAME |
lock_timeout |
Lock timeout (seconds) | 30 |
AWT_LOCK_TIMEOUT |
verbose_git |
Verbose git output | false |
AWT_VERBOSE_GIT |
{
"default_agent": "claude",
"branch_prefix": "agent",
"worktree_dir": "~/.awt",
"rebase_default": true,
"auto_push": true,
"auto_pr": true,
"remote_name": "origin",
"lock_timeout": 60,
"verbose_git": false
}By default, we use a global directory for worktrees to avoid issues with coding agents grepping in a project folder and finding changes from other agent tasks. To use local worktrees instead of the global directory you can just set a relative local path:
{
"worktree_dir": "./awt"
}NEW → ACTIVE → HANDOFF_READY → MERGED
↓ ↓ ↓
└──→ ABANDONED ←───┘
- NEW: Task created but not yet active
- ACTIVE: Work in progress
- HANDOFF_READY: PR created, ready for review
- MERGED: PR merged, task complete
- ABANDONED: Task cancelled or abandoned
AWT uses a global worktree directory (~/.awt by default) to store worktrees outside the repository. This prevents multiple agents from seeing each other's work and keeps your repository clean.
~/.awt/ # Global worktree directory
└── <project-name>-<hash>/ # Project-specific directory
└── <task-id>/ # Task worktree
└── [working files]
your-repo/
└── .git/
└── awt/
├── version # AWT version
├── config.json # Repository config
├── tasks/ # Task metadata
│ └── <id>.json
└── locks/ # Lock files
├── global.lock
└── task-<id>.lock
The project identifier is generated from the repository directory name and a hash of its absolute path, ensuring uniqueness across different projects with the same name. For example:
/Users/dev/myproject→~/.awt/myproject-87da903d//Users/dev/work/myproject→~/.awt/myproject-a1b2c3d4/
Each task is stored as JSON at .git/awt/tasks/<id>.json:
{
"id": "20251110-120000-abc123",
"agent": "claude",
"title": "Add user authentication",
"branch": "awt/claude/20251110-120000-abc123",
"base": "origin/main",
"created_at": "2025-11-10T12:00:00Z",
"state": "ACTIVE",
"worktree_path": "/Users/dev/.awt/myproject-87da903d/20251110-120000-abc123",
"last_commit": "sha1...",
"pr_url": ""
}- Agent Names: Alphanumeric, dash, underscore only (max 50 chars)
- Task Titles: No newlines/tabs, max 200 chars
- Branch Names: Git naming rules enforced
- Commit Messages: Subject line max 100 chars, total max 10000 chars
- Worktree path validation (existence, emptiness)
- CWD checks before worktree removal
- No operations inside
.gitdirectory - Worktree != repository root
- POSIX file locking (flock) with EWOULDBLOCK/EAGAIN checks
- O_EXCL fallback for network filesystems
- Global lock for repository-wide operations
- Per-task locks for task-specific operations
- Configurable timeouts and retry logic
# Agent 1 (Claude)
awt task start --agent=claude --title="Add user auth"
# Agent 2 (GPT)
awt task start --agent=gpt --title="Add API docs"# Agent 1 completes their work
awt task handoff 20251110-120000-abc123
# Agent 2 takes over for review
awt task checkout 20251110-120000-abc123
# Agent 2 makes changes and re-commits
awt task commit 20251110-120000-abc123 -m "Address review comments"
awt task handoff 20251110-120000-abc123# Error: Lock timeout
# Solution: Increase timeout or check for stale locks
awt config set lock_timeout 60
awt prune # Clean up stale locks# Error: Branch already exists
# Solution: Use different task ID or delete old branch
git branch -d awt/agent/old-task-id# Error: Worktree not found
# Solution: Check task status and recreate if needed
awt task status <task-id>
awt prune # Clean up orphaned metadata
# Worktrees are stored globally at ~/.awt/<project-id>/<task-id>
# Check if the directory exists:
ls -la ~/.awt/# Error: Cannot remove worktree, CWD is inside it
# Solution: Change directory or use --force-remove
cd /path/to/main/worktree
awt task handoff <task-id>
# Or
awt task handoff <task-id> --force-removego build -o awt ./cmd/awt# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run with race detector
go test -race ./...# Tag a new version
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
# GitHub Actions will automatically:
# - Run tests
# - Build binaries for all platforms
# - Create GitHub release
# - Update Homebrew tapContributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run
go test ./...andgo vet ./... - Submit a pull request
MIT License - see LICENSE file for details.
Developed by Kernel Labs for enabling AI agent collaboration.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Wiki