README
ΒΆ
πͺΎ baretree
Git repositories, worktrees, and branches, organized.
baretree combines centralized repository management (inspired by ghq) with powerful Git worktree support. Manage all your repositories in one place, keep branches organized, and switch contexts instantly.
Why baretree?
Before
~/projects/
βββ my-app/ # main branch... or was it develop?
βββ my-app-feature/ # Which feature branch is this?
βββ my-app-auth-backup/ # Forgot to delete after merge
βββ my-app-hotfix-20240115/ # Old hotfix, still needed?
βββ ...scattered everywhere
After
~/baretree/ # All repositories organized
βββ github.com/
β βββ user/
β βββ my-app/ # One repository
β β βββ .git/ # Bare repository
β β βββ .shared/ # Shared across all worktrees (.env, etc.)
β β βββ main/ # worktree β main branch
β β βββ feature/
β β βββ auth/ # worktree β feature/auth branch
β β βββ api/ # worktree β feature/api branch
β βββ another-project/
βββ gitlab.com/
βββ ...
- All worktrees in one directory - No more scattered clones for each branch
- Shared files across worktrees -
.env,node_moduleslinked automatically - Instant context switching - Jump between worktrees (
bt cd) and repositories (bt go) - Migrate existing repos instantly - One command converts any repository
- Centralized repository management - All repos in
~/baretree/{host}/{user}/{repo} - AI Agent ready - Parallel tasks and isolated workspaces for AI coding assistants
π Quick Start
1. Install
# Homebrew (macOS/Linux)
brew install amaya382/tap/baretree
# GitHub Release (download binary)
# Download from https://github.com/amaya382/baretree/releases
# Extract and add to your PATH
# Example for Linux (amd64)
curl -L https://github.com/amaya382/baretree/releases/latest/download/baretree_Linux_x86_64.tar.gz | tar xz
sudo mv bt /usr/local/bin/
2. Shell Integration (required for bt cd)
This is required for bt cd and completion, however, you can skip the manual setup if installed via Homebrew (shell integration is automatically configured).
Note (Homebrew users): After installing via Homebrew, open a new terminal window for shell integration to take effect.
# Bash
echo 'eval "$(bt shell-init bash)"' >> ~/.bashrc && source ~/.bashrc
# Zsh
echo 'eval "$(bt shell-init zsh)"' >> ~/.zshrc && source ~/.zshrc
# Fish
echo 'bt shell-init fish | source' >> ~/.config/fish/config.fish && source ~/.config/fish/config.fish
π Getting Started
Choose your style: Centralized (recommended) or Standalone.
Option A: Centralized (Recommended)
Manage all repositories in a central location (~/baretree by default).
Migrate existing repositories to baretree managed directory
cd ~/projects/my-existing-repo
bt migrate . --to-managed # or -m
# Your repo is now baretree-structured and placed under ~/baretree
# Working tree state (staged, unstaged, untracked) is preserved
# Original repository is preserved by default (use --remove-source to delete)
bt go my-existing-repo
Clone a new repository
# Clone to ~/baretree/github.com/user/repo
bt get user/repo # Defaults to github.com
bt get github.com/user/repo # With domain
bt get git@github.com:user/repo.git # By full URL
Navigate between repositories
bt repos # List all repositories
bt go my-repo # Jump to repository
bt go user/repo # Jump with more specific path
Work with worktrees
bt add -b feature/auth # Create feature branch (auto-fetches remotes)
bt add -b feature/auth --no-fetch # Skip auto-fetch
bt add -b feature/auth --behind=pull # Pull base branch if behind upstream, then create
bt cd feature/auth # Jump to worktree
bt ls # List all worktrees
bt rm feature/auth # Remove when done
bt unbare main ~/standalone-repo # Export worktree as standalone repo
Option B: Standalone (without centralized management)
Use baretree for a single project without centralized repository management.
Start fresh
bt init my-project
cd my-project
bt cd @
# Start coding!
Migrate an existing repository in-place
cd ~/projects/my-repo
bt migrate . --in-place
# Your repo is now baretree-structured
# Working tree state (staged, unstaged, untracked) is preserved
Clone to a specific location
bt clone git@github.com:user/repo.git ~/projects/my-project
cd ~/projects/my-project
Work with worktrees
bt add -b feature/auth # Create feature branch (auto-fetches remotes)
bt add -b feature/auth --no-fetch # Skip auto-fetch
bt add -b feature/auth --behind=pull # Pull base branch if behind upstream, then create
bt cd feature/auth # Jump to worktree
bt ls # List all worktrees
bt rm feature/auth # Remove when done
bt unbare main ~/standalone-repo # Export worktree as standalone repo
π Post-create Actions
Automate worktree setup with shared files and commands that run on creation.
Shared Files
Share files like .env or node_modules across all worktrees automatically.
# Add shared files (symlink by default, stored in .shared/ directory)
bt post-create add symlink .env
bt post-create add symlink node_modules
# Use copy instead of symlink for files that need independent copies
bt post-create add copy .env
# Use --no-managed to source from default branch instead of .shared/
bt post-create add symlink .env --no-managed
Commands
Run commands automatically when creating new worktrees.
# Add commands to run after worktree creation
bt post-create add command "npm install"
bt post-create add command "direnv allow"
Commands are executed in the new worktree directory. Failures are warnings (won't block worktree creation).
More commands
bt post-create list # Show configured actions
bt post-create apply # Apply to all worktrees
bt post-create remove .env # Remove configuration
bt post-create remove "npm install" # Remove command
π Sync to Root
Make files from the default branch worktree accessible at the repository root via symlinks. This is useful for tools that need to find configuration files at the project root.
Common use cases:
- AI agent configuration:
CLAUDE.md,.claude/,.cursorrules,.github/copilot-instructions.md - Editor settings:
.idea/,.vscode/(when opening project root as workspace)- Note: For VS Code, Multi-Root Workspaces is recommended over
sync-to-root
- Note: For VS Code, Multi-Root Workspaces is recommended over
- Other root-level configs: Any file that tools expect at the repository root
# Sync AI agent config
bt sync-to-root add CLAUDE.md
bt sync-to-root add .claude
# Sync editor settings
bt sync-to-root add .idea
# Use a different target path
bt sync-to-root add docs/guide.md guide.md
# List configured entries
bt sync-to-root list
# Remove entry
bt sync-to-root remove CLAUDE.md
# Re-apply all symlinks
bt sync-to-root apply
After configuration:
project/
βββ .git/
βββ CLAUDE.md -> main/CLAUDE.md # Accessible from root
βββ .claude -> main/.claude # Accessible from root
βββ main/
β βββ CLAUDE.md
β βββ .claude/
β βββ ...
βββ feature/auth/
π€ AI Agent Integration
baretree's worktree-based structure is ideal for AI coding assistants like Claude Code, Cursor, and GitHub Copilot Workspace. Each worktree provides an isolated workspace.
Recommended Setup: Open Project Root as Workspace
For the best experience with AI agents and editors, open the project root (not individual worktrees) as your workspace:
# Open the project root in your editor
code ~/baretree/github.com/user/my-project # VS Code
cursor ~/baretree/github.com/user/my-project # Cursor
# Start Claude Code from the project root
cd ~/baretree/github.com/user/my-project
claude
Then use sync-to-root to make AI configuration files accessible from the root:
bt sync-to-root add CLAUDE.md
bt sync-to-root add .claude
bt sync-to-root add .cursorrules # For Cursor
This setup provides:
- Unified view: See all worktrees (main, feature/auth, etc.) in one workspace
- AI config at root:
CLAUDE.mdand.claude/are recognized by AI agents - Easy context switching: Jump between worktrees without changing windows
- Consistent rules: Agent rules apply across all worktrees
Your project structure:
my-project/ # <- Open this as workspace
βββ .git/
βββ CLAUDE.md -> main/CLAUDE.md # AI agents see this
βββ .claude -> main/.claude # AI agents see this
βββ main/
β βββ CLAUDE.md # Actual file
β βββ .claude/
β βββ src/
βββ feature/
βββ auth/ # Work on features here

[!TIP] Having trouble with VS Code debugger, source control, or
.vscode/settings in worktrees? VS Code's Multi-Root Workspaces lets you add each worktree as a separate workspace folder, so per-worktree settings like debug configurations work correctly.
Agent Rules Template
An example rules file for AI agents is available at examples/rules/. See examples/README.md for details.
Copy to your project's rules directory:
# For Claude Code
cp examples/rules/working-directory-on-git-worktree-with-baretree.md ~/.claude/rules/
# For Cursor
cp examples/rules/working-directory-on-git-worktree-with-baretree.md .cursor/rules/
π Command Reference
Worktree Management
| Command | Description |
|---|---|
bt add <branch> |
Add worktree (-b for new branch, --base for base branch/commit, --behind for behind-upstream action, auto-fetches remotes) |
bt list / bt ls |
List worktrees |
bt remove / bt rm |
Remove worktree (--with-branch to delete branch, --force to override safety checks) |
bt cd <name> |
Switch to worktree (@ for default, - for previous) |
bt status |
Show repository status |
bt repair |
Repair worktree/branch name mismatches |
bt rename [old] <new> |
Rename worktree and branch |
bt unbare <wt> <dest> |
Convert worktree to standalone repository |
bt root |
Show repository root directory path |
Repository Management (Centralized)
| Command | Alias | Description |
|---|---|---|
bt repo get <url> |
bt get |
Clone to baretree root (centralized-style) |
bt repo list |
bt repos |
List all managed repositories |
bt repo cd <name> |
bt go |
Jump to a repository |
bt repo migrate <path> --to-managed |
bt migrate |
Migrate and move to baretree managed directory |
bt repo remove <name> |
bt repo rm |
Remove a baretree repository |
bt repo root |
Show baretree root directory | |
bt repo config |
Manage global configuration |
Repository Management (Standalone)
| Command | Alias | Description |
|---|---|---|
bt repo init [dir] |
bt init |
Initialize new baretree repository |
bt repo clone <url> [dest] |
bt clone |
Clone to specific location |
bt repo migrate <path> -i |
bt migrate |
Convert existing repo in-place |
bt repo migrate <path> -d <dest> |
bt migrate |
Convert and copy to destination |
Post-create Actions
| Command | Description |
|---|---|
bt post-create add symlink <file> |
Add shared file as symlink |
bt post-create add copy <file> |
Add shared file as copy |
bt post-create add command <cmd> |
Add command to run on creation |
bt post-create remove <source> |
Remove action |
bt post-create list |
List configured actions |
bt post-create apply |
Apply to existing worktrees |
Sync to Root
| Command | Description |
|---|---|
bt sync-to-root add <source> [target] |
Symlink file/dir from default worktree to repo root |
bt sync-to-root remove <source> |
Remove entry and symlink |
bt sync-to-root list |
List configured entries |
bt sync-to-root apply |
Re-apply all symlinks |
Configuration
| Command | Description |
|---|---|
bt config default-branch |
Get or set the default branch |
bt config export |
Export repository config to TOML |
bt config import |
Import repository config from TOML |
bt repo config root |
Get or set the baretree root directory |
bt repo config export |
Export global config to TOML |
bt repo config import |
Import global config from TOML |
βοΈ Configuration
All configuration is stored in git-config (no extra config files needed).
Default Branch
Get, set, or unset the default branch for a repository (used for post-create files and sync-to-root):
bt config default-branch # Show current default branch
bt config default-branch develop # Set to 'develop'
bt config default-branch --unset # Remove setting (reverts to 'main')
Baretree Root
Get, set, or unset the root directory where repositories are stored (default: ~/baretree):
bt repo config root # Show current root directory
bt repo config root ~/code # Set root to ~/code
bt repo config root --unset # Remove setting (reverts to ~/baretree)
You can also use environment variable (takes precedence over the command setting):
export BARETREE_ROOT=~/code
[!TIP] Set baretree root to
~/ghqto use baretree alongside ghq. Runbt repo migrate -i .to add worktree support in each repository.
π¦ Install
Homebrew (macOS/Linux)
brew install amaya382/tap/baretree
GitHub Release (Binary)
Download the latest binary from GitHub Releases:
# Example for Linux (amd64)
curl -L https://github.com/amaya382/baretree/releases/latest/download/baretree_Linux_x86_64.tar.gz | tar xz
sudo mv bt /usr/local/bin/
# Example for macOS (Apple Silicon)
curl -L https://github.com/amaya382/baretree/releases/latest/download/baretree_Darwin_arm64.tar.gz | tar xz
sudo mv bt /usr/local/bin/
[In preparation] Snap (Linux)
sudo snap install baretree --classic
[In preparation] Scoop (Windows)
scoop bucket add amaya382 https://github.com/amaya382/scoop-bucket
scoop install baretree
From Source
go install github.com/amaya382/baretree/cmd/bt@latest
π§ Troubleshooting
bt cd doesn't work
Make sure shell integration is enabled:
# Check if the shell function and the command exist
type bt
type -p bt
# Re-add shell integration
eval "$(bt shell-init bash)" # or zsh/fish
Symlinks don't work on Windows
- Enable Developer Mode (Windows 10+)
- Or use
--type copyinstead
Can't remove worktree (uncommitted changes or unmerged branch)
bt rm aborts before touching anything when the worktree has uncommitted
changes, or (with --with-branch) the branch is not fully merged into the
default branch. Nothing is deleted in that case β the branch would otherwise
be left behind after the worktree is gone.
Use --force to override both checks. It enables git worktree remove --force
and git branch -D, so uncommitted work and unmerged commits are dropped.
bt rm feature/branch --force # discard uncommitted changes
bt rm feature/branch --with-branch --force # also drop an unmerged branch
Worktree and branch names don't match
bt repair --dry-run --all # Preview changes
bt repair --all # Fix (use branch name as source)
bt repair --source=dir --all # Fix (use directory name as source)
π Requirements
- Git 2.15+
- Go 1.23+ (building from source)