-
Notifications
You must be signed in to change notification settings - Fork 52
feat: add worktree hooks support for automated setup and cleanup #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Issue: Users need to automate setup tasks when creating new worktrees Reason: Manual setup of development environments, dependencies, and configuration for each new worktree is repetitive and error-prone Solution: - Added WorktreeHook and WorktreeHookConfig types for worktree lifecycle hooks - Implemented post_creation hook that executes after successful worktree creation - Extended ConfigureHooks UI to support both status and worktree hooks - Added HookExecutor utility for consistent hook execution with environment variables - Provided comprehensive documentation and examples in docs/worktree-hooks.md Environment variables available to post creation hooks: - CCMANAGER_WORKTREE_PATH: Path to the newly created worktree - CCMANAGER_WORKTREE_BRANCH: Git branch name of the new worktree - CCMANAGER_GIT_ROOT: Path to the git repository root - CCMANAGER_BASE_BRANCH: The base branch from which the worktree was created 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…st.ts Issue: Test files were unnecessarily split for worktree hook functionality Reason: Having separate test files for the same service creates maintenance overhead and makes it harder to understand the full test coverage Solution: - Merged all hook execution tests into the main worktreeService.test.ts file - Added necessary mocks for configurationManager and HookExecutor - Added default mock for getWorktreeHooks to prevent existing test failures - Removed the separate worktreeService.hooks.test.ts file All tests continue to pass with the same coverage and functionality. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: The hookExecutor module was implemented as a class with static methods, which is unnecessarily complex for simple stateless utility functions. Reason: - Classes with only static methods are an anti-pattern in JavaScript/TypeScript - Simple exported functions are more idiomatic and easier to test - Reduces code complexity without losing any functionality Solution: - Converted HookExecutor class to two exported functions: - executeHook: Base function for executing hooks with environment variables - executeWorktreePostCreationHook: Specific function for worktree hooks - Updated all imports to use the new function exports - Simplified tests by removing mocked unit tests, keeping only integration tests - All functionality remains identical with cleaner, more maintainable code 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…ion screens Issue: The combined hooks configuration screen was cluttered and mixed different types of hooks (status change hooks and worktree lifecycle hooks) in a single interface, making it difficult for users to understand and configure each type independently. Reason: Status hooks and worktree hooks serve different purposes: - Status hooks react to session state changes (idle, busy, waiting) - Worktree hooks trigger on worktree lifecycle events (creation, deletion, etc.) Mixing them in one screen created cognitive load and poor user experience. Solution: Split ConfigureHooks into two separate components: - ConfigureStatusHooks: Manages session status change hooks - ConfigureWorktreeHooks: Manages worktree lifecycle hooks (currently post_creation) Each screen is now focused on its specific domain with appropriate context and environment variables displayed for each hook type. Changes: - Created ConfigureStatusHooks component for status change hooks - Created ConfigureWorktreeHooks component for worktree lifecycle hooks - Updated Configuration menu with separate entries (H for status, T for worktree) - Added comprehensive tests for both new components - Fixed test module mocking to properly handle os.homedir before imports 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: - ConfigureStatusHooks and ConfigureWorktreeHooks components were using useEffect to initialize state - This violates project coding standards that prohibit useEffect usage - Adds unnecessary complexity and side effects for simple initialization Reason: - useEffect is not needed for initializing state with synchronous values - Direct state initialization is cleaner and follows React best practices - Reduces component complexity and improves predictability Solution: - Replaced useEffect with direct state initialization in useState - Removed useEffect import from both components - Initialize statusHooks and worktreeHooks directly with configurationManager values - All tests pass and functionality remains unchanged 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: The documentation didn't clearly state that hooks execute in the worktree directory by default, which could confuse users about the execution context. Reason: Users need to understand where their hook commands run to write effective hooks. The default behavior (executing in worktree) wasn't documented, and there was no guidance on how to execute commands in the git root if needed. Solution: - Added "Execution Context" section to docs explaining hooks run in worktree directory by default - Documented how to use CCMANAGER_GIT_ROOT environment variable to change to git root - Updated all examples to reflect the default worktree execution context - Added comprehensive tests verifying the execution directory behavior - Merged working directory tests into main hookExecutor.test.ts file 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: The executeStatusHook method was defined in sessionManager.ts but conceptually belonged with other hook execution utilities. Reason: Hook execution logic was scattered across multiple services, making it harder to maintain and test. All hook-related functionality should be centralized for better code organization. Solution: Moved executeStatusHook from sessionManager.ts to hookExecutor.ts as a standalone function, following the same pattern as other hook utilities. This improves code modularity and makes hook execution logic easier to maintain and test. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…error handling Issue: - Hook execution using exec() didn't wait for background processes to complete - Error messages lacked stderr output for debugging failed hooks - Status hooks were not properly awaited Solution: - Replace exec() with spawn() using shell:true to properly wait for all child processes - Include stderr in error messages when hooks fail (exit code \!= 0) - Ignore stderr when hooks succeed (exit code == 0) to avoid log clutter - Make executeStatusHook async to properly await hook completion - Add comprehensive tests for process waiting and stderr handling This ensures hooks complete fully before the operation continues and provides better debugging information when hooks fail. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: Hooks were executing asynchronously (fire-and-forget), potentially causing race conditions and incomplete hook execution before the main operation continued. Reason: The original implementation didn't wait for hook completion, which could lead to: - Worktree creation completing before post-creation hooks finished - Status change hooks overlapping or executing out of order - Hooks not completing their intended side effects before the application proceeded Solution: - Made createWorktree async and added await for executeWorktreePostCreationHook - Added await for executeStatusHook in sessionManager's state detection - Updated IWorktreeService interface to reflect async createWorktree - Updated all call sites to handle the Promise returned by createWorktree - Added error handling to prevent hook failures from breaking main flow This ensures hooks execute synchronously and complete before the application continues, maintaining proper execution order and preventing race conditions. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
… blocking Issue: Status hooks were made blocking in the previous commit, but they should remain non-blocking to avoid slowing down the state detection interval. Reason: Status hooks fire frequently (every 100ms when state changes) and making them blocking could: - Delay state detection and UI updates - Cause the interval to skip cycles if a hook takes longer than 100ms - Create unnecessary performance overhead for non-critical status notifications Solution: - Changed status hook execution to fire-and-forget (non-blocking) using void operator - Removed async from setInterval callback as it's no longer needed - Removed try-catch as executeStatusHook already handles errors internally - Kept worktree hooks blocking as they need to complete before worktree creation returns This ensures proper balance: worktree hooks are blocking (critical for setup), while status hooks are non-blocking (for performance). 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Issue: Test files for hook executor were split unnecessarily into two separate files - hookExecutor.test.ts contained tests for executeHook and executeWorktreePostCreationHook - hookExecutor.statusHook.test.ts contained tests for executeStatusHook - This separation made test maintenance more difficult Reason: Having multiple test files for a single module adds unnecessary complexity - Tests for the same module should be colocated for better organization - Separate files increase cognitive load when understanding test coverage - Duplication of imports and mock setup across files Solution: Merged hookExecutor.statusHook.test.ts into hookExecutor.test.ts - Moved all executeStatusHook tests into main test file - Consolidated mock setup at the top of the file - Maintained all existing test coverage and functionality - Deleted the now-redundant statusHook test file 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds support for executing custom hooks during worktree creation and deletion operations in CCManager. This feature allows users to automate tasks like environment setup, configuration file copying, or cleanup operations when managing worktrees.
Features Added
1. Worktree Hooks
2. Configuration UI
3. Hook Executor Utility
Implementation Details
Testing
Documentation
docs/worktree-hooks.mdBreaking Changes
None. This is a new feature that doesn't affect existing functionality.
Future Enhancements