Appearance
Hooks
daft hooks define clear boundaries as your code evolves. They are a local, parallel approach to GitHub Actions — every stage of code's lifecycle gets a well-defined gate.
Each stage in your code's journey through development has different needs:
- When you start isolated work, you want the right env booted up
- When you commit a change, you want format/lint/fast-tests to gate it
- When you merge, you want the equivalent of PR checks to gate it
- When you tear down a worktree, you want artifacts persisted and state reclaimed
daft models each of these as a hook stage. They share one configuration system, one trust model, one job orchestrator.
The boundaries
| Stage | Hook type | Boundary semantics | Status |
|---|---|---|---|
| End of clone setup | post-clone | One-shot bootstrap of a fresh repo | Shipped |
| Start of isolated dev | Worktree hooks (worktree-pre/post-create) | Set up local dev env (deps, services) | Shipped |
| Sealing a unit of change | Commit hooks | Progressive code-replication boundary — format, lint, fast tests before the change is recorded | Roadmap (#468) |
| Letting a change escape isolation | Merge hooks (pre-merge, post-merge) | PR-check parity — full tests, integration, security gates before code leaves the branch | Shipped |
| Reclaiming an isolated env | Worktree teardown (worktree-pre/post-remove) | Teardown, persist artifacts, sync state | Shipped |
How daft hooks differ from lefthook
Two distinctions:
- Lefthook is commit-time-only. daft covers the full code-evolution lifecycle. Commit hooks are one stage among many — they share the trust model, the YAML schema, and the job orchestrator with worktree-lifecycle hooks. (See #468 for the lefthook drop-in plan.)
- Boundaries before changes leave your machine. CI traditionally runs after code reaches the central repo; daft hooks run before. CI shifts left.
daft and your existing git hooks
daft's hooks do not replace git's own. Every daft-initiated git push honors the repository's pre-push hook — whether it lives in .git/hooks or is managed by lefthook, husky, or pre-commit via core.hooksPath. A failing pre-push gate blocks the push and fails the command; its run is reported as a pre-push phase on the same surface lifecycle hooks use. The one conditional site is the automatic upstream push on branch creation: it consults the hook only when it would publish commits the remote does not already have, so branching off a fully-pushed base skips it (tunable via daft.checkout.pushVerify). Pass --no-verify to any pushing command to skip it for one invocation. And because the shared hook always runs in the pushed branch's own worktree under daft push, that command is the way to push another worktree's branch without the hook validating the wrong tree. See Git Hooks for the details.
Where to next
- Reference: Lifecycle hooks — types, triggers, env vars, exit-code semantics
- Reference: YAML reference — the full
daft.ymlschema - Concept: Job orchestration — parallelism, dependencies, conditions, OS/arch gating
- Concept: Trust & security — why hooks need trust and how the model works
- Status: Roadmap — what's coming for commit-stage hooks
- Recipes: Recipes for Hooks
- CI parity: Recipes → CI parity — run the same
daft.ymllocally and in CI