Skip to content

feat(hooks): add flexible project-managed hooks system#62

Merged
avihut merged 8 commits intodevelopfrom
daft-7/hooks
Jan 23, 2026
Merged

feat(hooks): add flexible project-managed hooks system#62
avihut merged 8 commits intodevelopfrom
daft-7/hooks

Conversation

@avihut
Copy link
Owner

@avihut avihut commented Jan 23, 2026

Summary

Adds a comprehensive hooks system for worktree lifecycle events, replacing the hardcoded direnv integration with a flexible, project-managed approach.

Features

  • Six hook types: post-clone, post-init, pre-create, post-create, pre-remove, post-remove
  • Trust-based security model: Repositories must be explicitly trusted before hooks execute
  • Trust management CLI: git daft hooks trust/untrust/status/list commands
  • Clone flags: --trust-hooks to trust and run hooks, --no-hooks to skip
  • Rich environment variables: Hooks receive context via DAFT_* environment variables
  • Project-managed hooks: Stored in .daft/hooks/ within repositories

Implementation

  • Core infrastructure: hook types, discovery, configuration (src/hooks/)
  • Trust database with pattern matching support (src/hooks/trust.rs)
  • Hook executor with timeout and fail mode handling (src/hooks/executor.rs)
  • Environment variable builder (src/hooks/environment.rs)
  • Integration with clone, checkout, checkout-branch, checkout-branch-from-default, init, and prune commands
  • Comprehensive unit and integration tests

Breaking Changes

  • Removed built-in direnv integration (users can replicate with post-create hook)

Test plan

  • cargo test - 78 unit tests pass
  • cargo clippy -- -D warnings - clean
  • just test-integration-hooks - 11 integration tests pass
  • just test-integration - all integration tests pass
  • Manual testing with direnv hooks

Fixes #7

🤖 Generated with Claude Code

avihut and others added 7 commits January 23, 2026 09:58
Implement Phase 1 of the hooks system with:

- Hook types: PostClone, PostInit, PreCreate, PostCreate, PreRemove, PostRemove
- Trust management with Deny/Prompt/Allow levels stored in ~/.config/daft/trust.json
- Pattern-based trust rules with glob matching
- Environment variable builder for hook execution context
- Hook executor with timeout support and fail modes (abort/warn)
- Git config integration for hooks settings (daft.hooks.*)
- Hook discovery from project (.daft/hooks/) and user (~/.config/daft/hooks/) directories

This replaces the hardcoded direnv integration with a flexible, project-managed
hooks system similar to GitHub Actions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `git daft hooks` subcommand for managing repository trust:
- `trust` - Trust a repository to run hooks (with --prompt option)
- `untrust` - Revoke trust from a repository
- `status` - Show trust status and available hooks
- `list` - List all trusted repositories

The command is accessible via:
- `daft hooks <subcommand>`
- `git daft hooks <subcommand>`

Also updates documentation to include hooks commands and
reflects the new hooks system in key features.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Integrate the hooks system into all worktree-related commands:

- clone.rs: Add post-clone hook with --trust-hooks/--no-hooks flags
  - New repos show hooks notice if untrusted
  - --trust-hooks flag automatically trusts and runs hooks
  - --no-hooks flag skips hooks without prompting

- init.rs: Add post-init hook
  - Newly initialized repos are automatically trusted
  - Hook runs after worktree creation

- checkout.rs: Add pre-create and post-create hooks
  - Pre-create hook runs before worktree creation
  - Post-create hook replaces direnv integration
  - Removed direct direnv calls

- checkout_branch.rs: Add pre-create and post-create hooks
  - Same hook pattern as checkout
  - Includes base branch in context for hooks

- prune.rs: Add pre-remove and post-remove hooks
  - Pre-remove runs before each worktree removal
  - Post-remove runs after each worktree removal
  - Hooks receive RemovalReason::RemoteDeleted context

Also:
- Export RemovalReason from hooks module
- Remove direnv imports from command files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove src/direnv.rs (replaced by hooks system)
- Remove pub mod direnv from lib.rs
- Update command docstrings to reference hooks instead of direnv
- Add comprehensive Hooks System section to README.md
- Update CLAUDE.md with hooks system documentation
- Update architecture diagrams to show hooks module

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 15 new unit tests for hook discovery functions:
  - find_hooks(), hook_exists(), list_hooks()
  - Tests for project hooks, user hooks, and both combined
  - Non-executable hooks are correctly ignored on Unix
  - HookType and HooksConfig accessor coverage

- Add integration test suite (tests/integration/test_hooks.sh):
  - Trust/security: untrusted repos skip hooks, trust commands work
  - Clone flags: --no-hooks and --trust-hooks behavior
  - Hook execution: environment variables, abort behavior
  - 11 integration tests covering the full hooks lifecycle

