mirror of
https://github.com/max-sixty/worktrunk.git
synced 2026-09-14 20:00:38 +08:00
d22917702e
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>
40 lines
1.4 KiB
Bash
Executable File
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" "$@"
|