Skip to content

Add Claude Code hooks integration#8

Merged
bkildow merged 5 commits intomainfrom
feature/claude-hooks
Mar 20, 2026
Merged

Add Claude Code hooks integration#8
bkildow merged 5 commits intomainfrom
feature/claude-hooks

Conversation

@bkildow
Copy link
Copy Markdown
Owner

@bkildow bkildow commented Mar 20, 2026

Summary

  • Adds wt claude init command to configure Claude Code WorktreeCreate/WorktreeRemove hooks in .claude/settings.local.json
  • Adds hidden wt claude hook-worktree-create and wt claude hook-worktree-remove subcommands that Claude Code invokes via hooks
  • New internal/claude package for settings file management (deep-merge, idempotency, removal)

When configured, Claude Code agents get properly scaffolded worktrees in the project's worktrees/ directory with shared files applied and setup hooks launched in background — matching wt add and wt remove behavior.

Test plan

  • Unit tests pass: go test -short ./... (15 new tests across cmd/ and internal/claude/)
  • Lint passes: golangci-lint run ./cmd/ ./internal/claude/
  • Manual: Run wt claude init in a wt project, verify .claude/settings.local.json has hooks
  • E2E: Pipe JSON to wt claude hook-worktree-create, verify worktree created with shared files
  • E2E: Pipe JSON to wt claude hook-worktree-remove, verify worktree and branch removed

bkildow added 5 commits March 20, 2026 11:52
Introduces `wt claude init` to configure WorktreeCreate and WorktreeRemove
hooks in .claude/settings.local.json, plus hidden `wt claude hook-worktree-create`
and `wt claude hook-worktree-remove` subcommands that Claude Code invokes
automatically. This gives Claude Code agents properly scaffolded worktrees
with shared files, setup hooks, and teardown — matching `wt add`/`wt remove`.
readHookPayload used io.ReadAll which blocks until EOF — if Claude Code
doesn't close the stdin pipe promptly, the hook hangs indefinitely.
Replace with json.NewDecoder which returns after parsing one JSON object.

Also fix hookPayload struct to match the actual Claude Code schema:
worktree_name → name, remove project_dir (not in any payload), add
transcript_path. Update WorktreeRemove handler to derive branch name
from worktree_path since the remove payload doesn't include name.

Fix pre-existing lint issues in exclude.go (file permissions, unchecked
Close error).
Redirect background child process stdio to /dev/null explicitly to
prevent fd inheritance hangs. Write hooks to shared/symlink so all
worktrees receive them via symlink, and apply to existing worktrees
on init. Skip git fetch in hook handler (blocked by sandbox). Use
hook event name constants instead of string literals.
When a symlink destination already exists as a real directory (e.g.
.claude/ created by Claude Code), recurse into it and symlink individual
files instead of trying to replace the whole directory. This preserves
worktree-local files while still symlinking shared config files like
settings.local.json.
Document the Claude Code integration: features bullet, commands table
entry, detailed usage section, and project layout diagram update.
@bkildow bkildow merged commit bd208f6 into main Mar 20, 2026
@bkildow bkildow deleted the feature/claude-hooks branch March 20, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant