Files
max-sixty__worktrunk/plugins/worktrunk/hooks/wt.sh
T
Maximilian Roos d22917702e refactor(plugins): consolidate Claude + Codex into one payload dir (#2789)
The Claude plugin lived at the repo root (`.claude-plugin/`) while the
Codex plugin lived in `plugins/worktrunk/` — two homes for one logical
plugin, with the description string duplicated across both and drifting
independently. This collapses them into a single payload directory.

**What moved.** `git mv
.claude-plugin/{plugin.json,hooks/,CLAUDE.md,README.md} →
plugins/worktrunk/` (history-preserving renames). The repo root keeps
only the two marketplace pointers — Claude and Codex each hardcode their
marketplace path with no fallback, so two pointer files is the
irreducible floor. Both pointers' `source` now resolves to
`./plugins/worktrunk`. `.claude-plugin/` is now a single 2-line file.

**The load-bearing constraint** (verified live against claude-cli
2.1.x): for a *subdirectory* `source`, Claude expects `plugin.json` at
the plugin root **without** a `.claude-plugin/` wrapper — that wrapper
is marketplace-root-only. (First attempt with the wrapper failed `Plugin
not found`; the corrected layout installs cleanly.) Codex keeps its own
required `.codex-plugin/` wrapper. So inside `plugins/worktrunk/`:
`plugin.json` is Claude's, `.codex-plugin/plugin.json` is Codex's,
`hooks/` is Claude's, `skills → ../../skills` is shared.

**Path edits inside moved files:** `plugin.json` `hooks` →
`./hooks/hooks.json`; `hooks.json`
`${CLAUDE_PLUGIN_ROOT}/.claude-plugin/hooks/wt.sh` →
`${CLAUDE_PLUGIN_ROOT}/hooks/wt.sh`.

**Reviewer navigation:** `git log` shows the moves as renames.
`plugins/worktrunk/CLAUDE.md` was rewritten to document the unified
layout + per-tool path resolution; the repo `CLAUDE.md` "Plugin Layout"
section likewise. `tests/integration_tests/config_show.rs` adds
`test_plugin_layout_is_consolidated`, which locks the layout invariants
(`.claude-plugin/` is marketplace-only, Claude manifest at plugin root,
hooks relative to it) **and** asserts the duplicated Claude description
stays byte-identical across the marketplace pointer and the manifest —
that was the standing follow-up; JSON can't `include!`, so a drift test
is the right tool, not a generator.

**Verification:** Live end-to-end on both real CLIs, twice — once with
copied skill dirs, once mirroring the real tree *including the
`plugins/worktrunk/skills` symlink* (Claude's `skills` array resolves
through it). Full pre-merge gate green: 3720 passed, 0 skipped, all
pre-commit lints, no snapshot churn. No user-facing docs/help text
changed (the consolidation is repo-internal), so `test_docs_are_in_sync`
needed no resync.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:35:25 -07:00

40 lines
1.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Cross-platform wrapper for the worktrunk CLI.
# If WORKTRUNK_BIN is set, uses that path exclusively.
# Otherwise, on Windows (MSYS/Cygwin), prefers git-wt.exe over wt and
# rejects wt if it resolves to Windows Terminal (.../WindowsApps/wt.exe).
# On other platforms, uses wt directly.
# Usage: wt.sh [args...]
if [[ -n "$WORKTRUNK_BIN" ]]; then
if ! command -v "$WORKTRUNK_BIN" >/dev/null 2>&1; then
echo "worktrunk: WORKTRUNK_BIN is set to '$WORKTRUNK_BIN' but it was not found" >&2
exit 1
fi
WT="$WORKTRUNK_BIN"
elif [[ "$(uname -o 2>/dev/null)" =~ ^(Msys|Cygwin)$ ]]; then
# check for bash on Windows (on Windows, Claude Code defaults to Git Bash)
if command -v git-wt.exe >/dev/null 2>&1; then
# prefer git-wt over wt if available
WT=git-wt.exe
elif command -v wt >/dev/null 2>&1; then
# reject wt if it's the Windows Terminal alias
if [[ "$(command -v wt)" == *WindowsApps* ]]; then
echo "worktrunk: 'wt' resolves to Windows Terminal; install worktrunk as git-wt.exe or remove the Windows Terminal alias. See https://worktrunk.dev/worktrunk/#install" >&2
exit 1
fi
WT=wt
fi
else
# non-Windows, always use wt
WT=wt
fi
if [[ -z "$WT" ]] || ! command -v "$WT" >/dev/null 2>&1; then
echo "worktrunk: could not find 'wt' in PATH" >&2
exit 1
fi
"$WT" "$@"