- Update justfile with test-integration-hooks recipe
- Update test_all.sh to include hooks tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Clone command now executes post-create hook after creating the initial
  worktree, ensuring hooks like direnv integration run on first clone
- Hook executor now adds newlines after each line of hook output, fixing
  an issue where hook output would run together with the __DAFT_CD__
  marker and break shell integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@avihut avihut changed the title fix(hooks): run post-create hooks during clone and fix output newlines feat(hooks): add flexible project-managed hooks system Jan 23, 2026
@avihut avihut self-assigned this Jan 23, 2026
@avihut avihut added the enhancement New feature or request label Jan 23, 2026
@avihut avihut added this to the v1.0.0 milestone Jan 23, 2026
@avihut avihut linked an issue Jan 23, 2026 that may be closed by this pull request
Closed
24 tasks
The implementation plan is now maintained in GitHub issue #7 rather than
as a separate documentation file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@avihut avihut merged commit 2c017f6 into develop Jan 23, 2026
@avihut avihut deleted the daft-7/hooks branch January 23, 2026 10:26
avihut added a commit that referenced this pull request Jan 24, 2026
* docs(hooks): comprehensive hooks plan

* feat(hooks): add core infrastructure for hooks system

Implement Phase 1 of the hooks system with:

- Hook types: PostClone, PostInit, PreCreate, PostCreate, PreRemove, PostRemove
- Trust management with Deny/Prompt/Allow levels stored in ~/.config/daft/trust.json
- Pattern-based trust rules with glob matching
- Environment variable builder for hook execution context
- Hook executor with timeout support and fail modes (abort/warn)
- Git config integration for hooks settings (daft.hooks.*)
- Hook discovery from project (.daft/hooks/) and user (~/.config/daft/hooks/) directories

This replaces the hardcoded direnv integration with a flexible, project-managed
hooks system similar to GitHub Actions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(hooks): add trust management command (Phase 2)

Add `git daft hooks` subcommand for managing repository trust:
- `trust` - Trust a repository to run hooks (with --prompt option)
- `untrust` - Revoke trust from a repository
- `status` - Show trust status and available hooks
- `list` - List all trusted repositories

The command is accessible via:
- `daft hooks <subcommand>`
- `git daft hooks <subcommand>`

Also updates documentation to include hooks commands and
reflects the new hooks system in key features.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(hooks): integrate hooks into existing commands (Phase 3)

Integrate the hooks system into all worktree-related commands:

- clone.rs: Add post-clone hook with --trust-hooks/--no-hooks flags
  - New repos show hooks notice if untrusted
  - --trust-hooks flag automatically trusts and runs hooks
  - --no-hooks flag skips hooks without prompting

- init.rs: Add post-init hook
  - Newly initialized repos are automatically trusted
  - Hook runs after worktree creation

- checkout.rs: Add pre-create and post-create hooks
  - Pre-create hook runs before worktree creation
  - Post-create hook replaces direnv integration
  - Removed direct direnv calls

- checkout_branch.rs: Add pre-create and post-create hooks
  - Same hook pattern as checkout
  - Includes base branch in context for hooks

- prune.rs: Add pre-remove and post-remove hooks
  - Pre-remove runs before each worktree removal
  - Post-remove runs after each worktree removal
  - Hooks receive RemovalReason::RemoteDeleted context

Also:
- Export RemovalReason from hooks module
- Remove direnv imports from command files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: remove direnv.rs and update documentation (Phase 4)

- Remove src/direnv.rs (replaced by hooks system)
- Remove pub mod direnv from lib.rs
- Update command docstrings to reference hooks instead of direnv
- Add comprehensive Hooks System section to README.md
- Update CLAUDE.md with hooks system documentation
- Update architecture diagrams to show hooks module

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(hooks): add comprehensive tests for hooks system (Phase 5)

- Add 15 new unit tests for hook discovery functions:
  - find_hooks(), hook_exists(), list_hooks()
  - Tests for project hooks, user hooks, and both combined
  - Non-executable hooks are correctly ignored on Unix
  - HookType and HooksConfig accessor coverage

- Add integration test suite (tests/integration/test_hooks.sh):
  - Trust/security: untrusted repos skip hooks, trust commands work
  - Clone flags: --no-hooks and --trust-hooks behavior
  - Hook execution: environment variables, abort behavior
  - 11 integration tests covering the full hooks lifecycle

- Update justfile with test-integration-hooks recipe
- Update test_all.sh to include hooks tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(hooks): run post-create hooks during clone and fix output newlines

- Clone command now executes post-create hook after creating the initial
  worktree, ensuring hooks like direnv integration run on first clone
- Hook executor now adds newlines after each line of hook output, fixing
  an issue where hook output would run together with the __DAFT_CD__
  marker and break shell integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: move hooks plan from docs to issue #7

The implementation plan is now maintained in GitHub issue #7 rather than
as a separate documentation file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hooks

1 participant