Skip to content

feat: add git-worktree lifecycle hooks (bootstrap, staleness, GC)#167

Merged
aagnone3 merged 1 commit into
mainfrom
claude/funny-johnson-9k2bze
Jul 16, 2026
Merged

feat: add git-worktree lifecycle hooks (bootstrap, staleness, GC)#167
aagnone3 merged 1 commit into
mainfrom
claude/funny-johnson-9k2bze

Conversation

@aagnone3

Copy link
Copy Markdown
Collaborator

What & why

Claude Code creates session worktrees under .claude/worktrees/<name> with a bare git worktree addno dependency install, no gitignored-env copy, and no cleanup after the branch merges. The plugin's existing git-worktree skill only helps when a human runs its manager script by hand; it does nothing for the worktrees the harness spins up itself (parallel/web sessions and isolation:"worktree" subagents). So every harness-created worktree currently starts unusable — missing .env files, uninstalled deps — and merged worktrees pile up locally forever.

This PR adopts and generalizes the battle-tested worktree lifecycle scripts from the BlueStar monorepo (Life-With-Data/bluestar-intelsetup-worktree.sh, check-stale-worktree.sh, gc-worktrees.sh) into two reusable, project-agnostic plugin hooks. Those scripts already solve the exact problem, but were hard-wired to that repo (pnpm, Prisma, Node 22, origin/main); this ports the reusable logic and strips the project specifics.

Changes

scripts/worktree-session.pySessionStart (startup), ships (wired into plugin.json). No-op outside a .claude/worktrees/* tree (main tree, non-git dir, hand-made worktree → silent). Inside one it:

  1. Copies gitignored env files (.env, .env.local, one/two levels of */.env*) from the main tree.
  2. Runs an opt-in bootstrap command once ($AGENTIC_WORKTREE_BOOTSTRAP_CMD, e.g. "pnpm install"), gated on a marker so later sessions pay nothing.
  3. Emits a non-destructive staleness advisory when the branch is already merged — detected with git cherry so squash/rebase merges (different SHAs) are caught, while a fresh commit-less branch or one with unmerged work stays silent.

scripts/gc-worktrees.py — a destructive GC of merged worktrees + local branches for a git post-merge hook. Deliberately not auto-wired anywhere (every other plugin hook is a safety net; this deletes things). Guarded by clean-tree, fully-merged (git cherry), and activity-window (default 30 min) checks so a concurrent live session is never yanked. Install instructions in HOOKS.md.

Design choices matching existing plugin conventions:

  • Env-var config, not agentic-engineering.local.md frontmatter — mirrors the sdd-cache precedent: which command installs deps (and whether to bootstrap at all) is a per-machine choice that shouldn't ride a PR and flip behavior for every clone. This also keeps the scripts out of the config_registry.py surface.
  • Python3, stdlib only — matches the plugin's "Python implementations shared across harnesses" rule and its unittest suite.
  • Fail-open, always exit 0 — a broken bootstrap/GC hook can never block a session start or a git pull.
  • Claude-only — Cursor/Codex expose no SessionStart worktree event, so documented Claude-primary like plan-tracker-guard.py.

How to integrate / enable

worktree-session.py ships enabled and is inert until you're in a harness worktree. To auto-install deps there, export AGENTIC_WORKTREE_BOOTSTRAP_CMD (e.g. "pnpm install"). To enable GC, install gc-worktrees.py as a post-merge git hook (snippet in HOOKS.md). WORKTREE_BOOTSTRAP=0 / WORKTREE_GC=0 opt out.

Tests

  • New tests/worktree_session_test.py (6 cases) builds a real throwaway repo + harness-shaped worktree and pins: no-op fast paths, env-copy, missing-deps nudge, fresh-branch-not-stale, and merged-branch-stale (via a divergent-then-cherry-picked commit so the landed patch has a realistic squash-merge SHA).
  • python3 -m unittest discover -s plugins/agentic-engineering/tests -p '*_test.py'323 pass.
  • bun test491 pass, bun run docs:check clean, bun run typecheck clean.

Other opportunities surveyed (not included here)

While cataloging the source repos I also looked at bluestar-intel's ralph-loop plugin (Stop-hook autonomous iteration loop) and agent-leverage's hookify.*.local.md declarative guard rules. Both overlap with capabilities the plugin/harness already provide (orchestrating-swarms//loop; block-no-verify) or depend on an external plugin, so I left them out to keep this PR focused on the one clear, self-contained gap. Happy to follow up on either if useful.

🤖 Generated with Claude Code


Generated by Claude Code

Adopt and generalize the BlueStar monorepo's worktree lifecycle scripts as
reusable plugin hooks. Claude Code creates session worktrees under
.claude/worktrees/<name> with a bare `git worktree add` — no dependency
install, no gitignored-env copy, and no cleanup after merge. The existing
git-worktree skill only helps when a human runs its manager by hand; it does
nothing for the worktrees the harness spins up itself (parallel/web sessions
and isolation:"worktree" subagents). These hooks close that gap.

- worktree-session.py (SessionStart/startup, ships): inside a
  .claude/worktrees/* tree, copies gitignored env files, runs an opt-in
  bootstrap command ($AGENTIC_WORKTREE_BOOTSTRAP_CMD), and emits a
  non-destructive staleness advisory when the branch is already merged
  (git cherry, so squash/rebase merges are caught). No-op everywhere else.
- gc-worktrees.py (manual git post-merge hook, not auto-wired): destructive
  GC of merged worktrees + local branches, guarded by clean-tree, merged, and
  activity-window checks.

Config is by environment variable (matching the sdd-cache precedent), so
per-machine behavior can't ride a PR. Both fail open and always exit 0.
Generalized from project-specific pnpm/Prisma/Node logic. Wired into
plugin.json (Claude SessionStart) and documented in HOOKS.md with unittest
coverage (tests/worktree_session_test.py).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@aagnone3
aagnone3 merged commit d513a79 into main Jul 16, 2026
7 checks passed
@aagnone3
aagnone3 deleted the claude/funny-johnson-9k2bze branch July 16, 2026 23:44
@github-actions github-actions Bot mentioned this pull request Jul 16, 2026
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.

2 participants