This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
make # Build binary (equivalent to: go build -o wt ./cmd/wt)
make test # Run all tests
make test-short # Skip integration tests
make vet # Lint (golangci-lint)
make fmt # Format code (gofumpt)
make dev # fmt + vet + test + build
make clean # Remove built binary
make install # Install to $GOBIN as "wt"Raw go commands for reference:
go build -o wt ./cmd/wt # Build binary
go install ./cmd/wt # Install to $GOBIN as "wt"
go test ./... # Run all tests
go test ./internal/git/ # Run tests for a single package
go test ./internal/git/ -run TestDryRun # Run a specific test
go test -short ./... # Skip integration tests (git_test.go has integration tests gated on -short)
go vet ./... # Lintwt is a CLI tool for managing git worktree-based development workflows. It wraps a bare git repository and creates worktrees under a worktrees/ directory with shared files/symlinks.
- No
.gitat project root. The bare repo lives at.bare/(configurable via.worktree.yml). All git operations go throughgit.Runnerwhich passes--git-dirto every command. shared/folder IS the config for copy/symlink behavior. The directory structure mirrors the worktree root — no lists to maintain in YAML.- Dry-run is a first-class concept. The global
--dry-runflag is threaded throughgit.Runner(skips execution, prints what would happen) andproject.CreateScaffold. New commands must respectcmd.IsDryRun(). - Interactive by default. Commands that accept
[<name>]should launch a huh picker when called without an argument. Theui.Prompterinterface exists for testability.
cmd/— Cobra commands. Each command in its own file, registered inroot.goinit(). Global flags (like--dry-run) live onrootCmd.internal/git/— All git operations.Runnerwraps--git-dirfor bare repo context.CloneBareis the only method that bypasses--git-dir(it creates the bare repo). Parse functions (parseRemoteBranches,parseWorktreeList) are pure and unit-testable.internal/config/—.worktree.ymlreading/writing.DefaultConfig()provides sensible defaults.config.Exists()andconfig.Load()are used byproject.FindRoot()to walk up the directory tree.internal/project/— Project-level operations: root detection (walks up looking for.worktree.yml), scaffold creation, repo name extraction from URLs.internal/ui/— Terminal output (output.gowith styled helpers) and interactive prompts (prompts.gowith huh). All output goes toui.Output(defaults to stderr) so stdout stays clean for machine-readable output likewt cd.
- Create
cmd/<name>.gowithfunc new<Name>Cmd() *cobra.Command - Register it in
cmd/root.goinit()viarootCmd.AddCommand(new<Name>Cmd()) - Load project config with
config.Load()and create agit.NewRunner()using the resolved git dir - Use
project.FindRoot()to locate the project root from the current directory (for commands that run inside a project, unlikeclone)
Phase 1 (done): scaffold, wt clone. Phase 2 (next): wt add, wt list, wt remove, wt cd. Phase 3: wt apply. Phase 4+: hooks, templates, completions, IDE integration.
This project uses beads_rust (br/bd) for issue tracking. Issues are stored in .beads/ and tracked in git.
# View ready issues (unblocked, not deferred)
br ready # or: bd ready
# List and search
br list --status=open # All open issues
br show <id> # Full issue details with dependencies
br search "keyword" # Full-text search
# Create and update
br create --title="..." --description="..." --type=task --priority=2
br update <id> --status=in_progress
br close <id> --reason="Completed"
br close <id1> <id2> # Close multiple issues at once
# Sync with git
br sync --flush-only # Export DB to JSONL
br sync --status # Check sync status- Start: Run
br readyto find actionable work - Claim: Use
br update <id> --status=in_progress - Work: Implement the task
- Complete: Use
br close <id> - Sync: Always run
br sync --flush-onlyat session end
- Dependencies: Issues can block other issues.
br readyshows only unblocked work. - Priority: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (use numbers 0-4, not words)
- Types: task, bug, feature, epic, chore, docs, question
- Blocking:
br dep add <issue> <depends-on>to add dependencies
Before ending any session, run this checklist:
git status # Check what changed
br sync --flush-only # Export beads changes to JSONL- Check
br readyat session start to find available work - Update status as you work (in_progress → closed)
- Create new issues with
br createwhen you discover tasks - Use descriptive titles and set appropriate priority/type
- Always sync before ending session