Repository navigation
fix(install): stop stripping the Claude Code mod from the marketplace clone; clear OpenCode 2's plugin cache - #1689
Merged
Conversation
… clone; clear OpenCode 2's plugin cache
Bug 1: install.sh / install.ps1 / install.cmd overwrote
<claude config>/plugins/marketplaces/plannotator/apps/hook/hooks/hooks.json,
Claude Code's own git clone of this repo, with a hard-coded copy that has no
"modules" key, so a plugin installed or updated from that clone loses the
Claude Code mod. The installers no longer write the clone. Instead they
restore the file from the clone's HEAD when it differs from HEAD and its
content (whitespace removed) is exactly one of the shapes earlier installers
wrote; a user's own edit is never touched. Needs git; otherwise a no-op.
Bug 2: OpenCode 2 caches npm plugins at
${XDG_CACHE_HOME:-~/.cache}/opencode/npm/<name>@<spec>/<generation>/, so the
installers left it on the old plugin. All three now root the cache at
XDG_CACHE_HOME (as both OpenCode generations do, Windows included) and remove
npm/@plannotator/opencode@* entries only. --skip-opencode still leaves the
cache alone. plannotator uninstall removes the OpenCode 2 entries too.
…apped XDG_CACHE_HOME drive cannot abort the install
backnotprop
added a commit
that referenced
this pull request
Oct 4, 2026
#1689 stopped pinning the absolute plannotator.exe path in the plugin hooks, so the hook runs bare `plannotator` and needs the install directory on PATH. install.ps1's Show-PathAdvice adds it to the user PATH; install.cmd only printed advice. :PrintPathAdvice now appends INSTALL_DIR to HKCU\Environment Path through one PowerShell call: read unexpanded and written back with its own kind (as plannotator uninstall removes it), skipped when any entry already names the directory, the directory passed via PLN_PATH_DIR, and a command with no quote, percent, bang, caret, ampersand or redirect for cmd.exe to reinterpret. A failure falls back to the old printed setx advice; the session-only note stays. Source-scan tests plus a pwsh parse check (CI).
backnotprop
added a commit
that referenced
this pull request
Oct 4, 2026
…error, deferred pi discovery, Windows PATH (#1692) * fix(claude-mod): refuse strict-gate and --hook annotate words instead of losing the decision /plannotator-annotate <file> --require-approval (or --result-file, --hook) launched a detached CLI whose exit code / result file nothing reads, so the reviewer's feedback was lost. The mod now refuses such words up front with a message pointing at the terminal. One list, SCRIPT_ONLY_ANNOTATE_FLAGS, in the shared tool contract (copied into the mod), is what the shell take-over also consults. * fix(cli): an occupied fixed port is one clean startup line, not a stack trace In remote mode the port is fixed (19432), so a second concurrent session — more common now that the Claude Code mod's servers outlive the terminal — died with a raw Bun stack. startBunServerOnAvailablePort now throws a typed PortInUseError (same message, so Pi's self-preemption pattern and tests are unchanged), and the CLI wraps its server starts so that error prints one line naming the port and PLANNOTATOR_PORT and exits through the startup-failure code (1, or 2 under a strict annotate gate). The port policy is unchanged. The mod already shows the CLI's stderr as the command's startup error. * fix(ai): defer pi model discovery so /api/ai/capabilities never waits on spawning pi Pi's fetchModels spawns `pi` and waits up to 10s; it ran eagerly at startup and beforeCapabilities awaited it, so every plain capabilities answer (and the first-run announcement gated on it) could stall up to 10s, even when a session bridge replaced every SDK provider. Pi now goes through the same deferred discovery as Codex/OpenCode (?activate= or first session, catalogProviders unchanged), in both runtimes; a Pi session spawns its own pi, so it does not block on discovery. The now-empty eager list and beforeCapabilities hook go. * fix(install.cmd): add the install directory to the user PATH #1689 stopped pinning the absolute plannotator.exe path in the plugin hooks, so the hook runs bare `plannotator` and needs the install directory on PATH. install.ps1's Show-PathAdvice adds it to the user PATH; install.cmd only printed advice. :PrintPathAdvice now appends INSTALL_DIR to HKCU\Environment Path through one PowerShell call: read unexpanded and written back with its own kind (as plannotator uninstall removes it), skipped when any entry already names the directory, the directory passed via PLN_PATH_DIR, and a command with no quote, percent, bang, caret, ampersand or redirect for cmd.exe to reinterpret. A failure falls back to the old printed setx advice; the session-only note stays. Source-scan tests plus a pwsh parse check (CI). * test(smoke): activate pi-sdk before expecting its models (discovery is deferred)
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two install-script bugs, fixed in
install.sh,install.ps1andinstall.cmdtogether.Bug 1: the installer stripped the Claude Code mod from the marketplace clone
${CLAUDE_CONFIG_DIR:-~/.claude}/plugins/marketplaces/plannotatoris Claude Code's own git clone of this repo. Installing or updating the plugin copiesapps/hookfrom it intoplugins/cache/plannotator/plannotator/<version>/. On every run, all three installers overwrote the clone'sapps/hook/hooks/hooks.jsonwith a hard-coded copy. That copy has no"modules": ["./mod/register.ts"]and nodescription.Evidence (Claude Code 2.1.289, temp
CLAUDE_CONFIG_DIR, realbacknotprop/plannotatormarketplace):claude plugin marketplace update plannotatorprinted "Successfully updated" and kept the local edit (M apps/hook/hooks/hooks.json).claude plugin install plannotator@plannotatorthen copied the stripped file into the plugin cache, so the installed plugin had no mod. This is the usual case, because people run the installer right after a release.History of the block
64d2f299) added it. The stated reason: "the Claude Code plugin marketplace can leave stale hooks.json with incorrect timeout values (e.g. 1800 instead of 345600)". The repo file has had 345600 since fix: increase hook timeout to 4 days #88.41059d8e) made the Windows installers write the absoluteplannotator.exepath, so the hook works when the hook shell has no PATH set.47bdd210then quoted that path.13c667c0) found the same copy dropping thePreToolUse/EnterPlanModeentry ("Fix install scripts silently stripping PreToolUse/EnterPlanMode hook entry").modules, and the copy dropped it again.Why removing the rewrite is safe
plannotatorcommand resolves once the installer's PATH entry is live (after a terminal restart, which the installer already asks for).hooks.jsonexisting.Repair. A clone that an earlier installer rewrote stays dirty until the next upstream commit. So each installer now restores the file only when all of these are true:
apps/hook/hooks/hooks.json(git -C <clone> cat-file -e HEAD:<path>).git diff --quiet HEAD -- <path>exits 1; any other exit means skip).plannotator, an unquoted…plannotator.exepath, or a\"…plannotator.exe\"pathWhen all three hold, the installer runs
git -C <clone> checkout -q -- apps/hook/hooks/hooks.jsonand prints "Restored … from its git checkout". Any other local edit is left alone.install.shholds the pattern as an ERE, andinstall.ps1/install.cmdhold the identical .NET pattern, written with\x22/\x5c/\A/\zso cmd.exe passes it through verbatim.install.cmdruns the check through onepowershell -NoProfilecall, as it already does for config parsing.plannotator uninstallassumed nothing about the clone; it removes the plugin throughclaude plugin uninstall.Bug 2: OpenCode 2's plugin cache was never cleared
The installers removed
~/.cache/opencode/{node_modules,packages}/@plannotator, which is the OpenCode 1 layout. OpenCode 2 (2.0.22) uses a different layout, read from source:packages/util/src/npm.tsputs a plugin inpath.join(global.cache, "npm", key), wherekey = sanitize(${name}@${spec}). Each install is a numeric generation directory inside it.packages/util/src/global-roots.tssetscache = $XDG_CACHE_HOME || ~/.cache, then/opencode. This holds on Windows too: it usesos.homedir(), not%LOCALAPPDATA%.So
@plannotator/opencode@latestis cached in the nested directory…/opencode/npm/@plannotator/opencode@latest/<generation>/. Re-running the installer left OpenCode 2 on the old plugin.What changed:
${XDG_CACHE_HOME:-$HOME/.cache}/opencode(Windows:%XDG_CACHE_HOME%, else%USERPROFILE%\.cache).npm/@plannotator/opencode@*, then the@plannotatorscope directory if it is empty. Other@plannotator/*packages and other plugins are kept.--skip-opencode/PLANNOTATOR_SKIP_OPENCODE_INSTALL/skipInstall.opencodestill leave the cache untouched.plannotator uninstallnow also removesnpm/@plannotator/opencode[@*]under bothXDG_CACHE_HOMEand~/.cache.tests/devcontainer/README.mdshows the OpenCode 2 path.Tests
bun test scripts/install.test.ts packages/server/uninstall.test.ts: 212 pass, 13 skip (the existing pwsh-only drivers), 0 fail.New in
scripts/install.test.ts:install.ps1andinstall.cmdmust carry the identical pattern, with no"|!%&<>for cmd.exe. Both patterns must match each historical rewrite: sh fix: validate plugin hooks.json on install #230, sh feat(hook): PFM reminder & improvement hook support across all runtimes #689, cmd fix: validate plugin hooks.json on install #230, ps1 fix: Support Windows markdown paths in CLI annotate flow #267, ps1 feat(hook): PFM reminder & improvement hook support across all runtimes #689, and quoted ps1 with CRLF. They must not match the repo'shooks.json, a changed timeout, an extra key, or another tool's command.git statusstays clean.CLAUDE_CONFIG_DIR).opencode@latest/opencode@0.27.25are removed.npm/@plannotator/pi-extension@latestandnpm/some-plugin@latestare kept.XDG_CACHE_HOMEis honored, and the empty scope directory is removed.--skip-opencodeleaves every path.main'sinstall.sh, the 5 tests that should catch the bugs fail.packages/server/uninstall.test.tsgains OpenCode 2 fixtures.shellcheck -S warning scripts/install.shreports the same 8 warnings asmain, none in the changed lines.install.ps1/install.cmdcould not be run here (no pwsh). They are covered by the parity and source tests only.After merge
The served install scripts (
plannotator.ai/install.sh,install.ps1,install.cmd) are synced to S3 by hand. Until that sync, users keep getting the old scripts, which still rewrite the clone.