Conversation
📝 WalkthroughWalkthroughAdds a stable per-worktree numeric index (WT_INDEX) with allocation, persistence, and retrieval in the git layer; surfaces indices to commands, listing, and hook environments; introduces optional index.max configuration; and includes an example hook script that uses WT_INDEX to compute per-worktree port offsets. Changes
Sequence Diagram(s)sequenceDiagram
participant User as CLI (create)
participant Cmd as Create Command
participant Git as internal/git
participant FS as .git/worktrees/<name>/wt-index
participant Hooks as Hook Runner
User->>Cmd: wt create <name>
Cmd->>Git: AllocateIndex(repoRoot, max)
Git->>Git: scan existing wt-index files
Git-->>Cmd: index (n) or error
Cmd->>Git: SetWorktreeIndex(repoRoot, name, n)
Git->>FS: write wt-index file
Cmd->>Hooks: run post-create hooks with env.Index = n
Hooks->>FS: (hook reads .wt-ports.env or uses WT_INDEX)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
internal/git/git.go (1)
541-567: Consider documenting the lack of atomicity for concurrent allocations.The allocation algorithm is correct and efficient. However, if two
wt createcommands run concurrently, both could allocate the same index before either persists it viaSetWorktreeIndex. This is likely acceptable given the CLI's typical single-user usage pattern, but might be worth noting in documentation or a code comment.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
examples/hooks/setup-ports.shinternal/commands/cleanup.gointernal/commands/commands_test.gointernal/commands/create.gointernal/commands/delete.gointernal/commands/list.gointernal/config/config.gointernal/config/config_test.gointernal/git/git.gointernal/git/git_test.gointernal/hooks/hooks.gointernal/hooks/hooks_test.go
🧰 Additional context used
📓 Path-based instructions (4)
internal/commands/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
internal/commands/**/*.go: Cobra command implementations should be located in internal/commands/ package
Use cmd.Println() for stderr output in Cobra commands
Use fmt.Fprintln(cmd.OutOrStdout(), ...) for stdout output (paths, listings) in Cobra commands
Files:
internal/commands/delete.gointernal/commands/create.gointernal/commands/cleanup.gointernal/commands/list.gointernal/commands/commands_test.go
internal/hooks/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
internal/hooks/**/*.go: Lifecycle hook execution should be in internal/hooks/ package
Pass standardized hook environment variables: WT_NAME, WT_PATH, WT_BRANCH, WT_REPO_ROOT, WT_WORKTREE_DIR
Files:
internal/hooks/hooks.gointernal/hooks/hooks_test.go
internal/config/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Configuration loading and parsing for .wt.yaml files should be in internal/config/ package
Files:
internal/config/config.gointernal/config/config_test.go
internal/git/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
internal/git/**/*.go: Git worktree command wrapping and porcelain output parsing should be in internal/git/ package
Determine if running in main repo vs worktree by checking if .git is a file (worktree) or directory (main repo)
Files:
internal/git/git.gointernal/git/git_test.go
🧬 Code graph analysis (8)
internal/commands/delete.go (1)
internal/git/git.go (1)
GetWorktreeIndex(530-539)
internal/hooks/hooks_test.go (1)
internal/hooks/hooks.go (1)
Env(14-21)
internal/git/git_test.go (1)
internal/git/git.go (7)
CreateWorktree(25-31)RemoveWorktree(43-53)GetWorktreeIndex(530-539)SetWorktreeIndex(517-527)AllocateIndex(542-567)GetCurrentBranch(105-115)GetWorktreeStatus(471-514)
internal/commands/create.go (1)
internal/git/git.go (2)
AllocateIndex(542-567)SetWorktreeIndex(517-527)
internal/config/config_test.go (1)
internal/config/config.go (1)
Config(21-27)
internal/commands/cleanup.go (1)
internal/git/git.go (1)
GetWorktreeIndex(530-539)
internal/commands/list.go (1)
internal/git/git.go (1)
GetWorktreeIndex(530-539)
internal/commands/commands_test.go (1)
internal/git/git.go (1)
GetWorktreeIndex(530-539)
🔇 Additional comments (27)
examples/hooks/setup-ports.sh (1)
1-39: LGTM! Well-documented example hook.This example script effectively demonstrates the WT_INDEX feature by calculating unique port offsets for each worktree. The graceful fallback on missing WT_INDEX (exit 0 with warning) is appropriate for an optional hook scenario.
internal/commands/delete.go (1)
104-107: LGTM! Index retrieval before deletion is correctly placed.Fetching the index before the deletion flow ensures hooks receive the index value. Silently ignoring errors is appropriate since the index file may not exist for worktrees created before this feature.
internal/commands/cleanup.go (1)
204-207: LGTM! Consistent with delete.go pattern.The index retrieval for cleanup candidates mirrors the approach in
delete.go, maintaining consistency across deletion paths.internal/config/config_test.go (1)
99-124: LGTM! Good test coverage for IndexConfig.The tests appropriately verify both explicit configuration (
index.max: 20) and the default zero-value behavior. The comment clarifying that0means "no limit" adds useful documentation.internal/hooks/hooks_test.go (2)
48-97: LGTM! Comprehensive test for WT_INDEX inclusion.The test correctly verifies that
WT_INDEXis included whenIndex > 0. The explicit check at lines 86-96 is slightly redundant (already verified by the map lookup loop), but it adds clarity to the test intent.
99-123: LGTM! Good boundary test for Index=0.This test correctly verifies the conditional behavior where
WT_INDEXis excluded whenIndexis zero, ensuring hooks that depend on a valid index don't receive a misleading zero value.internal/config/config.go (2)
26-26: LGTM!The
Indexfield follows the existing pattern and the zero value correctly represents "no limit" as documented.
15-18: Consider documenting or validating the behavior of negativeMaxvalues.The
IndexConfigstruct only documents that0means "no limit", but negative values are also silently treated as unlimited when passed toAllocateIndex. Either add explicit validation in theLoadfunction to reject negative values, or update the comment to document that negative values are treated the same as0.internal/hooks/hooks.go (2)
20-20: LGTM!Adding
Indexto theEnvstruct aligns with the coding guidelines for passing standardized hook environment variables.
24-36: LGTM! Conditional WT_INDEX inclusion is well-designed.The logic correctly omits
WT_INDEXwhen the index is 0 (reserved for main repo), ensuring hooks only receive this variable when a valid worktree index has been allocated. This follows the coding guidelines for passingWT_INDEXto hooks.internal/commands/create.go (1)
111-121: LGTM! Robust index allocation with graceful degradation.The implementation correctly:
- Allocates index after worktree creation (ensuring worktree directory exists for
SetWorktreeIndex)- Uses warnings for failures rather than blocking (worktree remains usable without index)
- Only sets
env.Indexon full success, ensuring hooks receive valid data- Follows coding guidelines using
cmd.Printffor warning output to stderrinternal/commands/list.go (4)
49-49: LGTM!Adding
indexfield toworktreeInfostruct cleanly extends the display model.
104-106: LGTM!Silently ignoring errors for index retrieval is appropriate here—missing indices simply display as "-" in the output, which is the expected fallback behavior.
157-165: LGTM! Clean compact output formatting.The INDEX column formatting is appropriate. The fixed width of 5 characters handles typical use cases well (indices up to ~9999 with the
#prefix). Follows coding guidelines by outputting tocmd.OutOrStdout().
178-181: LGTM!Conditional display of index in verbose mode is consistent with the pattern used elsewhere (e.g., age, ahead/behind). Good placement after Branch for logical grouping.
internal/commands/commands_test.go (3)
10-11: LGTM!Import addition for
gitpackage is necessary for the new test assertions usinggit.GetWorktreeIndex.
307-366: LGTM! Comprehensive test for index allocation and reuse.The test thoroughly validates the core index allocation behavior:
- Sequential allocation (1, 2)
- Index reuse after deletion (freed index 1 is reused)
Good use of explicit assertions with descriptive error messages.
368-398: LGTM! Clean integration test for list output.The test effectively validates that the INDEX column appears in list output with the expected
#1value for the first worktree.internal/git/git.go (4)
242-242: LGTM!The new
Indexfield is appropriately typed asintand well-documented with a clear comment explaining its purpose.
509-512: LGTM!The index retrieval is consistent with the existing error-handling pattern in this function. Silently falling back to 0 (the zero value) is appropriate since legacy worktrees won't have an index file.
516-527: LGTM!The implementation follows the established pattern for storing worktree metadata. The directory existence check prevents orphaned index files, and the file permissions are appropriate.
529-539: LGTM!The function correctly propagates errors (unlike some other getters that silently return zero values), which is appropriate since callers like
AllocateIndexneed to distinguish between "no index" and "index 0".internal/git/git_test.go (5)
875-919: LGTM!Comprehensive test coverage for
SetWorktreeIndexandGetWorktreeIndex:
- Verifies error on missing index file
- Tests setting and retrieving an index
- Tests updating an existing index
The test properly uses
deferfor cleanup.
921-957: LGTM!Good test of the basic allocation flow, verifying that indexes start at 1 and increment correctly.
959-1006: LGTM!Excellent test coverage for the index reuse algorithm. The test correctly verifies that:
- Freed indexes are reused
- The lowest available index is always chosen
The intentional lack of
deferforwt1andwt2is appropriate here since their removal is part of the test logic.
1008-1056: LGTM!Thorough test of the
maxIndexlimit behavior, covering:
- Failure when limit is reached
- Exact error message validation
- Success with a higher limit
- Success with no limit (
maxIndex=0)
1058-1087: LGTM!Good integration test verifying that
GetWorktreeStatuscorrectly retrieves and populates theIndexfield from the stored metadata.
Implement the WT_INDEX feature as described in IMPLEMENTATION_PLAN.md. Each worktree now receives a stable, reusable numeric identifier useful for port offsets and resource allocation. Key changes: - Add IndexConfig to config.go with optional max limit - Add SetWorktreeIndex, GetWorktreeIndex, AllocateIndex to git.go - Add Index field to hooks.Env, pass WT_INDEX to hooks - Allocate index during wt create, display in wt list - Pass index to pre/post delete hooks in delete and cleanup commands - Add setup-ports.sh example hook demonstrating WT_INDEX usage - Add comprehensive tests for all new functionality Storage: .git/worktrees/<name>/wt-index (auto-cleaned by git) Allocation: Lowest unused index starting at 1 (0 reserved for main) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove # prefix from index in list output (avoids PR reference confusion) - Update README.md with WT_INDEX feature documentation - Update ARCHITECTURE.md with worktree index details - Update CLAUDE.md hook environment vars - Fix test to check for index without # prefix Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
docs/ARCHITECTURE.md (1)
75-81: Consider clarifying two behaviors.The documentation is clear overall. Two optional clarifications:
- "index 0 is reserved for the main repo" - Consider clarifying whether the main repo actually receives index 0 or if WT_INDEX is simply not set for the main repo.
- The
index.maxcap - Consider documenting what happens when the limit is reached (e.g., does creation fail? Is an error returned?).README.md (1)
152-170: Excellent user-facing documentation with practical examples.The use cases and port allocation example (
VITE_PORT=$((5173 + WT_INDEX * 10))) are particularly helpful for users.Optional: Consider adding a brief note about what happens when
index.maxis reached (e.g., "Creation fails if all indexes 1-20 are in use").
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
CLAUDE.mdREADME.mddocs/ARCHITECTURE.mdexamples/hooks/setup-ports.shinternal/commands/cleanup.gointernal/commands/commands_test.gointernal/commands/create.gointernal/commands/delete.gointernal/commands/list.gointernal/config/config.gointernal/config/config_test.gointernal/git/git.gointernal/git/git_test.gointernal/hooks/hooks.gointernal/hooks/hooks_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
- internal/hooks/hooks_test.go
- internal/commands/cleanup.go
- internal/commands/delete.go
- internal/commands/commands_test.go
- internal/commands/list.go
- internal/commands/create.go
🧰 Additional context used
📓 Path-based instructions (3)
internal/config/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Configuration loading and parsing for .wt.yaml files should be in internal/config/ package
Files:
internal/config/config.gointernal/config/config_test.go
internal/git/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
internal/git/**/*.go: Git worktree command wrapping and porcelain output parsing should be in internal/git/ package
Determine if running in main repo vs worktree by checking if .git is a file (worktree) or directory (main repo)
Files:
internal/git/git_test.gointernal/git/git.go
internal/hooks/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
internal/hooks/**/*.go: Lifecycle hook execution should be in internal/hooks/ package
Pass standardized hook environment variables: WT_NAME, WT_PATH, WT_BRANCH, WT_REPO_ROOT, WT_WORKTREE_DIR
Files:
internal/hooks/hooks.go
🧬 Code graph analysis (2)
internal/git/git_test.go (1)
internal/git/git.go (7)
CreateWorktree(25-31)RemoveWorktree(43-53)GetWorktreeIndex(530-539)SetWorktreeIndex(517-527)AllocateIndex(542-567)GetCurrentBranch(105-115)GetWorktreeStatus(471-514)
internal/config/config_test.go (1)
internal/config/config.go (1)
Config(21-27)
🔇 Additional comments (20)
CLAUDE.md (1)
39-41: LGTM!The documentation accurately describes the new WT_INDEX environment variable and the worktree index feature. The hook environment section now properly includes all standardized variables as per the coding guidelines.
internal/config/config.go (2)
15-18: LGTM!Clean struct definition with appropriate YAML tag. The comment clarifies that 0 means no limit, which is the correct default behavior.
26-26: LGTM!The Index field is properly integrated into the Config struct. The zero-value default (Max=0, no limit) is appropriate and requires no explicit initialization in DefaultConfig().
internal/config/config_test.go (1)
99-124: LGTM!Good test coverage for the new IndexConfig field, testing both explicit configuration and default behavior. The tests follow the existing table-driven pattern in the file.
internal/hooks/hooks.go (2)
20-20: LGTM!The Index field is appropriately added to the Env struct to support passing WT_INDEX to hooks.
24-36: LGTM!The conditional inclusion of WT_INDEX when
Index > 0correctly implements the design where index 0 is reserved for the main repo. The refactoring to use a local slice with conditional append is clean.internal/git/git.go (5)
242-242: LGTM!The Index field is properly added to WorktreeStatus to surface the worktree index in status reporting.
509-511: LGTM!Consistent with the error-handling pattern used elsewhere in this function (e.g., CreatedAt, initialCommit). Missing or unreadable index defaults to 0.
516-526: LGTM!The function properly validates the worktree directory exists before writing, preventing writes to non-existent worktrees. File permissions (0644) are appropriate for this metadata file.
529-538: LGTM!Returns an error when the file doesn't exist, allowing callers to distinguish between "index not set" and "index is 0". This is appropriate since index 0 is reserved for the main repo.
541-566: LGTM!The allocation algorithm correctly:
- Handles missing worktrees directory (new repos)
- Scans existing indexes and finds the lowest unused
- Reserves 0 for main repo by starting at 1
- Enforces maxIndex limit when configured
internal/git/git_test.go (5)
875-919: LGTM!Comprehensive test for Set/Get operations including the initial error state when no index file exists, basic set/get, and update scenarios.
921-957: LGTM!Good test coverage for basic allocation behavior, verifying that index 1 is returned first and subsequent allocations find the next available index.
959-1006: LGTM!Excellent test for index reuse behavior. Verifies that when worktrees are deleted, their indexes become available and the lowest available index is allocated next.
1008-1056: LGTM!Thorough boundary testing for the maxIndex limit, including error case when limit is reached, success with higher limit, and the no-limit (max=0) scenario.
1058-1087: LGTM!Good integration test verifying that GetWorktreeStatus correctly includes the index field from the persisted wt-index file.
examples/hooks/setup-ports.sh (1)
1-39: LGTM!Well-documented example hook demonstrating a practical use case for WT_INDEX. The script:
- Gracefully handles missing WT_INDEX
- Uses clear port offset calculation (WT_INDEX * 10)
- Writes a sourceable env file for downstream tooling
- Provides helpful output messages
Good addition to the examples.
docs/ARCHITECTURE.md (1)
73-73: LGTM!Clear and concise documentation of the WT_INDEX environment variable.
README.md (2)
150-150: LGTM!Consistent with the ARCHITECTURE.md documentation.
224-224: LGTM!Good cross-reference to the example hook that demonstrates WT_INDEX usage.
Summary
.git/worktrees/<name>/wt-index(auto-cleaned by git)index.maxconfig to limit maximum worktreesChanges
IndexConfigwithmaxfield for optional limitSetWorktreeIndex,GetWorktreeIndex,AllocateIndexfunctionsIndexfield toEnv, passWT_INDEXenvironment variablesetup-ports.shdemonstrating port offset calculationTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Configuration
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.