Skip to content

refactor: one generic hook-entry shim per OS (ADR-0008, #46)#77

Merged
Cannon07 merged 8 commits into
mainfrom
feat/consolidate-hook-entry
Jun 6, 2026
Merged

refactor: one generic hook-entry shim per OS (ADR-0008, #46)#77
Cannon07 merged 8 commits into
mainfrom
feat/consolidate-hook-entry

Conversation

@Cannon07
Copy link
Copy Markdown
Owner

@Cannon07 Cannon07 commented Jun 5, 2026

Consolidates the per-agent hook entries into one generic, parameterized shim per OS — the architecture-review fork (a), recorded as ADR-0008, and the gateway that makes the per-agent Windows rollout cheap.

The change

Post-#47 the per-backend hook entries (backends/<agent>/code-{preview,close}-diff.{sh,ps1}) were near-identical, differing only in data: backend name, pre/post event, and a fast-path tool filter. They're collapsed into:

bin/hook-entry.sh    <backend> <pre|post>
bin/hook-entry.ps1   <backend> <pre|post>

So 10 shim files (→16 with the Windows rollout) become 2. Adding the remaining Windows agents is now "register a name," not "write 6 more .ps1 files." backends/ now holds only OpenCode's TS plugin.

  • lua/code-preview/platform.lua (new) — single home for the OS branch (script_ext / hook_command / make_executable / shim_dependency), replacing logic duplicated across the four installers + health.lua.
  • bin/hook-entry.{sh,ps1} (new) — generic; the per-backend fast-path filter is a backend-keyed branch inside (the normalisers tool map stays the source of truth).
  • All four installers rewired to write hook-entry.<ext> <backend> <event> via platform; stem-based markers (hook-entry + legacy) for idempotent install/uninstall.
  • opencode index.ts execSyncs the shared shim per-OS; opencode.lua copies plugin files with a portable libuv copy (drops cp, a Windows blocker).
  • Deleted all 10 per-backend shims; health.lua checks the shared hook-entry + uses platform.

Behavior

No user-facing behavior change on Unix — same previews, same indicators. Pure structure + the OS-branch centralization.

Tests

Full suite green on macOS: claudecode 15, codex 22, copilot 15, opencode 13, + Lua specs (65 E2E total). The E2E exercises the real generic shim end-to-end against a live nvim for every backend. The opencode harness imports index.ts directly, so it covers the new shim resolution unchanged.

Validation needed on Windows (the one risk)

hook-entry.ps1 is drafted but unvalidated on Windows. The risk (per ADR-0008): the command passes <backend> <event> as positional args to powershell -File hook-entry.ps1 — PS 5.1 lacks PSNativeCommandArgumentPassing. The args are simple alnum tokens (low risk), but need confirming on a real box:

  1. Reinstall (:CodePreviewInstallClaudeCodeHooks — the command string changed).
  2. Confirm an edit previews and a shell delete marks neo-tree via the generic .ps1.

Deferred (not in this PR)

The integration registry / install-engine refactor (the review's bigger fork c) stays deferred. Codex/Copilot/OpenCode Windows enablement is still pending validation, though they're now wired to the generic shim.

🤖 Generated with Claude Code

Cannon07 and others added 8 commits June 5, 2026 20:30
…#46)

First slice of the hook-entry consolidation (ADR-0008): replace the per-backend
code-{preview,close}-diff shims with one generic, parameterized shim per OS.

- lua/code-preview/platform.lua: single home for the per-OS branch
  (script_ext / hook_command / make_executable / shim_dependency), replacing
  logic that was duplicated across installers and health.lua.
- bin/hook-entry.{sh,ps1}: generic hook entry, invoked as `<backend> <pre|post>`.
  Reads stdin, per-backend fast-path filter, discovers nvim, single RPC. The
  .sh handles all backends; the .ps1 is drafted for Windows validation.
- claudecode.lua: install writes `hook-entry.<ext> claudecode pre|post` via
  platform; marker matching is stem-based (hook-entry + legacy code-preview).
- Delete backends/claudecode/code-{preview,close}-diff.{sh,ps1}.
- health.lua: check the shared hook-entry shim; use platform.shim_dependency.
- Tests: helpers + stale-socket + install tests point at the generic shim.

codex/copilot/opencode still use their own shims (migrated in follow-up
commits). Full suite green on macOS (65 E2E + Lua specs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
codex.lua now writes `hook-entry.<ext> codex pre|post` via platform (its
fast-path tool filter already lives in hook-entry.sh); markers gain "hook-entry"
(legacy code-preview-diff/code-close-diff kept for upgrade cleanup); chmod goes
through platform.make_executable. Deletes backends/codex/*.sh. health.lua drops
the codex adapter check (shared shim covers it). Tests point at the generic shim.

Codex E2E 22/22, full suite 65/65 on macOS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
copilot.lua now writes its `bash` hook field as `'<hook-entry.sh>' copilot
pre|post` (the field runs under bash, so it always invokes the .sh — no
PowerShell wrapper; copilot-on-Windows would need git-bash and stays deferred).
is_our_config matches "hook-entry" (legacy code-preview-diff kept); chmod via
platform.make_executable. Deletes backends/copilot/*.sh. health.lua drops the
copilot adapter check. Tests point at the generic shim.

Copilot E2E 15/15, full suite 65/65 on macOS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
index.ts now execSyncs the shared bin/hook-entry.{sh,ps1} as `opencode pre|post`
(per-OS: powershell -File on Windows, direct on Unix) instead of the per-backend
backends/opencode/code-*-diff.sh. opencode.lua copies plugin files with a
portable libuv copy (drops `cp`, a Windows blocker) and makes bin/hook-entry.sh
executable via platform. Deletes backends/opencode/*.sh — backends/ now holds
only opencode's TS plugin.

The opencode test harness imports index.ts directly, so it exercises the new
shim resolution unchanged. OpenCode E2E 13/13, full suite 65/65 on macOS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…46)

Records the decision to collapse the per-agent hook entries into one generic
parameterized shim per OS (bin/hook-entry.{sh,ps1}), and updates the Hook entry
/ Integration glossary terms to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ranch (#46)

CLAUDE.md, the PRD-*.md / ROADMAP.md / REFACTOR-PLAN.md / pr-description.md
working notes were untracked in the repo before this work and got picked up by
a `git add -A`. Untrack them (kept on disk) so the PR contains only the
consolidation changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… review)

1. health.lua: the inline .claude/settings parse keyed off "code-preview" /
   "claude-preview" substrings, which mis-fired after the hook-entry rename — a
   fresh install was flagged "legacy" whenever the plugin lived under a
   claude-preview.nvim directory (the path, not the command, matched). Delegate
   to claudecode.install_state() (matches the "hook-entry" marker by command
   shape), mirroring the codex pattern. Removes the bug and the duplication.

2. hook-entry.ps1: rename param $Event -> $HookEvent ($Event is a PowerShell
   automatic variable; harmless here but a known foot-gun).

Verified on macOS: checkhealth reports "installed" correctly; full suite 65/65.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes the "must validate on a real box" risk: the multi-token command field
is confirmed on the two paths that needed it — claudecode on Windows (PS 5.1,
powershell -File hook-entry.ps1 claudecode pre) and codex on macOS (bare-path →
hook-entry.sh codex pre). Both shell-exec, so the args arrive intact and no .cmd
trampoline is needed; this also settles ADR-0007's per-agent-invocation spike
for codex. Copilot (bash field) and opencode (explicit execSync) are multi-token
-safe by construction. Codex/copilot/opencode on Windows remain deferred.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Cannon07 Cannon07 merged commit b77392b into main Jun 6, 2026
3 checks passed
@Cannon07 Cannon07 deleted the feat/consolidate-hook-entry branch June 6, 2026 04: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