From 93c3ac38b0fdcba0dbd95193dce9a8d6f163cd5e Mon Sep 17 00:00:00 2001 From: shahinyanm Date: Sun, 26 Jul 2026 14:54:59 +0400 Subject: [PATCH] fix: hooks were dead on a freshly installed plugin (0.50.2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dist/ is a build artifact and is not in git, but the marketplace installs this plugin from git. start.sh builds it — except start.sh only runs when the MCP server starts, while hooks are invoked directly as `node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-*`. On a freshly installed or updated plugin, every hook fired before the first MCP server start hit a missing entry point and died. It died quietly, which is the damaging part: Claude Code reads a failed hook as no decision, so enforcement did not warn or error, it just was not there. Found on a real machine — an updated 0.50.1 had no dist at all, while a months-old 0.47.1 had one purely because past sessions had built it. This is the most plausible explanation for "it doesn't always work". Route hooks through hooks/run.sh, which: - builds dist when missing (~3s; node_modules ships with the plugin) - guards the build with a lock, because a session start fires several hooks at once and they would otherwise all run tsc into one directory - exits 0 if the build fails, so a hook that cannot decide never turns into a hook that refuses - does not cd, because the hooks read process.cwd() as the project root Verified on a dist-less copy: one hook builds and decides; six concurrent hooks all decide and leave no stale lock; a relative path still resolves from the caller's directory. The npm install path is untouched — installer.ts writes its own absolute-path commands and never reads hooks/hooks.json. --- .claude-plugin/marketplace.json | 4 +-- .claude-plugin/plugin.json | 2 +- CHANGELOG.md | 33 ++++++++++++++++++++++ agents/tp-api-surface-tracker.md | 2 +- agents/tp-audit-scanner.md | 2 +- agents/tp-commit-writer.md | 2 +- agents/tp-context-engineer.md | 2 +- agents/tp-dead-code-finder.md | 2 +- agents/tp-debugger.md | 2 +- agents/tp-dep-health.md | 2 +- agents/tp-doc-writer.md | 2 +- agents/tp-history-explorer.md | 2 +- agents/tp-impact-analyzer.md | 2 +- agents/tp-incident-timeline.md | 2 +- agents/tp-incremental-builder.md | 2 +- agents/tp-migration-scout.md | 2 +- agents/tp-onboard.md | 2 +- agents/tp-performance-profiler.md | 2 +- agents/tp-pr-reviewer.md | 2 +- agents/tp-refactor-planner.md | 2 +- agents/tp-review-impact.md | 2 +- agents/tp-run.md | 2 +- agents/tp-session-restorer.md | 2 +- agents/tp-ship-coordinator.md | 2 +- agents/tp-spec-writer.md | 2 +- agents/tp-test-coverage-gapper.md | 2 +- agents/tp-test-triage.md | 2 +- agents/tp-test-writer.md | 2 +- hooks/hooks.json | 24 ++++++++-------- hooks/run.sh | 47 +++++++++++++++++++++++++++++++ package-lock.json | 4 +-- package.json | 3 +- server.json | 4 +-- 33 files changed, 126 insertions(+), 45 deletions(-) create mode 100755 hooks/run.sh diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 9d02f3c..9cfae6d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,14 +6,14 @@ }, "metadata": { "description": "Token Pilot — save 60-90% tokens when AI reads code", - "version": "0.50.1" + "version": "0.50.2" }, "plugins": [ { "name": "token-pilot", "source": "./", "description": "Reduces token consumption by 60-90% via AST-aware lazy file reading, structural symbol navigation, and cross-session tool-usage analytics. 25 MCP tools + 25 subagents + budget watchdog hooks.", - "version": "0.50.1", + "version": "0.50.2", "author": { "name": "Digital-Threads" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 917bbc7..2842b17 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "token-pilot", - "version": "0.50.1", + "version": "0.50.2", "description": "Saves 60-90% tokens on AI code reading. AST-aware lazy reads, symbol navigation, find_usages, structural git diff/log, edit-safety guard, Task-routing matcher, cross-session telemetry (errors + diagnostics), 25 tp-* subagents tiered to haiku/sonnet/opus with budget watchdog.", "author": { "name": "Digital-Threads", diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf07cd..061c39f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,39 @@ All notable changes to Token Pilot will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.50.2] - 2026-07-26 + +### Fixed — hooks were dead on a freshly installed plugin + +`dist/` is a build artifact and is not in git, but the marketplace +installs this plugin **from git**. `start.sh` builds it — except +`start.sh` only runs when the MCP server starts, and hooks are invoked +directly as `node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-*`. So on a +freshly installed or freshly updated plugin, every hook fired before the +first MCP server start hit a missing entry point and died. + +It died quietly, which is the worst part. Claude Code treats a failed +hook as no decision, so enforcement did not warn or error — it just +stopped existing until something else happened to build `dist`. Found on +a real machine: an updated 0.50.1 had no `dist` at all, while a months-old +0.47.1 had one only because past sessions had built it. This is the most +likely explanation for "it doesn't always work". + +Hooks now go through `hooks/run.sh`, which builds `dist` if it is missing +(~3s; `node_modules` ships with the plugin, so no install is needed), +guards that build with a lock so the several hooks a session start fires +cannot run `tsc` into the same directory at once, and — if the build +fails anyway — exits 0 rather than failing the user's tool call. A hook +that cannot decide must not become a hook that refuses. + +Verified against a dist-less copy: a single hook builds and returns its +decision; six concurrent hooks all return decisions and leave no stale +lock; relative paths still resolve from the caller's directory, since the +launcher deliberately does not `cd`. + +The npm install path is untouched — it writes its own absolute-path hook +commands and never reads `hooks/hooks.json`. + ## [0.50.1] - 2026-07-26 ### Fixed — two guard-clause defects in dispatch routing diff --git a/agents/tp-api-surface-tracker.md b/agents/tp-api-surface-tracker.md index 31adbc4..ef9c7f9 100644 --- a/agents/tp-api-surface-tracker.md +++ b/agents/tp-api-surface-tracker.md @@ -9,7 +9,7 @@ tools: - mcp__token-pilot__read_symbol - Bash model: haiku -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: dd184501203fa7f3c73f419c4ffbe33c4be75400cb64a7a51733a3fe23f6e085 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-audit-scanner.md b/agents/tp-audit-scanner.md index 29bfabe..bad4730 100644 --- a/agents/tp-audit-scanner.md +++ b/agents/tp-audit-scanner.md @@ -11,7 +11,7 @@ tools: - Grep - Read model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: d172f600bf32277ea6eb4cbbee4542ddd698a986dcd96997d33930561964569b requiredMcpServers: - "token-pilot" diff --git a/agents/tp-commit-writer.md b/agents/tp-commit-writer.md index 9793d23..db796f4 100644 --- a/agents/tp-commit-writer.md +++ b/agents/tp-commit-writer.md @@ -8,7 +8,7 @@ tools: - mcp__token-pilot__test_summary - mcp__token-pilot__outline - Bash -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: de64a406b5176de19f7422619c7de7949b1f28865f225402c9cea9255f377428 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-context-engineer.md b/agents/tp-context-engineer.md index 818ecf9..a78e9fb 100644 --- a/agents/tp-context-engineer.md +++ b/agents/tp-context-engineer.md @@ -13,7 +13,7 @@ tools: - Edit - Glob model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 68b32af2dacd82ebe52c4eec93edb903d452688274c3065218270627c564d8b0 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-dead-code-finder.md b/agents/tp-dead-code-finder.md index d58ecfb..c332201 100644 --- a/agents/tp-dead-code-finder.md +++ b/agents/tp-dead-code-finder.md @@ -11,7 +11,7 @@ tools: - Grep - Read model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: d9b7f5b7ae6f4ae21305c775361bcab097cc774370a6d976c093571d46d55021 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-debugger.md b/agents/tp-debugger.md index fcbbf3b..6f37373 100644 --- a/agents/tp-debugger.md +++ b/agents/tp-debugger.md @@ -12,7 +12,7 @@ tools: - Read - Bash model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 052413de8d92377edcde6ae5c823f5378db304baccfa29e8866467f42553a500 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-dep-health.md b/agents/tp-dep-health.md index aabecb7..0d3b4d0 100644 --- a/agents/tp-dep-health.md +++ b/agents/tp-dep-health.md @@ -9,7 +9,7 @@ tools: - Bash - Read model: haiku -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: e14dc57493d816f8c2e017963e2ef5f66bea50fd0b805a80e8a0d97c968427e7 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-doc-writer.md b/agents/tp-doc-writer.md index 879b81c..b337629 100644 --- a/agents/tp-doc-writer.md +++ b/agents/tp-doc-writer.md @@ -13,7 +13,7 @@ tools: - Edit - Glob model: haiku -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 57d741794ab40e31a7ac49c68ea39a9088f5827cdef866ce81bfca1b7c9180cf requiredMcpServers: - "token-pilot" diff --git a/agents/tp-history-explorer.md b/agents/tp-history-explorer.md index 7591bf9..ee7e95b 100644 --- a/agents/tp-history-explorer.md +++ b/agents/tp-history-explorer.md @@ -10,7 +10,7 @@ tools: - Bash - Read model: haiku -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 7b70fa76a60e3c58a1de4f56c32c0f166424137e203a0cf1c8654e7c9235d904 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-impact-analyzer.md b/agents/tp-impact-analyzer.md index c2f009e..188b7f0 100644 --- a/agents/tp-impact-analyzer.md +++ b/agents/tp-impact-analyzer.md @@ -12,7 +12,7 @@ tools: - mcp__token-pilot__read_symbols - Read model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 351a987e11eba63852f5431a16d8eb53104f4f689f82fdcc5a2bf4db948ba92f requiredMcpServers: - "token-pilot" diff --git a/agents/tp-incident-timeline.md b/agents/tp-incident-timeline.md index 1d754e3..d3d2492 100644 --- a/agents/tp-incident-timeline.md +++ b/agents/tp-incident-timeline.md @@ -8,7 +8,7 @@ tools: - mcp__token-pilot__read_symbol - Bash model: inherit -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: de5722bfea374eaab096c1ae635c37879e7a91370ee3cd0532f4240be03c91eb requiredMcpServers: - "token-pilot" diff --git a/agents/tp-incremental-builder.md b/agents/tp-incremental-builder.md index 257f531..4c0a677 100644 --- a/agents/tp-incremental-builder.md +++ b/agents/tp-incremental-builder.md @@ -13,7 +13,7 @@ tools: - Edit - Bash model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 375a824d0d847bb5453ec594c7a62ad566ee7e4d92717b0473f771f1a0477c60 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-migration-scout.md b/agents/tp-migration-scout.md index cf7e035..402d86b 100644 --- a/agents/tp-migration-scout.md +++ b/agents/tp-migration-scout.md @@ -11,7 +11,7 @@ tools: - Grep - Glob model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 0334de1bf99b431b65359637d125cda7c44c6f780eb92c57cc538715b1939536 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-onboard.md b/agents/tp-onboard.md index 8455633..99b2f15 100644 --- a/agents/tp-onboard.md +++ b/agents/tp-onboard.md @@ -10,7 +10,7 @@ tools: - mcp__token-pilot__smart_read - mcp__token-pilot__smart_read_many - mcp__token-pilot__read_section -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 832e95633fbc8e9b0c10f3e540a327d4be062fb4b3f17a6cce6be13f414e2927 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-performance-profiler.md b/agents/tp-performance-profiler.md index b674340..8c60966 100644 --- a/agents/tp-performance-profiler.md +++ b/agents/tp-performance-profiler.md @@ -11,7 +11,7 @@ tools: - Bash - Read model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: b61f06380d80798fa2e49d37bcba0653495bee04dd6bdbc1feff9a75607b0508 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-pr-reviewer.md b/agents/tp-pr-reviewer.md index 660da8b..b7789f1 100644 --- a/agents/tp-pr-reviewer.md +++ b/agents/tp-pr-reviewer.md @@ -11,7 +11,7 @@ tools: - mcp__token-pilot__read_for_edit - Read model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: f83f50d05b4f70285ae7afed2b1a406fc436df56e61a0aedbfb31edc7f2b6e66 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-refactor-planner.md b/agents/tp-refactor-planner.md index 5190949..1228b82 100644 --- a/agents/tp-refactor-planner.md +++ b/agents/tp-refactor-planner.md @@ -8,7 +8,7 @@ tools: - mcp__token-pilot__outline - mcp__token-pilot__read_symbol model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: c5f6fc122c89e16e5cf774045f92169ee3468555320b898171ba13eca5323550 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-review-impact.md b/agents/tp-review-impact.md index 2461884..009354e 100644 --- a/agents/tp-review-impact.md +++ b/agents/tp-review-impact.md @@ -9,7 +9,7 @@ tools: - mcp__token-pilot__module_info - Bash model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 8ef3c3341cbfed4eb8dd130126a9683edc57e378c92ff0ca764d584fd941c55c requiredMcpServers: - "token-pilot" diff --git a/agents/tp-run.md b/agents/tp-run.md index d9e9a70..5973223 100644 --- a/agents/tp-run.md +++ b/agents/tp-run.md @@ -16,7 +16,7 @@ tools: - Glob - Bash model: haiku -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 2b08618d34a61f00aafccbda9fed6d83243296dedb83440edbd2d5c28bb6dbc4 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-session-restorer.md b/agents/tp-session-restorer.md index 136ecba..4b0991c 100644 --- a/agents/tp-session-restorer.md +++ b/agents/tp-session-restorer.md @@ -9,7 +9,7 @@ tools: - mcp__token-pilot__session_budget - Bash - Read -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 529374ed728f5eed5b758b3be3da65624783c0bf0c1a253d7d661a843eb5f767 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-ship-coordinator.md b/agents/tp-ship-coordinator.md index 0a492fe..40a9e47 100644 --- a/agents/tp-ship-coordinator.md +++ b/agents/tp-ship-coordinator.md @@ -11,7 +11,7 @@ tools: - Read - Grep model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: a60f6ae110eb3138064bce074e8ba26fa0ce5f4659df1624a9d9d3646803391b requiredMcpServers: - "token-pilot" diff --git a/agents/tp-spec-writer.md b/agents/tp-spec-writer.md index c7715a3..5334249 100644 --- a/agents/tp-spec-writer.md +++ b/agents/tp-spec-writer.md @@ -9,7 +9,7 @@ tools: - Read - Write model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: c7a4e8b39228fd5158528f389c924c5ff2d98c4b9b05ee0106d54a26c5dc1350 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-test-coverage-gapper.md b/agents/tp-test-coverage-gapper.md index 1f56881..dcc54b3 100644 --- a/agents/tp-test-coverage-gapper.md +++ b/agents/tp-test-coverage-gapper.md @@ -10,7 +10,7 @@ tools: - mcp__token-pilot__test_summary - Glob - Grep -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: be81eed53a3720d146cf89e4a14a7a56577633f7c84c234c412ab70d64c05b11 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-test-triage.md b/agents/tp-test-triage.md index f75ea9a..f1431c4 100644 --- a/agents/tp-test-triage.md +++ b/agents/tp-test-triage.md @@ -8,7 +8,7 @@ tools: - mcp__token-pilot__find_usages - mcp__token-pilot__read_symbol model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 362ecf4cb03b059421ea26933473700900073dc38b3a7fe271208dfb1ae14f90 requiredMcpServers: - "token-pilot" diff --git a/agents/tp-test-writer.md b/agents/tp-test-writer.md index a29a0af..8963227 100644 --- a/agents/tp-test-writer.md +++ b/agents/tp-test-writer.md @@ -13,7 +13,7 @@ tools: - Edit - Bash model: sonnet -token_pilot_version: "0.50.1" +token_pilot_version: "0.50.2" token_pilot_body_hash: 269f2fe22ff4517c277d3f56ca67d8a5527b93290ab21079a83ba7af22c1b5a9 requiredMcpServers: - "token-pilot" diff --git a/hooks/hooks.json b/hooks/hooks.json index 12f3089..8c19fcc 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -6,7 +6,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-read" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-read" } ] }, @@ -15,7 +15,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-edit" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-edit" } ] }, @@ -24,7 +24,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-edit" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-edit" } ] }, @@ -33,7 +33,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-pre-bash" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-pre-bash" } ] }, @@ -42,7 +42,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-pre-grep" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-pre-grep" } ] }, @@ -51,7 +51,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-pre-task" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-pre-task" } ] } @@ -61,7 +61,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-bootstrap", + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-bootstrap", "once": true, "statusMessage": "Bootstrapping token-pilot..." } @@ -71,7 +71,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-session-start" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-session-start" } ] } @@ -81,7 +81,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-user-prompt" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-user-prompt" } ] } @@ -92,7 +92,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-bash", + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-post-bash", "async": true } ] @@ -102,7 +102,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-task" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-post-task" } ] } @@ -112,7 +112,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-subagent-stop" + "command": "sh ${CLAUDE_PLUGIN_ROOT}/hooks/run.sh hook-subagent-stop" } ] } diff --git a/hooks/run.sh b/hooks/run.sh new file mode 100755 index 0000000..c3dd88b --- /dev/null +++ b/hooks/run.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Hook launcher for the Claude Code plugin install. +# +# `dist/` is a build artifact and is not in git, but the marketplace +# installs this plugin FROM git. start.sh builds it — except start.sh only +# runs when the MCP server starts, and hooks are invoked directly. So on a +# freshly installed or freshly updated plugin, every hook fired before the +# first MCP server start hit a missing dist/index.js and died. Silently: +# Claude Code treats a failed hook as "no decision", so enforcement simply +# stopped existing until something else happened to build. +# +# This wrapper makes the hook path self-sufficient. Three rules: +# +# 1. Build if dist is missing — ~3s, and node_modules ships with the +# plugin so no install is needed. +# 2. Guard the build with a lock. A session start fires several hooks at +# once; without this they would all run tsc into the same directory. +# 3. Never block the user's tool call. If the build fails or another +# process is still building, exit 0 and let the call through. A hook +# that cannot decide must not become a hook that refuses. +# +# No `cd`: the hooks read process.cwd() as the project root, so this has to +# exec from wherever Claude Code invoked it. + +PLUGIN_DIR="$(cd "$(dirname "$0")/.." && pwd)" +ENTRY="$PLUGIN_DIR/dist/index.js" + +if [ ! -f "$ENTRY" ]; then + LOCK="$PLUGIN_DIR/.build.lock" + if mkdir "$LOCK" 2>/dev/null; then + echo "[token-pilot] building plugin (first run after install)…" >&2 + (cd "$PLUGIN_DIR" && npm run build >&2 2>&1) || true + rmdir "$LOCK" 2>/dev/null || true + else + # Another hook won the race — wait for it rather than build twice. + i=0 + while [ ! -f "$ENTRY" ] && [ "$i" -lt 30 ]; do + sleep 1 + i=$((i + 1)) + done + fi +fi + +# Still nothing to run: stay out of the way instead of failing the call. +[ -f "$ENTRY" ] || exit 0 + +exec node "$ENTRY" "$@" diff --git a/package-lock.json b/package-lock.json index a43db95..dcf35ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "token-pilot", - "version": "0.50.1", + "version": "0.50.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "token-pilot", - "version": "0.50.1", + "version": "0.50.2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 97b8b7a..c6adf1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "token-pilot", - "version": "0.50.1", + "version": "0.50.2", "description": "Save up to 80% tokens when AI reads code \u2014 MCP server for token-efficient code navigation, AST-aware structural reading instead of dumping full files into context window", "type": "module", "main": "dist/index.js", @@ -16,6 +16,7 @@ "start.sh", ".claude-plugin/", "hooks/hooks.json", + "hooks/run.sh", ".mcp.json", "skills/", "README.md", diff --git a/server.json b/server.json index 191bc43..13ecd30 100644 --- a/server.json +++ b/server.json @@ -6,12 +6,12 @@ "url": "https://github.com/Digital-Threads/token-pilot", "source": "github" }, - "version": "0.50.1", + "version": "0.50.2", "packages": [ { "registryType": "npm", "identifier": "token-pilot", - "version": "0.50.1", + "version": "0.50.2", "transport": { "type": "stdio" },