Skip to content

feat(daemon): add MULTICA_POST_CHECKOUT_HOOK for repo checkout extensibility#3309

Open
medi1-3 wants to merge 1 commit into
multica-ai:mainfrom
medi1-3:feat/post-checkout-hook
Open

feat(daemon): add MULTICA_POST_CHECKOUT_HOOK for repo checkout extensibility#3309
medi1-3 wants to merge 1 commit into
multica-ai:mainfrom
medi1-3:feat/post-checkout-hook

Conversation

@medi1-3
Copy link
Copy Markdown

@medi1-3 medi1-3 commented May 26, 2026

Summary

Adds an opt-in MULTICA_POST_CHECKOUT_HOOK environment variable. When set to an executable path, the daemon runs that script after every successful worktree create or update in repocache.CreateWorktree. The hook receives the worktree as CWD and the following env vars: MULTICA_WORKTREE_PATH, MULTICA_REPO_URL, MULTICA_REPO_NAME, MULTICA_BRANCH.

Why

Self-hosted deployments often need to materialize per-repo state into the worktree immediately after checkout — typical examples:

  • Per-repo secret injection — write .env from an external secret store (Infisical, Vault, Doppler) so dotenv-based tooling (pnpm dev, pytest, python-dotenv) just works once the agent cds in.
  • Per-repo bootstrappnpm install, python -m venv .venv, poetry install, etc.
  • Per-repo skill files — drop project-specific skill markdown into the worktree.

Today, agents must remember to run such steps manually after multica repo checkout. A daemon-level hook makes the bootstrap step transparent and reliable.

Design

  • Fire-and-log: failures are warnings, not errors. Checkout always succeeds for the agent regardless of hook outcome.
  • 30s timeout via context.WithTimeout so a hung hook cannot stall task spawning.
  • Defensive validation: missing path / directory / non-executable file are skipped with a warning rather than executed or panicked.
  • No new dependency on Config. Read directly via os.Getenv, matching the gitEnv pattern already used in this file.
  • Idempotent at the daemon level: the hook runs after both fresh worktree creation AND worktree update — so on a reused environment, the hook gets a chance to refresh whatever it manages.

Behavior matrix

MULTICA_POST_CHECKOUT_HOOK Result
Unset / empty No-op (default behavior unchanged)
Path to executable file Hook runs; output logged at INFO if exit 0, WARN with stderr if non-zero
Path to missing file WARN + skip
Path to directory WARN + skip
Path to non-executable file WARN + skip
Hook exits non-zero WARN + checkout still succeeds
Hook exceeds 30s Killed via context cancellation + WARN

Test plan

  • Unit tests cover: no-op (unset), happy path (env vars + CWD reach the hook), missing path, non-executable file, non-zero exit. All in cache_test.go.
  • go test ./internal/daemon/repocache/ — passes
  • go test ./internal/daemon/... — passes (no regression in sibling packages)
  • Manual e2e on a self-hosted instance with a real hook that writes a .env file — pending (will report in a comment).

Compatibility

Fully backwards compatible. The env var defaults to unset, in which case behavior is identical to today's.

After repocache.CreateWorktree completes (either fresh worktree or update
of an existing one), invoke the executable at MULTICA_POST_CHECKOUT_HOOK
if the env var is set and points to an executable file.

The hook is invoked with the worktree as CWD and these env vars set so it
can act without re-deriving them from CWD or git state:

  MULTICA_WORKTREE_PATH  absolute path to the worktree
  MULTICA_REPO_URL       URL passed to `multica repo checkout`
  MULTICA_REPO_NAME      basename of the worktree path
  MULTICA_BRANCH         actual branch name on the worktree

Behavior:

  - Unset/empty MULTICA_POST_CHECKOUT_HOOK is a no-op (default).
  - Missing path, directory, or non-executable file is logged at WARN
    and skipped — never aborts the checkout.
  - Hook exit non-zero is logged at WARN with stdout+stderr; checkout
    still succeeds.
  - 30s timeout caps hook runtime so a hung hook can't stall task spawn.

Use cases: materializing per-repo .env files from an external secret
store, dropping skill files into the worktree, running language-specific
project bootstrap (`pnpm install`, `python -m venv`, etc.) before the
agent starts.

Tests cover: unset (no-op), happy path (env vars + CWD reach the hook),
non-executable file (skipped), missing path (skipped), non-zero exit
(non-fatal).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

@medi1-3 is attempting to deploy a commit to the IndexLabs Team on Vercel.

A member of the Team first needs to authorize it.

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