mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-15 13:23:13 +08:00
Compare commits
13 Commits
fix/bash-h
...
a2454e1026
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2454e1026 | ||
|
|
1a50145d39 | ||
|
|
eb900ddd81 | ||
|
|
ccecb0b9f4 | ||
|
|
9fb88c6700 | ||
|
|
6b7bd7156c | ||
|
|
1fabf4d2cf | ||
|
|
7eb7c598fb | ||
|
|
8b5c0c1b07 | ||
|
|
c1e7a272cc | ||
|
|
b5c4d2beb9 | ||
|
|
34380326c8 | ||
|
|
9227d3cc30 |
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@@ -140,7 +140,10 @@ jobs:
|
||||
run: |
|
||||
case "${{ matrix.pm }}" in
|
||||
npm) npm ci ;;
|
||||
pnpm) pnpm install --no-frozen-lockfile ;;
|
||||
# pnpm v10 can fail CI on ignored native build scripts
|
||||
# (for example msgpackr-extract) even though this repo is Yarn-native
|
||||
# and pnpm is only exercised here as a compatibility lane.
|
||||
pnpm) pnpm install --config.strict-dep-builds=false --no-frozen-lockfile ;;
|
||||
# Yarn Berry (v4+) removed --ignore-engines; engine checking is no longer a core feature
|
||||
yarn) yarn install ;;
|
||||
bun) bun install ;;
|
||||
|
||||
21
.github/workflows/release.yml
vendored
21
.github/workflows/release.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@@ -22,6 +23,7 @@ jobs:
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
@@ -53,6 +55,23 @@ jobs:
|
||||
- name: Verify release metadata stays in sync
|
||||
run: node tests/plugin-manifest.test.js
|
||||
|
||||
- name: Check npm publish state
|
||||
id: npm_publish_state
|
||||
run: |
|
||||
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
if npm view "${PACKAGE_NAME}@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
|
||||
echo "already_published=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "already_published=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Publish npm package
|
||||
if: steps.npm_publish_state.outputs.already_published != 'true'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm publish --access public --provenance
|
||||
|
||||
- name: Generate release highlights
|
||||
id: highlights
|
||||
env:
|
||||
@@ -73,6 +92,8 @@ jobs:
|
||||
- Improved release-note generation and changelog hygiene
|
||||
|
||||
### Notes
|
||||
- npm package: \`ecc-universal\`
|
||||
- Claude marketplace/plugin identifier: \`everything-claude-code@everything-claude-code\`
|
||||
- For migration tips and compatibility notes, see README and CHANGELOG.
|
||||
EOF
|
||||
|
||||
|
||||
37
.github/workflows/reusable-release.yml
vendored
37
.github/workflows/reusable-release.yml
vendored
@@ -12,9 +12,24 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
secrets:
|
||||
NPM_TOKEN:
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Version tag to release or republish (e.g., v1.10.0)'
|
||||
required: true
|
||||
type: string
|
||||
generate-notes:
|
||||
description: 'Auto-generate release notes'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@@ -31,6 +46,7 @@ jobs:
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
@@ -62,6 +78,23 @@ jobs:
|
||||
- name: Verify release metadata stays in sync
|
||||
run: node tests/plugin-manifest.test.js
|
||||
|
||||
- name: Check npm publish state
|
||||
id: npm_publish_state
|
||||
run: |
|
||||
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
if npm view "${PACKAGE_NAME}@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
|
||||
echo "already_published=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "already_published=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Publish npm package
|
||||
if: steps.npm_publish_state.outputs.already_published != 'true'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npm publish --access public --provenance
|
||||
|
||||
- name: Generate release highlights
|
||||
env:
|
||||
TAG_NAME: ${{ inputs.tag }}
|
||||
@@ -74,6 +107,10 @@ jobs:
|
||||
- Harness reliability and cross-platform compatibility
|
||||
- Eval-driven quality improvements
|
||||
- Better workflow and operator ergonomics
|
||||
|
||||
### Package Notes
|
||||
- npm package: \`ecc-universal\`
|
||||
- Claude marketplace/plugin identifier: \`everything-claude-code@everything-claude-code\`
|
||||
EOF
|
||||
|
||||
- name: Create GitHub Release
|
||||
|
||||
5
.github/workflows/reusable-test.yml
vendored
5
.github/workflows/reusable-test.yml
vendored
@@ -130,7 +130,10 @@ jobs:
|
||||
run: |
|
||||
case "${{ inputs.package-manager }}" in
|
||||
npm) npm ci ;;
|
||||
pnpm) pnpm install --no-frozen-lockfile ;;
|
||||
# pnpm v10 can fail CI on ignored native build scripts
|
||||
# (for example msgpackr-extract) even though this repo is Yarn-native
|
||||
# and pnpm is only exercised here as a compatibility lane.
|
||||
pnpm) pnpm install --config.strict-dep-builds=false --no-frozen-lockfile ;;
|
||||
# Yarn Berry (v4+) removed --ignore-engines; engine checking is no longer a core feature
|
||||
yarn) yarn install ;;
|
||||
bun) bun install ;;
|
||||
|
||||
16
README.md
16
README.md
@@ -174,10 +174,18 @@ Get up and running in under 2 minutes:
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# Install plugin
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
> Install-name clarification: older posts may still show `ecc@ecc`. That shorthand is deprecated. Anthropic marketplace/plugin installs are keyed by a canonical plugin identifier, so ECC standardized on `everything-claude-code@everything-claude-code` to keep the listing name, install path, `/plugin list`, and repo docs aligned instead of maintaining two different public names for the same plugin.
|
||||
### Naming + Migration Note
|
||||
|
||||
ECC now has three public identifiers, and they are not interchangeable:
|
||||
|
||||
- GitHub source repo: `affaan-m/everything-claude-code`
|
||||
- Claude marketplace/plugin identifier: `everything-claude-code@everything-claude-code`
|
||||
- npm package: `ecc-universal`
|
||||
|
||||
This is intentional. Anthropic marketplace/plugin installs are keyed by a canonical plugin identifier, so ECC standardized on `everything-claude-code@everything-claude-code` to keep the listing name, `/plugin install`, `/plugin list`, and repo docs aligned to one public install surface. Older posts may still show the old short-form nickname; that shorthand is deprecated. Separately, the npm package stayed on `ecc-universal`, so npm installs and marketplace installs intentionally use different names.
|
||||
|
||||
### Step 2: Install Rules (Required)
|
||||
|
||||
@@ -185,6 +193,8 @@ Get up and running in under 2 minutes:
|
||||
>
|
||||
> If your local Claude setup was wiped or reset, that does not mean you need to repurchase ECC. Start with `ecc list-installed`, then run `ecc doctor` and `ecc repair` before reinstalling anything. That usually restores ECC-managed files without rebuilding your setup. If the problem is account or marketplace access for ECC Tools, handle billing/account recovery separately.
|
||||
|
||||
> If your local Claude setup was wiped or reset, that does not mean you need to repurchase ECC. Start with `ecc list-installed`, then run `ecc doctor` and `ecc repair` before reinstalling anything. That usually restores ECC-managed files without rebuilding your setup. If the problem is account or marketplace access for ECC Tools, handle billing/account recovery separately.
|
||||
|
||||
```bash
|
||||
# Clone the repo first
|
||||
git clone https://github.com/affaan-m/everything-claude-code.git
|
||||
@@ -650,7 +660,7 @@ The easiest way to use this repo - install as a Claude Code plugin:
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# Install the plugin
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
Or add directly to your `~/.claude/settings.json`:
|
||||
|
||||
@@ -102,10 +102,10 @@
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# 安装插件
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
> 安装名称说明:较早的帖子里可能还会出现 `ecc@ecc`。那个旧缩写现在已经废弃。Anthropic 的 marketplace/plugin 安装是按规范化插件标识符寻址的,因此 ECC 统一为 `everything-claude-code@everything-claude-code`,这样市场条目、安装命令、`/plugin list` 输出和仓库文档都使用同一个公开名称,不再出现两个名字指向同一插件的混乱。
|
||||
> 安装名称说明:较早的帖子里可能还会出现旧的短别名。那个旧缩写现在已经废弃。Anthropic 的 marketplace/plugin 安装是按规范化插件标识符寻址的,因此 ECC 统一为 `everything-claude-code@everything-claude-code`,这样市场条目、安装命令、`/plugin list` 输出和仓库文档都使用同一个公开名称,不再出现两个名字指向同一插件的混乱。
|
||||
|
||||
### 第二步:安装规则(必需)
|
||||
|
||||
@@ -548,7 +548,7 @@ Claude Code v2.1+ 会**按照约定自动加载**已安装插件中的 `hooks/ho
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# 安装插件
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
或直接添加到你的 `~/.claude/settings.json`:
|
||||
|
||||
@@ -17,7 +17,7 @@ Everything Claude Code プロジェクトのインタラクティブなステッ
|
||||
## 前提条件
|
||||
|
||||
このスキルは起動前に Claude Code からアクセス可能である必要があります。ブートストラップには2つの方法があります:
|
||||
1. **プラグイン経由**: `/plugin install everything-claude-code` — プラグインがこのスキルを自動的にロードします
|
||||
1. **プラグイン経由**: `/plugin install everything-claude-code@everything-claude-code` — プラグインがこのスキルを自動的にロードします
|
||||
2. **手動**: このスキルのみを `~/.claude/skills/configure-ecc/SKILL.md` にコピーし、"configure ecc" と言って起動します
|
||||
|
||||
---
|
||||
|
||||
@@ -124,7 +124,7 @@ Comece em menos de 2 minutos:
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# Instalar plugin
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
### Passo 2: Instalar as Regras (Obrigatório)
|
||||
@@ -313,7 +313,7 @@ claude --version
|
||||
/plugin marketplace add https://github.com/affaan-m/everything-claude-code
|
||||
|
||||
# Instalar o plugin
|
||||
/plugin install everything-claude-code
|
||||
/plugin install everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
Ou adicione diretamente ao seu `~/.claude/settings.json`:
|
||||
|
||||
@@ -19,7 +19,7 @@ origin: ECC
|
||||
|
||||
此技能必须在激活前对 Claude Code 可访问。有两种引导方式:
|
||||
|
||||
1. **通过插件**: `/plugin install everything-claude-code` — 插件会自动加载此技能
|
||||
1. **通过插件**: `/plugin install everything-claude-code@everything-claude-code` — 插件会自动加载此技能
|
||||
2. **手动**: 仅将此技能复制到 `~/.claude/skills/configure-ecc/SKILL.md`,然后通过说 "configure ecc" 激活
|
||||
|
||||
***
|
||||
|
||||
368
hooks/hooks.json
368
hooks/hooks.json
@@ -7,113 +7,18 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:bash:block-no-verify",
|
||||
"scripts/hooks/block-no-verify.js",
|
||||
"minimal,standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/pre-bash-dispatcher.js"
|
||||
}
|
||||
],
|
||||
"description": "Block git hook-bypass flag to protect pre-commit, commit-msg, and pre-push hooks from being skipped",
|
||||
"id": "pre:bash:block-no-verify"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/auto-tmux-dev.js"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Auto-start dev servers in tmux with directory-based session names",
|
||||
"id": "pre:bash:auto-tmux-dev"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:bash:tmux-reminder",
|
||||
"scripts/hooks/pre-bash-tmux-reminder.js",
|
||||
"strict"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Reminder to use tmux for long-running commands",
|
||||
"id": "pre:bash:tmux-reminder"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:bash:git-push-reminder",
|
||||
"scripts/hooks/pre-bash-git-push-reminder.js",
|
||||
"strict"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Reminder before git push to review changes",
|
||||
"id": "pre:bash:git-push-reminder"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:bash:commit-quality",
|
||||
"scripts/hooks/pre-bash-commit-quality.js",
|
||||
"strict"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Pre-commit quality check: lint staged files, validate commit message format, detect console.log/debugger/secrets before committing",
|
||||
"id": "pre:bash:commit-quality"
|
||||
"description": "Consolidated Bash preflight dispatcher for quality, tmux, push, and GateGuard checks",
|
||||
"id": "pre:bash:dispatcher"
|
||||
},
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:write:doc-file-warning",
|
||||
"scripts/hooks/doc-file-warning.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:write:doc-file-warning scripts/hooks/doc-file-warning.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Doc file warning: warn about non-standard documentation files (exit code 0; warns only)",
|
||||
@@ -124,16 +29,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:edit-write:suggest-compact",
|
||||
"scripts/hooks/suggest-compact.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:edit-write:suggest-compact scripts/hooks/suggest-compact.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Suggest manual compaction at logical intervals",
|
||||
@@ -144,16 +40,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"shell",
|
||||
"scripts/hooks/run-with-flags-shell.sh",
|
||||
"pre:observe",
|
||||
"skills/continuous-learning-v2/hooks/observe.sh",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" shell scripts/hooks/run-with-flags-shell.sh pre:observe skills/continuous-learning-v2/hooks/observe.sh standard,strict",
|
||||
"async": true,
|
||||
"timeout": 10
|
||||
}
|
||||
@@ -166,16 +53,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:governance-capture",
|
||||
"scripts/hooks/governance-capture.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:governance-capture scripts/hooks/governance-capture.js standard,strict",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
@@ -187,16 +65,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:config-protection",
|
||||
"scripts/hooks/config-protection.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:config-protection scripts/hooks/config-protection.js standard,strict",
|
||||
"timeout": 5
|
||||
}
|
||||
],
|
||||
@@ -208,16 +77,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:mcp-health-check",
|
||||
"scripts/hooks/mcp-health-check.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:mcp-health-check scripts/hooks/mcp-health-check.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Check MCP server health before MCP tool execution and block unhealthy MCP calls",
|
||||
@@ -228,42 +88,12 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:edit-write:gateguard-fact-force",
|
||||
"scripts/hooks/gateguard-fact-force.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:edit-write:gateguard-fact-force scripts/hooks/gateguard-fact-force.js standard,strict",
|
||||
"timeout": 5
|
||||
}
|
||||
],
|
||||
"description": "Fact-forcing gate: block first Edit/Write/MultiEdit per file and demand investigation (importers, data schemas, user instruction) before allowing",
|
||||
"id": "pre:edit-write:gateguard-fact-force"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:bash:gateguard-fact-force",
|
||||
"scripts/hooks/gateguard-fact-force.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"timeout": 5
|
||||
}
|
||||
],
|
||||
"description": "Fact-forcing gate: block destructive Bash commands and demand rollback plan; quote user instruction on first Bash per session",
|
||||
"id": "pre:bash:gateguard-fact-force"
|
||||
}
|
||||
],
|
||||
"PreCompact": [
|
||||
@@ -272,16 +102,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"pre:compact",
|
||||
"scripts/hooks/pre-compact.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:compact scripts/hooks/pre-compact.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Save state before context compaction",
|
||||
@@ -294,13 +115,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/session-start-bootstrap.js"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/session-start-bootstrap.js"
|
||||
}
|
||||
],
|
||||
"description": "Load previous context and detect package manager on new session",
|
||||
@@ -313,94 +128,20 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/post-bash-command-log.js",
|
||||
"audit"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Audit log all bash commands to ~/.claude/bash-commands.log",
|
||||
"id": "post:bash:command-log-audit"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/post-bash-command-log.js",
|
||||
"cost"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Cost tracker - log bash tool usage with timestamps",
|
||||
"id": "post:bash:command-log-cost"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:bash:pr-created",
|
||||
"scripts/hooks/post-bash-pr-created.js",
|
||||
"standard,strict"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Log PR URL and provide review command after PR creation",
|
||||
"id": "post:bash:pr-created"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:bash:build-complete",
|
||||
"scripts/hooks/post-bash-build-complete.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/post-bash-dispatcher.js",
|
||||
"async": true,
|
||||
"timeout": 30
|
||||
}
|
||||
],
|
||||
"description": "Example: async hook for build analysis (runs in background without blocking)",
|
||||
"id": "post:bash:build-complete"
|
||||
"description": "Consolidated Bash postflight dispatcher for logging, PR, and build notifications",
|
||||
"id": "post:bash:dispatcher"
|
||||
},
|
||||
{
|
||||
"matcher": "Edit|Write|MultiEdit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:quality-gate",
|
||||
"scripts/hooks/quality-gate.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:quality-gate scripts/hooks/quality-gate.js standard,strict",
|
||||
"async": true,
|
||||
"timeout": 30
|
||||
}
|
||||
@@ -413,16 +154,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:edit:design-quality-check",
|
||||
"scripts/hooks/design-quality-check.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:design-quality-check scripts/hooks/design-quality-check.js standard,strict",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
@@ -434,16 +166,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:edit:accumulate",
|
||||
"scripts/hooks/post-edit-accumulator.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:accumulate scripts/hooks/post-edit-accumulator.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Record edited JS/TS file paths for batch format+typecheck at Stop time",
|
||||
@@ -454,16 +177,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:edit:console-warn",
|
||||
"scripts/hooks/post-edit-console-warn.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:console-warn scripts/hooks/post-edit-console-warn.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Warn about console.log statements after edits",
|
||||
@@ -474,16 +188,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:governance-capture",
|
||||
"scripts/hooks/governance-capture.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:governance-capture scripts/hooks/governance-capture.js standard,strict",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
@@ -495,16 +200,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:session-activity-tracker",
|
||||
"scripts/hooks/session-activity-tracker.js",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:session-activity-tracker scripts/hooks/session-activity-tracker.js standard,strict",
|
||||
"timeout": 10
|
||||
}
|
||||
],
|
||||
@@ -516,16 +212,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"shell",
|
||||
"scripts/hooks/run-with-flags-shell.sh",
|
||||
"post:observe",
|
||||
"skills/continuous-learning-v2/hooks/observe.sh",
|
||||
"standard,strict"
|
||||
],
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" shell scripts/hooks/run-with-flags-shell.sh post:observe skills/continuous-learning-v2/hooks/observe.sh standard,strict",
|
||||
"async": true,
|
||||
"timeout": 10
|
||||
}
|
||||
@@ -540,16 +227,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": [
|
||||
"node",
|
||||
"-e",
|
||||
"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\"ecc\"],[\"ecc@ecc\"],[\"marketplace\",\"ecc\"],[\"everything-claude-code\"],[\"everything-claude-code@everything-claude-code\"],[\"marketplace\",\"everything-claude-code\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\"ecc\",\"everything-claude-code\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)",
|
||||
"node",
|
||||
"scripts/hooks/run-with-flags.js",
|
||||
"post:mcp-health-check",
|
||||
"scripts/hooks/mcp-health-check.js",
|
||||
"standard,strict"
|
||||
]
|
||||
"command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:mcp-health-check scripts/hooks/mcp-health-check.js standard,strict"
|
||||
}
|
||||
],
|
||||
"description": "Track failed MCP tool calls, mark unhealthy servers, and attempt reconnect",
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
"name": "ecc-universal",
|
||||
"version": "1.10.0",
|
||||
"description": "Complete collection of battle-tested Claude Code configs — agents, skills, hooks, rules, and legacy command shims evolved over 10+ months of intensive daily use by an Anthropic hackathon winner",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"keywords": [
|
||||
"claude-code",
|
||||
"ai",
|
||||
|
||||
@@ -30,19 +30,10 @@ const { spawnSync } = require('child_process');
|
||||
|
||||
const MAX_STDIN = 1024 * 1024; // 1MB limit
|
||||
let data = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
|
||||
process.stdin.on('data', chunk => {
|
||||
if (data.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - data.length;
|
||||
data += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
let input;
|
||||
function run(rawInput) {
|
||||
try {
|
||||
input = JSON.parse(data);
|
||||
const input = typeof rawInput === 'string' ? JSON.parse(rawInput) : rawInput;
|
||||
const cmd = input.tool_input?.command || '';
|
||||
|
||||
// Detect dev server commands: npm run dev, pnpm dev, yarn dev, bun run dev
|
||||
@@ -60,7 +51,13 @@ process.stdin.on('end', () => {
|
||||
// Windows: open in a new cmd window (non-blocking)
|
||||
// Escape double quotes in cmd for cmd /k syntax
|
||||
const escapedCmd = cmd.replace(/"/g, '""');
|
||||
input.tool_input.command = `start "DevServer-${sessionName}" cmd /k "${escapedCmd}"`;
|
||||
return JSON.stringify({
|
||||
...input,
|
||||
tool_input: {
|
||||
...input.tool_input,
|
||||
command: `start "DevServer-${sessionName}" cmd /k "${escapedCmd}"`,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Unix (macOS/Linux): Check tmux is available before transforming
|
||||
const tmuxCheck = spawnSync('which', ['tmux'], { encoding: 'utf8' });
|
||||
@@ -73,16 +70,38 @@ process.stdin.on('end', () => {
|
||||
// 2. Create new detached session with the dev command
|
||||
// 3. Echo confirmation message with instructions for viewing logs
|
||||
const transformedCmd = `SESSION="${sessionName}"; tmux kill-session -t "$SESSION" 2>/dev/null || true; tmux new-session -d -s "$SESSION" '${escapedCmd}' && echo "[Hook] Dev server started in tmux session '${sessionName}'. View logs: tmux capture-pane -t ${sessionName} -p -S -100"`;
|
||||
|
||||
input.tool_input.command = transformedCmd;
|
||||
return JSON.stringify({
|
||||
...input,
|
||||
tool_input: {
|
||||
...input.tool_input,
|
||||
command: transformedCmd,
|
||||
},
|
||||
});
|
||||
}
|
||||
// else: tmux not found, pass through original command unchanged
|
||||
}
|
||||
}
|
||||
process.stdout.write(JSON.stringify(input));
|
||||
|
||||
return JSON.stringify(input);
|
||||
} catch {
|
||||
// Invalid input — pass through original data unchanged
|
||||
process.stdout.write(data);
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (data.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - data.length;
|
||||
data += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
process.stdout.write(run(data));
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
||||
177
scripts/hooks/bash-hook-dispatcher.js
Normal file
177
scripts/hooks/bash-hook-dispatcher.js
Normal file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { isHookEnabled } = require('../lib/hook-flags');
|
||||
|
||||
const { run: runBlockNoVerify } = require('./block-no-verify');
|
||||
const { run: runAutoTmuxDev } = require('./auto-tmux-dev');
|
||||
const { run: runTmuxReminder } = require('./pre-bash-tmux-reminder');
|
||||
const { run: runGitPushReminder } = require('./pre-bash-git-push-reminder');
|
||||
const { run: runCommitQuality } = require('./pre-bash-commit-quality');
|
||||
const { run: runGateGuard } = require('./gateguard-fact-force');
|
||||
const { run: runCommandLog } = require('./post-bash-command-log');
|
||||
const { run: runPrCreated } = require('./post-bash-pr-created');
|
||||
const { run: runBuildComplete } = require('./post-bash-build-complete');
|
||||
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
|
||||
const PRE_BASH_HOOKS = [
|
||||
{
|
||||
id: 'pre:bash:block-no-verify',
|
||||
profiles: 'minimal,standard,strict',
|
||||
run: rawInput => runBlockNoVerify(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'pre:bash:auto-tmux-dev',
|
||||
run: rawInput => runAutoTmuxDev(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'pre:bash:tmux-reminder',
|
||||
profiles: 'strict',
|
||||
run: rawInput => runTmuxReminder(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'pre:bash:git-push-reminder',
|
||||
profiles: 'strict',
|
||||
run: rawInput => runGitPushReminder(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'pre:bash:commit-quality',
|
||||
profiles: 'strict',
|
||||
run: rawInput => runCommitQuality(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'pre:bash:gateguard-fact-force',
|
||||
profiles: 'standard,strict',
|
||||
run: rawInput => runGateGuard(rawInput),
|
||||
},
|
||||
];
|
||||
|
||||
const POST_BASH_HOOKS = [
|
||||
{
|
||||
id: 'post:bash:command-log-audit',
|
||||
run: rawInput => runCommandLog(rawInput, 'audit'),
|
||||
},
|
||||
{
|
||||
id: 'post:bash:command-log-cost',
|
||||
run: rawInput => runCommandLog(rawInput, 'cost'),
|
||||
},
|
||||
{
|
||||
id: 'post:bash:pr-created',
|
||||
profiles: 'standard,strict',
|
||||
run: rawInput => runPrCreated(rawInput),
|
||||
},
|
||||
{
|
||||
id: 'post:bash:build-complete',
|
||||
profiles: 'standard,strict',
|
||||
run: rawInput => runBuildComplete(rawInput),
|
||||
},
|
||||
];
|
||||
|
||||
function readStdinRaw() {
|
||||
return new Promise(resolve => {
|
||||
let raw = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
process.stdin.on('end', () => resolve(raw));
|
||||
process.stdin.on('error', () => resolve(raw));
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeHookResult(previousRaw, output) {
|
||||
if (typeof output === 'string' || Buffer.isBuffer(output)) {
|
||||
return {
|
||||
raw: String(output),
|
||||
stderr: '',
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (output && typeof output === 'object') {
|
||||
const nextRaw = Object.prototype.hasOwnProperty.call(output, 'stdout')
|
||||
? String(output.stdout ?? '')
|
||||
: !Number.isInteger(output.exitCode) || output.exitCode === 0
|
||||
? previousRaw
|
||||
: '';
|
||||
|
||||
return {
|
||||
raw: nextRaw,
|
||||
stderr: typeof output.stderr === 'string' ? output.stderr : '',
|
||||
exitCode: Number.isInteger(output.exitCode) ? output.exitCode : 0,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
raw: previousRaw,
|
||||
stderr: '',
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
|
||||
function runHooks(rawInput, hooks) {
|
||||
let currentRaw = rawInput;
|
||||
let stderr = '';
|
||||
|
||||
for (const hook of hooks) {
|
||||
if (!isHookEnabled(hook.id, { profiles: hook.profiles })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = normalizeHookResult(currentRaw, hook.run(currentRaw));
|
||||
currentRaw = result.raw;
|
||||
if (result.stderr) {
|
||||
stderr += result.stderr.endsWith('\n') ? result.stderr : `${result.stderr}\n`;
|
||||
}
|
||||
if (result.exitCode !== 0) {
|
||||
return { output: currentRaw, stderr, exitCode: result.exitCode };
|
||||
}
|
||||
} catch (error) {
|
||||
stderr += `[Hook] ${hook.id} failed: ${error.message}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return { output: currentRaw, stderr, exitCode: 0 };
|
||||
}
|
||||
|
||||
function runPreBash(rawInput) {
|
||||
return runHooks(rawInput, PRE_BASH_HOOKS);
|
||||
}
|
||||
|
||||
function runPostBash(rawInput) {
|
||||
return runHooks(rawInput, POST_BASH_HOOKS);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const mode = process.argv[2];
|
||||
const raw = await readStdinRaw();
|
||||
|
||||
const result = mode === 'post'
|
||||
? runPostBash(raw)
|
||||
: runPreBash(raw);
|
||||
|
||||
if (result.stderr) {
|
||||
process.stderr.write(result.stderr);
|
||||
}
|
||||
process.stdout.write(result.output);
|
||||
process.exit(result.exitCode);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main().catch(error => {
|
||||
process.stderr.write(`[Hook] bash-hook-dispatcher failed: ${error.message}\n`);
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
PRE_BASH_HOOKS,
|
||||
POST_BASH_HOOKS,
|
||||
runPreBash,
|
||||
runPostBash,
|
||||
};
|
||||
@@ -4,24 +4,46 @@
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
let raw = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
function run(rawInput) {
|
||||
try {
|
||||
const input = JSON.parse(raw);
|
||||
const input = typeof rawInput === 'string' ? JSON.parse(rawInput) : rawInput;
|
||||
const cmd = String(input.tool_input?.command || '');
|
||||
if (/(npm run build|pnpm build|yarn build)/.test(cmd)) {
|
||||
console.error('[Hook] Build completed - async analysis running in background');
|
||||
return {
|
||||
stdout: typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput),
|
||||
stderr: '[Hook] Build completed - async analysis running in background',
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors and pass through
|
||||
}
|
||||
|
||||
process.stdout.write(raw);
|
||||
});
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(raw);
|
||||
if (result && typeof result === 'object') {
|
||||
if (result.stderr) {
|
||||
process.stderr.write(`${result.stderr}\n`);
|
||||
}
|
||||
process.stdout.write(String(result.stdout || ''));
|
||||
process.exitCode = Number.isInteger(result.exitCode) ? result.exitCode : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(String(result));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
||||
@@ -38,8 +38,24 @@ function appendLine(filePath, line) {
|
||||
fs.appendFileSync(filePath, `${line}\n`, 'utf8');
|
||||
}
|
||||
|
||||
function run(rawInput, mode = 'audit') {
|
||||
const config = MODE_CONFIG[mode];
|
||||
|
||||
try {
|
||||
if (config) {
|
||||
const input = String(rawInput || '').trim() ? JSON.parse(String(rawInput)) : {};
|
||||
const command = sanitizeCommand(input.tool_input?.command || '?');
|
||||
appendLine(path.join(os.homedir(), '.claude', config.fileName), config.format(command));
|
||||
}
|
||||
} catch {
|
||||
// Logging must never block the calling hook.
|
||||
}
|
||||
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
|
||||
function main() {
|
||||
const config = MODE_CONFIG[process.argv[2]];
|
||||
const mode = process.argv[2];
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
@@ -50,17 +66,7 @@ function main() {
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
try {
|
||||
if (config) {
|
||||
const input = raw.trim() ? JSON.parse(raw) : {};
|
||||
const command = sanitizeCommand(input.tool_input?.command || '?');
|
||||
appendLine(path.join(os.homedir(), '.claude', config.fileName), config.format(command));
|
||||
}
|
||||
} catch {
|
||||
// Logging must never block the calling hook.
|
||||
}
|
||||
|
||||
process.stdout.write(raw);
|
||||
process.stdout.write(run(raw, mode));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,5 +75,6 @@ if (require.main === module) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run,
|
||||
sanitizeCommand,
|
||||
};
|
||||
|
||||
24
scripts/hooks/post-bash-dispatcher.js
Normal file
24
scripts/hooks/post-bash-dispatcher.js
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { runPostBash } = require('./bash-hook-dispatcher');
|
||||
|
||||
let raw = '';
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = runPostBash(raw);
|
||||
if (result.stderr) {
|
||||
process.stderr.write(result.stderr);
|
||||
}
|
||||
process.stdout.write(result.output);
|
||||
process.exitCode = result.exitCode;
|
||||
});
|
||||
@@ -4,17 +4,9 @@
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
let raw = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
function run(rawInput) {
|
||||
try {
|
||||
const input = JSON.parse(raw);
|
||||
const input = typeof rawInput === 'string' ? JSON.parse(rawInput) : rawInput;
|
||||
const cmd = String(input.tool_input?.command || '');
|
||||
|
||||
if (/\bgh\s+pr\s+create\b/.test(cmd)) {
|
||||
@@ -24,13 +16,45 @@ process.stdin.on('end', () => {
|
||||
const prUrl = match[0];
|
||||
const repo = prUrl.replace(/https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/\d+/, '$1');
|
||||
const prNum = prUrl.replace(/.+\/pull\/(\d+)/, '$1');
|
||||
console.error(`[Hook] PR created: ${prUrl}`);
|
||||
console.error(`[Hook] To review: gh pr review ${prNum} --repo ${repo}`);
|
||||
return {
|
||||
stdout: typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput),
|
||||
stderr: [
|
||||
`[Hook] PR created: ${prUrl}`,
|
||||
`[Hook] To review: gh pr review ${prNum} --repo ${repo}`,
|
||||
].join('\n'),
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors and pass through
|
||||
}
|
||||
|
||||
process.stdout.write(raw);
|
||||
});
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(raw);
|
||||
if (result && typeof result === 'object') {
|
||||
if (result.stderr) {
|
||||
process.stderr.write(`${result.stderr}\n`);
|
||||
}
|
||||
process.stdout.write(String(result.stdout || ''));
|
||||
process.exit(Number.isInteger(result.exitCode) ? result.exitCode : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(String(result));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
||||
@@ -380,7 +380,11 @@ function evaluate(rawInput) {
|
||||
}
|
||||
|
||||
function run(rawInput) {
|
||||
return evaluate(rawInput).output;
|
||||
const result = evaluate(rawInput);
|
||||
return {
|
||||
stdout: result.output,
|
||||
exitCode: result.exitCode,
|
||||
};
|
||||
}
|
||||
|
||||
// ── stdin entry point ────────────────────────────────────────────
|
||||
|
||||
24
scripts/hooks/pre-bash-dispatcher.js
Normal file
24
scripts/hooks/pre-bash-dispatcher.js
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { runPreBash } = require('./bash-hook-dispatcher');
|
||||
|
||||
let raw = '';
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = runPreBash(raw);
|
||||
if (result.stderr) {
|
||||
process.stderr.write(result.stderr);
|
||||
}
|
||||
process.stdout.write(result.output);
|
||||
process.exitCode = result.exitCode;
|
||||
});
|
||||
@@ -4,25 +4,49 @@
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
let raw = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
function run(rawInput) {
|
||||
try {
|
||||
const input = JSON.parse(raw);
|
||||
const input = typeof rawInput === 'string' ? JSON.parse(rawInput) : rawInput;
|
||||
const cmd = String(input.tool_input?.command || '');
|
||||
if (/\bgit\s+push\b/.test(cmd)) {
|
||||
console.error('[Hook] Review changes before push...');
|
||||
console.error('[Hook] Continuing with push (remove this hook to add interactive review)');
|
||||
return {
|
||||
stdout: typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput),
|
||||
stderr: [
|
||||
'[Hook] Review changes before push...',
|
||||
'[Hook] Continuing with push (remove this hook to add interactive review)',
|
||||
].join('\n'),
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors and pass through
|
||||
}
|
||||
|
||||
process.stdout.write(raw);
|
||||
});
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(raw);
|
||||
if (result && typeof result === 'object') {
|
||||
if (result.stderr) {
|
||||
process.stderr.write(`${result.stderr}\n`);
|
||||
}
|
||||
process.stdout.write(String(result.stdout || ''));
|
||||
process.exitCode = Number.isInteger(result.exitCode) ? result.exitCode : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(String(result));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
||||
@@ -4,17 +4,9 @@
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
let raw = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
function run(rawInput) {
|
||||
try {
|
||||
const input = JSON.parse(raw);
|
||||
const input = typeof rawInput === 'string' ? JSON.parse(rawInput) : rawInput;
|
||||
const cmd = String(input.tool_input?.command || '');
|
||||
|
||||
if (
|
||||
@@ -22,12 +14,44 @@ process.stdin.on('end', () => {
|
||||
!process.env.TMUX &&
|
||||
/(npm (install|test)|pnpm (install|test)|yarn (install|test)?|bun (install|test)|cargo build|make\b|docker\b|pytest|vitest|playwright)/.test(cmd)
|
||||
) {
|
||||
console.error('[Hook] Consider running in tmux for session persistence');
|
||||
console.error('[Hook] tmux new -s dev | tmux attach -t dev');
|
||||
return {
|
||||
stdout: typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput),
|
||||
stderr: [
|
||||
'[Hook] Consider running in tmux for session persistence',
|
||||
'[Hook] tmux new -s dev | tmux attach -t dev',
|
||||
].join('\n'),
|
||||
exitCode: 0,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors and pass through
|
||||
}
|
||||
|
||||
process.stdout.write(raw);
|
||||
});
|
||||
return typeof rawInput === 'string' ? rawInput : JSON.stringify(rawInput);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (raw.length < MAX_STDIN) {
|
||||
const remaining = MAX_STDIN - raw.length;
|
||||
raw += chunk.substring(0, remaining);
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
const result = run(raw);
|
||||
if (result && typeof result === 'object') {
|
||||
if (result.stderr) {
|
||||
process.stderr.write(`${result.stderr}\n`);
|
||||
}
|
||||
process.stdout.write(String(result.stdout || ''));
|
||||
process.exitCode = Number.isInteger(result.exitCode) ? result.exitCode : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(String(result));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
||||
51
tests/docs/install-identifiers.test.js
Normal file
51
tests/docs/install-identifiers.test.js
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const repoRoot = path.resolve(__dirname, '..', '..');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
passed++;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
const publicInstallDocs = [
|
||||
'README.md',
|
||||
'README.zh-CN.md',
|
||||
'docs/pt-BR/README.md',
|
||||
'docs/ja-JP/skills/configure-ecc/SKILL.md',
|
||||
'docs/zh-CN/skills/configure-ecc/SKILL.md',
|
||||
];
|
||||
|
||||
console.log('\n=== Testing public install identifiers ===\n');
|
||||
|
||||
for (const relativePath of publicInstallDocs) {
|
||||
const content = fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
|
||||
|
||||
test(`${relativePath} does not use the stale ecc@ecc plugin identifier`, () => {
|
||||
assert.ok(!content.includes('ecc@ecc'));
|
||||
});
|
||||
|
||||
test(`${relativePath} documents the canonical marketplace plugin identifier`, () => {
|
||||
assert.ok(content.includes('everything-claude-code@everything-claude-code'));
|
||||
});
|
||||
}
|
||||
|
||||
if (failed > 0) {
|
||||
console.log(`\nFailed: ${failed}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`\nPassed: ${passed}`);
|
||||
114
tests/hooks/bash-hook-dispatcher.test.js
Normal file
114
tests/hooks/bash-hook-dispatcher.test.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Tests for consolidated Bash hook dispatchers.
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
const preDispatcher = path.join(__dirname, '..', '..', 'scripts', 'hooks', 'pre-bash-dispatcher.js');
|
||||
const postDispatcher = path.join(__dirname, '..', '..', 'scripts', 'hooks', 'post-bash-dispatcher.js');
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function runScript(scriptPath, input, env = {}) {
|
||||
return spawnSync('node', [scriptPath], {
|
||||
input: typeof input === 'string' ? input : JSON.stringify(input),
|
||||
encoding: 'utf8',
|
||||
env: {
|
||||
...process.env,
|
||||
...env,
|
||||
},
|
||||
timeout: 10000,
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
console.log('\n=== Testing Bash hook dispatchers ===\n');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
if (test('pre dispatcher blocks --no-verify before other Bash checks', () => {
|
||||
const input = { tool_input: { command: 'git commit --no-verify -m "x"' } };
|
||||
const result = runScript(preDispatcher, input, { ECC_HOOK_PROFILE: 'strict' });
|
||||
assert.strictEqual(result.status, 2, 'Expected dispatcher to block git hook bypass');
|
||||
assert.ok(result.stderr.includes('--no-verify'), 'Expected block-no-verify reason in stderr');
|
||||
assert.strictEqual(result.stdout, '', 'Blocking hook should not pass through stdout');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('pre dispatcher still honors per-hook disable flags', () => {
|
||||
const input = { tool_input: { command: 'git push origin main' } };
|
||||
|
||||
const enabled = runScript(preDispatcher, input, { ECC_HOOK_PROFILE: 'strict' });
|
||||
assert.strictEqual(enabled.status, 0);
|
||||
assert.ok(enabled.stderr.includes('Review changes before push'), 'Expected git push reminder when enabled');
|
||||
|
||||
const disabled = runScript(preDispatcher, input, {
|
||||
ECC_HOOK_PROFILE: 'strict',
|
||||
ECC_DISABLED_HOOKS: 'pre:bash:git-push-reminder',
|
||||
});
|
||||
assert.strictEqual(disabled.status, 0);
|
||||
assert.ok(!disabled.stderr.includes('Review changes before push'), 'Disabled hook should not emit reminder');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('pre dispatcher respects hook profiles inside the consolidated path', () => {
|
||||
const input = { tool_input: { command: 'git push origin main' } };
|
||||
const result = runScript(preDispatcher, input, { ECC_HOOK_PROFILE: 'minimal' });
|
||||
assert.strictEqual(result.status, 0);
|
||||
assert.strictEqual(result.stderr, '', 'Strict-only reminders should stay disabled in minimal profile');
|
||||
assert.strictEqual(result.stdout, JSON.stringify(input));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('post dispatcher writes both bash audit and cost logs in one pass', () => {
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-bash-dispatcher-'));
|
||||
const payload = { tool_input: { command: 'npm publish --token=$PUBLISH_TOKEN' } };
|
||||
|
||||
try {
|
||||
const result = runScript(postDispatcher, payload, {
|
||||
HOME: homeDir,
|
||||
USERPROFILE: homeDir,
|
||||
});
|
||||
assert.strictEqual(result.status, 0);
|
||||
assert.strictEqual(result.stdout, JSON.stringify(payload));
|
||||
|
||||
const auditLog = fs.readFileSync(path.join(homeDir, '.claude', 'bash-commands.log'), 'utf8');
|
||||
const costLog = fs.readFileSync(path.join(homeDir, '.claude', 'cost-tracker.log'), 'utf8');
|
||||
|
||||
assert.ok(auditLog.includes('--token=<REDACTED>'));
|
||||
assert.ok(costLog.includes('tool=Bash command=npm publish --token=<REDACTED>'));
|
||||
assert.ok(!auditLog.includes('$PUBLISH_TOKEN'));
|
||||
assert.ok(!costLog.includes('$PUBLISH_TOKEN'));
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('post dispatcher preserves PR-created hints after consolidated execution', () => {
|
||||
const payload = {
|
||||
tool_input: { command: 'gh pr create --title "Fix bug" --body "desc"' },
|
||||
tool_output: { output: 'https://github.com/owner/repo/pull/42\n' },
|
||||
};
|
||||
const result = runScript(postDispatcher, payload);
|
||||
assert.strictEqual(result.status, 0);
|
||||
assert.ok(result.stderr.includes('PR created: https://github.com/owner/repo/pull/42'));
|
||||
assert.ok(result.stderr.includes('gh pr review 42 --repo owner/repo'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -1888,6 +1888,33 @@ async function runTests() {
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
test('hooks.json consolidates Bash hooks into one pre and one post dispatcher', () => {
|
||||
const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');
|
||||
const hooks = JSON.parse(fs.readFileSync(hooksPath, 'utf8'));
|
||||
|
||||
const preBash = hooks.hooks.PreToolUse.filter(entry => entry.matcher === 'Bash');
|
||||
const postBash = hooks.hooks.PostToolUse.filter(entry => entry.matcher === 'Bash');
|
||||
|
||||
assert.strictEqual(preBash.length, 1, 'Should have exactly one PreToolUse Bash dispatcher');
|
||||
assert.strictEqual(postBash.length, 1, 'Should have exactly one PostToolUse Bash dispatcher');
|
||||
assert.strictEqual(preBash[0].id, 'pre:bash:dispatcher');
|
||||
assert.strictEqual(postBash[0].id, 'post:bash:dispatcher');
|
||||
|
||||
const preCommand = Array.isArray(preBash[0].hooks[0].command)
|
||||
? preBash[0].hooks[0].command.join(' ')
|
||||
: preBash[0].hooks[0].command;
|
||||
const postCommand = Array.isArray(postBash[0].hooks[0].command)
|
||||
? postBash[0].hooks[0].command.join(' ')
|
||||
: postBash[0].hooks[0].command;
|
||||
|
||||
assert.ok(preCommand.includes('pre-bash-dispatcher.js'), 'PreToolUse Bash hook should use the pre dispatcher');
|
||||
assert.ok(postCommand.includes('post-bash-dispatcher.js'), 'PostToolUse Bash hook should use the post dispatcher');
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
test('SessionEnd marker hook is async and cleanup-safe', () => {
|
||||
const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');
|
||||
@@ -1903,6 +1930,27 @@ async function runTests() {
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
test('all hook commands use string form for Claude Code schema compatibility', () => {
|
||||
const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');
|
||||
const hooks = JSON.parse(fs.readFileSync(hooksPath, 'utf8'));
|
||||
|
||||
for (const [eventName, hookArray] of Object.entries(hooks.hooks)) {
|
||||
for (const entry of hookArray) {
|
||||
for (const hook of entry.hooks) {
|
||||
assert.strictEqual(
|
||||
typeof hook.command,
|
||||
'string',
|
||||
`${eventName}/${entry.id || entry.matcher || 'hook'} should use string command form`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
else failed++;
|
||||
|
||||
if (
|
||||
test('all hook commands use node or approved shell wrappers', () => {
|
||||
const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');
|
||||
@@ -1941,10 +1989,8 @@ async function runTests() {
|
||||
const sessionStartHook = hooks.hooks.SessionStart?.[0]?.hooks?.[0];
|
||||
|
||||
assert.ok(sessionStartHook, 'Should define a SessionStart hook');
|
||||
const commandText = Array.isArray(sessionStartHook.command)
|
||||
? sessionStartHook.command.join(' ')
|
||||
: sessionStartHook.command;
|
||||
assert.ok(Array.isArray(sessionStartHook.command), 'SessionStart should use argv form for cross-platform safety');
|
||||
const commandText = sessionStartHook.command;
|
||||
assert.strictEqual(typeof sessionStartHook.command, 'string', 'SessionStart should use string command form for Claude Code compatibility');
|
||||
assert.ok(
|
||||
commandText.includes('session-start-bootstrap.js'),
|
||||
'SessionStart should delegate to the extracted bootstrap script'
|
||||
|
||||
@@ -256,6 +256,14 @@ function getHookCommandByDescription(hooks, lifecycle, descriptionText) {
|
||||
return hookGroup.hooks[0].command;
|
||||
}
|
||||
|
||||
function getHookCommandById(hooks, lifecycle, hookId) {
|
||||
const hookGroup = hooks.hooks[lifecycle]?.find(entry => entry.id === hookId);
|
||||
|
||||
assert.ok(hookGroup, `Expected ${lifecycle} hook with id "${hookId}"`);
|
||||
assert.ok(hookGroup.hooks?.[0]?.command, `Expected ${lifecycle} hook command for id "${hookId}"`);
|
||||
return hookGroup.hooks[0].command;
|
||||
}
|
||||
|
||||
// Test suite
|
||||
async function runTests() {
|
||||
console.log('\n=== Hook Integration Tests ===\n');
|
||||
@@ -340,12 +348,7 @@ async function runTests() {
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await asyncTest('dev server hook transforms command to tmux session', async () => {
|
||||
// Test the auto-tmux dev hook — transforms dev commands to run in tmux
|
||||
const hookCommand = getHookCommandByDescription(
|
||||
hooks,
|
||||
'PreToolUse',
|
||||
'Auto-start dev servers in tmux'
|
||||
);
|
||||
const hookCommand = getHookCommandById(hooks, 'PreToolUse', 'pre:bash:dispatcher');
|
||||
const result = await runHookCommand(hookCommand, {
|
||||
tool_input: { command: 'npm run dev' }
|
||||
});
|
||||
@@ -526,12 +529,7 @@ async function runTests() {
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await asyncTest('dev server hook transforms yarn dev to tmux session', async () => {
|
||||
// The auto-tmux dev hook transforms dev commands (yarn dev, npm run dev, etc.)
|
||||
const hookCommand = getHookCommandByDescription(
|
||||
hooks,
|
||||
'PreToolUse',
|
||||
'Auto-start dev servers in tmux'
|
||||
);
|
||||
const hookCommand = getHookCommandById(hooks, 'PreToolUse', 'pre:bash:dispatcher');
|
||||
const result = await runHookCommand(hookCommand, {
|
||||
tool_input: { command: 'yarn dev' }
|
||||
});
|
||||
@@ -663,14 +661,8 @@ async function runTests() {
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await asyncTest('PostToolUse PR hook extracts PR URL', async () => {
|
||||
// Find the PR logging hook
|
||||
const prHook = hooks.hooks.PostToolUse.find(h =>
|
||||
h.description && h.description.includes('PR URL')
|
||||
);
|
||||
|
||||
assert.ok(prHook, 'PR hook should exist');
|
||||
|
||||
const result = await runHookCommand(prHook.hooks[0].command, {
|
||||
const hookCommand = getHookCommandById(hooks, 'PostToolUse', 'post:bash:dispatcher');
|
||||
const result = await runHookCommand(hookCommand, {
|
||||
tool_input: { command: 'gh pr create --title "Test"' },
|
||||
tool_output: { output: 'Creating pull request...\nhttps://github.com/owner/repo/pull/123' }
|
||||
});
|
||||
|
||||
@@ -361,23 +361,27 @@ function runTests() {
|
||||
const claudeRoot = path.join(homeDir, '.claude');
|
||||
const installedHooks = readJson(path.join(claudeRoot, 'hooks', 'hooks.json'));
|
||||
|
||||
const installedAutoTmuxEntry = installedHooks.hooks.PreToolUse.find(entry => entry.id === 'pre:bash:auto-tmux-dev');
|
||||
assert.ok(installedAutoTmuxEntry, 'hooks/hooks.json should include the auto tmux hook');
|
||||
assert.ok(Array.isArray(installedAutoTmuxEntry.hooks[0].command), 'hooks/hooks.json should install argv-form commands for cross-platform safety');
|
||||
const installedBashDispatcherEntry = installedHooks.hooks.PreToolUse.find(entry => entry.id === 'pre:bash:dispatcher');
|
||||
assert.ok(installedBashDispatcherEntry, 'hooks/hooks.json should include the consolidated Bash dispatcher hook');
|
||||
assert.strictEqual(typeof installedBashDispatcherEntry.hooks[0].command, 'string', 'hooks/hooks.json should install string-form commands for Claude Code schema compatibility');
|
||||
assert.ok(
|
||||
installedAutoTmuxEntry.hooks[0].command[0] === 'node' && installedAutoTmuxEntry.hooks[0].command[1] === '-e',
|
||||
installedBashDispatcherEntry.hooks[0].command.startsWith('node -e '),
|
||||
'hooks/hooks.json should use the inline node bootstrap contract'
|
||||
);
|
||||
assert.ok(
|
||||
installedAutoTmuxEntry.hooks[0].command.some(part => String(part).includes('plugin-hook-bootstrap.js')),
|
||||
installedBashDispatcherEntry.hooks[0].command.includes('plugin-hook-bootstrap.js'),
|
||||
'hooks/hooks.json should route plugin-managed hooks through the shared bootstrap'
|
||||
);
|
||||
assert.ok(
|
||||
installedAutoTmuxEntry.hooks[0].command.some(part => String(part).includes('CLAUDE_PLUGIN_ROOT')),
|
||||
installedBashDispatcherEntry.hooks[0].command.includes('CLAUDE_PLUGIN_ROOT'),
|
||||
'hooks/hooks.json should still consult CLAUDE_PLUGIN_ROOT for runtime resolution'
|
||||
);
|
||||
assert.ok(
|
||||
!installedAutoTmuxEntry.hooks[0].command.some(part => String(part).includes('${CLAUDE_PLUGIN_ROOT}')),
|
||||
installedBashDispatcherEntry.hooks[0].command.includes('pre-bash-dispatcher.js'),
|
||||
'hooks/hooks.json should point the Bash preflight contract at the consolidated dispatcher'
|
||||
);
|
||||
assert.ok(
|
||||
!installedBashDispatcherEntry.hooks[0].command.includes('${CLAUDE_PLUGIN_ROOT}'),
|
||||
'hooks/hooks.json should not retain raw CLAUDE_PLUGIN_ROOT shell placeholders after install'
|
||||
);
|
||||
} finally {
|
||||
|
||||
60
tests/scripts/release-publish.test.js
Normal file
60
tests/scripts/release-publish.test.js
Normal file
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const repoRoot = path.resolve(__dirname, '..', '..');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
passed++;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
function load(relativePath) {
|
||||
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
console.log('\n=== Testing release publish workflow ===\n');
|
||||
|
||||
for (const workflow of [
|
||||
'.github/workflows/release.yml',
|
||||
'.github/workflows/reusable-release.yml',
|
||||
]) {
|
||||
const content = load(workflow);
|
||||
|
||||
test(`${workflow} grants id-token for npm provenance`, () => {
|
||||
assert.match(content, /permissions:\s*[\s\S]*id-token:\s*write/m);
|
||||
});
|
||||
|
||||
test(`${workflow} configures the npm registry`, () => {
|
||||
assert.match(content, /registry-url:\s*['"]https:\/\/registry\.npmjs\.org['"]/);
|
||||
});
|
||||
|
||||
test(`${workflow} checks whether the tagged npm version already exists`, () => {
|
||||
assert.match(content, /Check npm publish state/);
|
||||
assert.match(content, /npm view "\$\{PACKAGE_NAME\}@\$\{PACKAGE_VERSION\}" version/);
|
||||
});
|
||||
|
||||
test(`${workflow} publishes new tag versions to npm`, () => {
|
||||
assert.match(content, /npm publish --access public --provenance/);
|
||||
assert.match(content, /NODE_AUTH_TOKEN:\s*\$\{\{\s*secrets\.NPM_TOKEN\s*\}\}/);
|
||||
});
|
||||
}
|
||||
|
||||
if (failed > 0) {
|
||||
console.log(`\nFailed: ${failed}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`\nPassed: ${passed}`);
|
||||
642
yarn.lock
642
yarn.lock
@@ -100,6 +100,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gar/promise-retry@npm:^1.0.0":
|
||||
version: 1.0.3
|
||||
resolution: "@gar/promise-retry@npm:1.0.3"
|
||||
checksum: 10c0/885b02c8b0d75b2d215da25f3b639158c4fbe8fefe0d79163304534b9a6d0710db4b7699f7cd3cc1a730792bff04cbe19f4850a62d3e105a663eaeec88f38332
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@humanfs/core@npm:^0.19.1":
|
||||
version: 0.19.1
|
||||
resolution: "@humanfs/core@npm:0.19.1"
|
||||
@@ -138,6 +145,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@isaacs/fs-minipass@npm:^4.0.0":
|
||||
version: 4.0.1
|
||||
resolution: "@isaacs/fs-minipass@npm:4.0.1"
|
||||
dependencies:
|
||||
minipass: "npm:^7.0.4"
|
||||
checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3":
|
||||
version: 0.1.3
|
||||
resolution: "@istanbuljs/schema@npm:0.1.3"
|
||||
@@ -169,30 +185,109 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opencode-ai/plugin@npm:^1.0.0":
|
||||
version: 1.3.15
|
||||
resolution: "@opencode-ai/plugin@npm:1.3.15"
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/agent@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@npmcli/agent@npm:4.0.0"
|
||||
dependencies:
|
||||
"@opencode-ai/sdk": "npm:1.3.15"
|
||||
agent-base: "npm:^7.1.0"
|
||||
http-proxy-agent: "npm:^7.0.0"
|
||||
https-proxy-agent: "npm:^7.0.1"
|
||||
lru-cache: "npm:^11.2.1"
|
||||
socks-proxy-agent: "npm:^8.0.3"
|
||||
checksum: 10c0/f7b5ce0f3dd42c3f8c6546e8433573d8049f67ef11ec22aa4704bc41483122f68bf97752e06302c455ead667af5cb753e6a09bff06632bc465c1cfd4c4b75a53
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/fs@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "@npmcli/fs@npm:5.0.0"
|
||||
dependencies:
|
||||
semver: "npm:^7.3.5"
|
||||
checksum: 10c0/26e376d780f60ff16e874a0ac9bc3399186846baae0b6e1352286385ac134d900cc5dafaded77f38d77f86898fc923ae1cee9d7399f0275b1aa24878915d722b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/redact@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@npmcli/redact@npm:4.0.0"
|
||||
checksum: 10c0/a1e9ba9c70a6b40e175bda2c3dd8cfdaf096e6b7f7a132c855c083c8dfe545c3237cd56702e2e6627a580b1d63373599d49a1192c4078a85bf47bbde824df31c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opencode-ai/plugin@npm:^1.0.0":
|
||||
version: 1.14.17
|
||||
resolution: "@opencode-ai/plugin@npm:1.14.17"
|
||||
dependencies:
|
||||
"@opencode-ai/sdk": "npm:1.14.17"
|
||||
effect: "npm:4.0.0-beta.48"
|
||||
zod: "npm:4.1.8"
|
||||
peerDependencies:
|
||||
"@opentui/core": ">=0.1.96"
|
||||
"@opentui/solid": ">=0.1.96"
|
||||
"@opentui/core": ">=0.1.100"
|
||||
"@opentui/solid": ">=0.1.100"
|
||||
peerDependenciesMeta:
|
||||
"@opentui/core":
|
||||
optional: true
|
||||
"@opentui/solid":
|
||||
optional: true
|
||||
checksum: 10c0/1a662ff700812223310612f3c8c7fd4465eda5763d726ec4d29d0eae26babf344ef176c9b987d79fe1e29c8a498178881a47d7080bb9f4db3e70dad59eb8cd9e
|
||||
checksum: 10c0/d1962bcc7a4f237050556a5557ce0db3ca0082d95e035ee795fe8623b2d88e536f0f44d48a14ea895407fc3db2faef2c95835b81408d8b9a2dec3115008e4986
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opencode-ai/sdk@npm:1.3.15":
|
||||
version: 1.3.15
|
||||
resolution: "@opencode-ai/sdk@npm:1.3.15"
|
||||
"@opencode-ai/sdk@npm:1.14.17":
|
||||
version: 1.14.17
|
||||
resolution: "@opencode-ai/sdk@npm:1.14.17"
|
||||
dependencies:
|
||||
cross-spawn: "npm:7.0.6"
|
||||
checksum: 10c0/3957ae62e0ec1e339d9493e03a2440c95afdd64a608a2dc9db8383338650318a294280b2142305db5b0147badacbefa0d07e949d31167e5a4a49c9d057d016fa
|
||||
checksum: 10c0/74985b5967c7655afeb5ae54dc901c53eb123ce53c7af505b0e462d7a7d3e42dc997af40063735a2ad2fb4dcfce1aca2d3c45c5fa5c17a468f411b6b84d0e8b0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@standard-schema/spec@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@standard-schema/spec@npm:1.1.0"
|
||||
checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -256,6 +351,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"abbrev@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "abbrev@npm:4.0.0"
|
||||
checksum: 10c0/b4cc16935235e80702fc90192e349e32f8ef0ed151ef506aa78c81a7c455ec18375c4125414b99f84b2e055199d66383e787675f0bcd87da7a4dbd59f9eac1d5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"acorn-jsx@npm:^5.3.2":
|
||||
version: 5.3.2
|
||||
resolution: "acorn-jsx@npm:5.3.2"
|
||||
@@ -274,6 +376,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2":
|
||||
version: 7.1.4
|
||||
resolution: "agent-base@npm:7.1.4"
|
||||
checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ajv@npm:^6.12.4":
|
||||
version: 6.14.0
|
||||
resolution: "ajv@npm:6.14.0"
|
||||
@@ -387,6 +496,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cacache@npm:^20.0.1":
|
||||
version: 20.0.4
|
||||
resolution: "cacache@npm:20.0.4"
|
||||
dependencies:
|
||||
"@npmcli/fs": "npm:^5.0.0"
|
||||
fs-minipass: "npm:^3.0.0"
|
||||
glob: "npm:^13.0.0"
|
||||
lru-cache: "npm:^11.1.0"
|
||||
minipass: "npm:^7.0.3"
|
||||
minipass-collect: "npm:^2.0.1"
|
||||
minipass-flush: "npm:^1.0.5"
|
||||
minipass-pipeline: "npm:^1.2.4"
|
||||
p-map: "npm:^7.0.2"
|
||||
ssri: "npm:^13.0.0"
|
||||
checksum: 10c0/539bf4020e44ba9ca5afc2ec435623ed7e0dd80c020097677e6b4a0545df5cc9d20b473212d01209c8b4aea43c0d095af0bb6da97bcb991642ea6fac0d7c462b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"callsites@npm:^3.0.0":
|
||||
version: 3.1.0
|
||||
resolution: "callsites@npm:3.1.0"
|
||||
@@ -425,6 +552,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chownr@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "chownr@npm:3.0.0"
|
||||
checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cliui@npm:^8.0.1":
|
||||
version: 8.0.1
|
||||
resolution: "cliui@npm:8.0.1"
|
||||
@@ -491,7 +625,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"debug@npm:^4.0.0, debug@npm:^4.3.1, debug@npm:^4.3.2":
|
||||
"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
|
||||
version: 4.4.3
|
||||
resolution: "debug@npm:4.4.3"
|
||||
dependencies:
|
||||
@@ -533,6 +667,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"detect-libc@npm:^2.0.1":
|
||||
version: 2.1.2
|
||||
resolution: "detect-libc@npm:2.1.2"
|
||||
checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"devlop@npm:^1.0.0":
|
||||
version: 1.1.0
|
||||
resolution: "devlop@npm:1.1.0"
|
||||
@@ -563,6 +704,24 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"effect@npm:4.0.0-beta.48":
|
||||
version: 4.0.0-beta.48
|
||||
resolution: "effect@npm:4.0.0-beta.48"
|
||||
dependencies:
|
||||
"@standard-schema/spec": "npm:^1.1.0"
|
||||
fast-check: "npm:^4.6.0"
|
||||
find-my-way-ts: "npm:^0.1.6"
|
||||
ini: "npm:^6.0.0"
|
||||
kubernetes-types: "npm:^1.30.0"
|
||||
msgpackr: "npm:^1.11.9"
|
||||
multipasta: "npm:^0.2.7"
|
||||
toml: "npm:^4.1.1"
|
||||
uuid: "npm:^13.0.0"
|
||||
yaml: "npm:^2.8.3"
|
||||
checksum: 10c0/dcd1ac9dbaa43b8bc3b3bd3ec1158b245c038c4522c2d3724d96243dc684773df21118cb2ed6fc648913ac6e9d5f016358d8495515f0c1863d81320b663ce312
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"emoji-regex@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "emoji-regex@npm:8.0.0"
|
||||
@@ -577,6 +736,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"env-paths@npm:^2.2.0":
|
||||
version: 2.2.1
|
||||
resolution: "env-paths@npm:2.2.1"
|
||||
checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"escalade@npm:^3.1.1":
|
||||
version: 3.2.0
|
||||
resolution: "escalade@npm:3.2.0"
|
||||
@@ -707,6 +873,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"exponential-backoff@npm:^3.1.1":
|
||||
version: 3.1.3
|
||||
resolution: "exponential-backoff@npm:3.1.3"
|
||||
checksum: 10c0/77e3ae682b7b1f4972f563c6dbcd2b0d54ac679e62d5d32f3e5085feba20483cf28bd505543f520e287a56d4d55a28d7874299941faf637e779a1aa5994d1267
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-check@npm:^4.6.0":
|
||||
version: 4.7.0
|
||||
resolution: "fast-check@npm:4.7.0"
|
||||
dependencies:
|
||||
pure-rand: "npm:^8.0.0"
|
||||
checksum: 10c0/7edce2b82d11d5325e9e79a2377e1f6e7200d27219edda2e3449d827e994c34461132fc149c90e41b78fc8e6ef4aae77d45350ac7bb1bc4a81110401d0a49fbc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
|
||||
version: 3.1.3
|
||||
resolution: "fast-deep-equal@npm:3.1.3"
|
||||
@@ -756,6 +938,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"find-my-way-ts@npm:^0.1.6":
|
||||
version: 0.1.6
|
||||
resolution: "find-my-way-ts@npm:0.1.6"
|
||||
checksum: 10c0/16ad4b15275b56ee0ec361d0c61afbdff4c75bd0ac04112f6910f188cb1058096ba63529c2363914da6bb60266aa4def1025af04af26368ff87eb0df52f2862f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"find-up@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "find-up@npm:5.0.0"
|
||||
@@ -793,6 +982,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fs-minipass@npm:^3.0.0":
|
||||
version: 3.0.3
|
||||
resolution: "fs-minipass@npm:3.0.3"
|
||||
dependencies:
|
||||
minipass: "npm:^7.0.3"
|
||||
checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-caller-file@npm:^2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "get-caller-file@npm:2.0.5"
|
||||
@@ -816,7 +1014,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^13.0.6":
|
||||
"glob@npm:^13.0.0, glob@npm:^13.0.6":
|
||||
version: 13.0.6
|
||||
resolution: "glob@npm:13.0.6"
|
||||
dependencies:
|
||||
@@ -835,9 +1033,16 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"globals@npm:^17.4.0":
|
||||
version: 17.4.0
|
||||
resolution: "globals@npm:17.4.0"
|
||||
checksum: 10c0/2be9e8c2b9035836f13d420b22f0247a328db82967d3bebfc01126d888ed609305f06c05895914e969653af5c6ba35fd7a0920f3e6c869afa60666c810630feb
|
||||
version: 17.5.0
|
||||
resolution: "globals@npm:17.5.0"
|
||||
checksum: 10c0/92828102ed2f5637907725f0478038bed02fc83e9fc89300bb753639ba7c022b6c02576fc772117302b431b204591db1f2fa909d26f3f0a9852cc856a941df3f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"graceful-fs@npm:^4.2.6":
|
||||
version: 4.2.11
|
||||
resolution: "graceful-fs@npm:4.2.11"
|
||||
checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -855,6 +1060,42 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-cache-semantics@npm:^4.1.1":
|
||||
version: 4.2.0
|
||||
resolution: "http-cache-semantics@npm:4.2.0"
|
||||
checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-proxy-agent@npm:^7.0.0":
|
||||
version: 7.0.2
|
||||
resolution: "http-proxy-agent@npm:7.0.2"
|
||||
dependencies:
|
||||
agent-base: "npm:^7.1.0"
|
||||
debug: "npm:^4.3.4"
|
||||
checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"https-proxy-agent@npm:^7.0.1":
|
||||
version: 7.0.6
|
||||
resolution: "https-proxy-agent@npm:7.0.6"
|
||||
dependencies:
|
||||
agent-base: "npm:^7.1.2"
|
||||
debug: "npm:4"
|
||||
checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-lite@npm:^0.7.2":
|
||||
version: 0.7.2
|
||||
resolution: "iconv-lite@npm:0.7.2"
|
||||
dependencies:
|
||||
safer-buffer: "npm:>= 2.1.2 < 3.0.0"
|
||||
checksum: 10c0/3c228920f3bd307f56bf8363706a776f4a060eb042f131cd23855ceca962951b264d0997ab38a1ad340e1c5df8499ed26e1f4f0db6b2a2ad9befaff22f14b722
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ignore@npm:^5.2.0":
|
||||
version: 5.3.2
|
||||
resolution: "ignore@npm:5.3.2"
|
||||
@@ -886,6 +1127,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ini@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "ini@npm:6.0.0"
|
||||
checksum: 10c0/9a7f55f306e2b25b41ae67c8b526e8f4673f057b70852b9025816ef4f15f07bf1ba35ed68ea4471ff7b31718f7ef1bc50d709f8d03cb012e10a3135eb99c7206
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ini@npm:~4.1.0":
|
||||
version: 4.1.3
|
||||
resolution: "ini@npm:4.1.3"
|
||||
@@ -893,6 +1141,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ip-address@npm:^10.0.1":
|
||||
version: 10.1.0
|
||||
resolution: "ip-address@npm:10.1.0"
|
||||
checksum: 10c0/0103516cfa93f6433b3bd7333fa876eb21263912329bfa47010af5e16934eeeff86f3d2ae700a3744a137839ddfad62b900c7a445607884a49b5d1e32a3d7566
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-alphabetical@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "is-alphabetical@npm:2.0.1"
|
||||
@@ -954,6 +1209,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isexe@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "isexe@npm:4.0.0"
|
||||
checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0":
|
||||
version: 3.2.2
|
||||
resolution: "istanbul-lib-coverage@npm:3.2.2"
|
||||
@@ -1055,6 +1317,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"kubernetes-types@npm:^1.30.0":
|
||||
version: 1.30.0
|
||||
resolution: "kubernetes-types@npm:1.30.0"
|
||||
checksum: 10c0/de3641e4f50cfc123c4102a73c12932e1db8e51783c7cae4ea8ad3561bd56fab0f1c2346801f84a4c36aae8cea0b25d21e9514cc0fcecd4d64b1314043263076
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"levn@npm:^0.4.1":
|
||||
version: 0.4.1
|
||||
resolution: "levn@npm:0.4.1"
|
||||
@@ -1097,6 +1366,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1":
|
||||
version: 11.3.5
|
||||
resolution: "lru-cache@npm:11.3.5"
|
||||
checksum: 10c0/5b54ef7b88afb4bd25b7a778f1b2b1cde32d9770913e530da34ab203cf0442413bcaa6e372800cbab9562557a4480e4d8bf32e3a368bb5a91b12218eca085c66
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-dir@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "make-dir@npm:4.0.0"
|
||||
@@ -1106,6 +1382,26 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-fetch-happen@npm:^15.0.0":
|
||||
version: 15.0.5
|
||||
resolution: "make-fetch-happen@npm:15.0.5"
|
||||
dependencies:
|
||||
"@gar/promise-retry": "npm:^1.0.0"
|
||||
"@npmcli/agent": "npm:^4.0.0"
|
||||
"@npmcli/redact": "npm:^4.0.0"
|
||||
cacache: "npm:^20.0.1"
|
||||
http-cache-semantics: "npm:^4.1.1"
|
||||
minipass: "npm:^7.0.2"
|
||||
minipass-fetch: "npm:^5.0.0"
|
||||
minipass-flush: "npm:^1.0.5"
|
||||
minipass-pipeline: "npm:^1.2.4"
|
||||
negotiator: "npm:^1.0.0"
|
||||
proc-log: "npm:^6.0.0"
|
||||
ssri: "npm:^13.0.0"
|
||||
checksum: 10c0/527580eb5e5476e6ad07a4e3bd017d13e935f4be815674b442081ae5a721c13d3af5715006619e6be79a85723067e047f83a0c9e699f41d8cec43609a8de4f7b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"markdown-it@npm:~14.1.1":
|
||||
version: 14.1.1
|
||||
resolution: "markdown-it@npm:14.1.1"
|
||||
@@ -1488,13 +1784,82 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass@npm:^7.1.2, minipass@npm:^7.1.3":
|
||||
"minipass-collect@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "minipass-collect@npm:2.0.1"
|
||||
dependencies:
|
||||
minipass: "npm:^7.0.3"
|
||||
checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-fetch@npm:^5.0.0":
|
||||
version: 5.0.2
|
||||
resolution: "minipass-fetch@npm:5.0.2"
|
||||
dependencies:
|
||||
iconv-lite: "npm:^0.7.2"
|
||||
minipass: "npm:^7.0.3"
|
||||
minipass-sized: "npm:^2.0.0"
|
||||
minizlib: "npm:^3.0.1"
|
||||
dependenciesMeta:
|
||||
iconv-lite:
|
||||
optional: true
|
||||
checksum: 10c0/ce4ab9f21cfabaead2097d95dd33f485af8072fbc6b19611bce694965393453a1639d641c2bcf1c48f2ea7d41ea7fab8278373f1d0bee4e63b0a5b2cdd0ef649
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-flush@npm:^1.0.5":
|
||||
version: 1.0.7
|
||||
resolution: "minipass-flush@npm:1.0.7"
|
||||
dependencies:
|
||||
minipass: "npm:^3.0.0"
|
||||
checksum: 10c0/960915c02aa0991662c37c404517dd93708d17f96533b2ca8c1e776d158715d8107c5ced425ffc61674c167d93607f07f48a83c139ce1057f8781e5dfb4b90c2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-pipeline@npm:^1.2.4":
|
||||
version: 1.2.4
|
||||
resolution: "minipass-pipeline@npm:1.2.4"
|
||||
dependencies:
|
||||
minipass: "npm:^3.0.0"
|
||||
checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-sized@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "minipass-sized@npm:2.0.0"
|
||||
dependencies:
|
||||
minipass: "npm:^7.1.2"
|
||||
checksum: 10c0/f9201696a6f6d68610d04c9c83e3d2e5cb9c026aae1c8cbf7e17f386105cb79c1bb088dbc21bf0b1eb4f3fb5df384fd1e7aa3bf1f33868c416ae8c8a92679db8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass@npm:^3.0.0":
|
||||
version: 3.3.6
|
||||
resolution: "minipass@npm:3.3.6"
|
||||
dependencies:
|
||||
yallist: "npm:^4.0.0"
|
||||
checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2, minipass@npm:^7.1.3":
|
||||
version: 7.1.3
|
||||
resolution: "minipass@npm:7.1.3"
|
||||
checksum: 10c0/539da88daca16533211ea5a9ee98dc62ff5742f531f54640dd34429e621955e91cc280a91a776026264b7f9f6735947629f920944e9c1558369e8bf22eb33fbb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "minizlib@npm:3.1.0"
|
||||
dependencies:
|
||||
minipass: "npm:^7.1.2"
|
||||
checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ms@npm:^2.1.3":
|
||||
version: 2.1.3
|
||||
resolution: "ms@npm:2.1.3"
|
||||
@@ -1502,6 +1867,56 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"msgpackr-extract@npm:^3.0.2":
|
||||
version: 3.0.3
|
||||
resolution: "msgpackr-extract@npm:3.0.3"
|
||||
dependencies:
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": "npm:3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": "npm:3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm": "npm:3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": "npm:3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64": "npm:3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64": "npm:3.0.3"
|
||||
node-gyp: "npm:latest"
|
||||
node-gyp-build-optional-packages: "npm:5.2.2"
|
||||
dependenciesMeta:
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64":
|
||||
optional: true
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64":
|
||||
optional: true
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm":
|
||||
optional: true
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64":
|
||||
optional: true
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64":
|
||||
optional: true
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
download-msgpackr-prebuilds: bin/download-prebuilds.js
|
||||
checksum: 10c0/e504fd8bf86a29d7527c83776530ee6dc92dcb0273bb3679fd4a85173efead7f0ee32fb82c8410a13c33ef32828c45f81118ffc0fbed5d6842e72299894623b4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"msgpackr@npm:^1.11.9":
|
||||
version: 1.11.10
|
||||
resolution: "msgpackr@npm:1.11.10"
|
||||
dependencies:
|
||||
msgpackr-extract: "npm:^3.0.2"
|
||||
dependenciesMeta:
|
||||
msgpackr-extract:
|
||||
optional: true
|
||||
checksum: 10c0/fa5b8b90661cc66127d4550bc3757d0e72fe3217a47f952acd0df647afb4593ffde0bbdb1c9f5a13b9df15d5a170a570a59728dd7ede9b0d711e20e4f970fa82
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multipasta@npm:^0.2.7":
|
||||
version: 0.2.7
|
||||
resolution: "multipasta@npm:0.2.7"
|
||||
checksum: 10c0/15917ac88aeefa5b8afac44b90d1e9d0d0ec7148b51e0766f07a69a220ecebcb6404539a856c45aa85a3d7fe517bc58febe81437146705f17ecd2961dc0b9fa5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"natural-compare@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "natural-compare@npm:1.4.0"
|
||||
@@ -1509,6 +1924,57 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"negotiator@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "negotiator@npm:1.0.0"
|
||||
checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-gyp-build-optional-packages@npm:5.2.2":
|
||||
version: 5.2.2
|
||||
resolution: "node-gyp-build-optional-packages@npm:5.2.2"
|
||||
dependencies:
|
||||
detect-libc: "npm:^2.0.1"
|
||||
bin:
|
||||
node-gyp-build-optional-packages: bin.js
|
||||
node-gyp-build-optional-packages-optional: optional.js
|
||||
node-gyp-build-optional-packages-test: build-test.js
|
||||
checksum: 10c0/c81128c6f91873381be178c5eddcbdf66a148a6a89a427ce2bcd457593ce69baf2a8662b6d22cac092d24aa9c43c230dec4e69b3a0da604503f4777cd77e282b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-gyp@npm:latest":
|
||||
version: 12.2.0
|
||||
resolution: "node-gyp@npm:12.2.0"
|
||||
dependencies:
|
||||
env-paths: "npm:^2.2.0"
|
||||
exponential-backoff: "npm:^3.1.1"
|
||||
graceful-fs: "npm:^4.2.6"
|
||||
make-fetch-happen: "npm:^15.0.0"
|
||||
nopt: "npm:^9.0.0"
|
||||
proc-log: "npm:^6.0.0"
|
||||
semver: "npm:^7.3.5"
|
||||
tar: "npm:^7.5.4"
|
||||
tinyglobby: "npm:^0.2.12"
|
||||
which: "npm:^6.0.0"
|
||||
bin:
|
||||
node-gyp: bin/node-gyp.js
|
||||
checksum: 10c0/3ed046746a5a7d90950cd8b0547332b06598443f31fe213ef4332a7174c7b7d259e1704835feda79b87d3f02e59d7791842aac60642ede4396ab25fdf0f8f759
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"nopt@npm:^9.0.0":
|
||||
version: 9.0.0
|
||||
resolution: "nopt@npm:9.0.0"
|
||||
dependencies:
|
||||
abbrev: "npm:^4.0.0"
|
||||
bin:
|
||||
nopt: bin/nopt.js
|
||||
checksum: 10c0/1822eb6f9b020ef6f7a7516d7b64a8036e09666ea55ac40416c36e4b2b343122c3cff0e2f085675f53de1d2db99a2a89a60ccea1d120bcd6a5347bf6ceb4a7fd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"optionator@npm:^0.9.3":
|
||||
version: 0.9.4
|
||||
resolution: "optionator@npm:0.9.4"
|
||||
@@ -1541,6 +2007,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-map@npm:^7.0.2":
|
||||
version: 7.0.4
|
||||
resolution: "p-map@npm:7.0.4"
|
||||
checksum: 10c0/a5030935d3cb2919d7e89454d1ce82141e6f9955413658b8c9403cfe379283770ed3048146b44cde168aa9e8c716505f196d5689db0ae3ce9a71521a2fef3abd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parent-module@npm:^1.0.0":
|
||||
version: 1.0.1
|
||||
resolution: "parent-module@npm:1.0.1"
|
||||
@@ -1589,7 +2062,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picomatch@npm:^4.0.3":
|
||||
"picomatch@npm:^4.0.3, picomatch@npm:^4.0.4":
|
||||
version: 4.0.4
|
||||
resolution: "picomatch@npm:4.0.4"
|
||||
checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0
|
||||
@@ -1603,6 +2076,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"proc-log@npm:^6.0.0":
|
||||
version: 6.1.0
|
||||
resolution: "proc-log@npm:6.1.0"
|
||||
checksum: 10c0/4f178d4062733ead9d71a9b1ab24ebcecdfe2250916a5b1555f04fe2eda972a0ec76fbaa8df1ad9c02707add6749219d118a4fc46dc56bdfe4dde4b47d80bb82
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"punycode.js@npm:^2.3.1":
|
||||
version: 2.3.1
|
||||
resolution: "punycode.js@npm:2.3.1"
|
||||
@@ -1617,6 +2097,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pure-rand@npm:^8.0.0":
|
||||
version: 8.4.0
|
||||
resolution: "pure-rand@npm:8.4.0"
|
||||
checksum: 10c0/6414bbc1c6f45fb774173431c7205e79783b77cfae0e2145e741b6999363554dbd2f4210d2a5bc08683e0b2f6823198c9308766b1d0911e1dccd7beb8842f860
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"require-directory@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "require-directory@npm:2.1.1"
|
||||
@@ -1652,7 +2139,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^7.5.3":
|
||||
"safer-buffer@npm:>= 2.1.2 < 3.0.0":
|
||||
version: 2.1.2
|
||||
resolution: "safer-buffer@npm:2.1.2"
|
||||
checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^7.3.5, semver@npm:^7.5.3":
|
||||
version: 7.7.4
|
||||
resolution: "semver@npm:7.7.4"
|
||||
bin:
|
||||
@@ -1684,6 +2178,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"smart-buffer@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "smart-buffer@npm:4.2.0"
|
||||
checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"smol-toml@npm:~1.6.0":
|
||||
version: 1.6.1
|
||||
resolution: "smol-toml@npm:1.6.1"
|
||||
@@ -1691,6 +2192,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"socks-proxy-agent@npm:^8.0.3":
|
||||
version: 8.0.5
|
||||
resolution: "socks-proxy-agent@npm:8.0.5"
|
||||
dependencies:
|
||||
agent-base: "npm:^7.1.2"
|
||||
debug: "npm:^4.3.4"
|
||||
socks: "npm:^2.8.3"
|
||||
checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"socks@npm:^2.8.3":
|
||||
version: 2.8.7
|
||||
resolution: "socks@npm:2.8.7"
|
||||
dependencies:
|
||||
ip-address: "npm:^10.0.1"
|
||||
smart-buffer: "npm:^4.2.0"
|
||||
checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sql.js@npm:^1.14.1":
|
||||
version: 1.14.1
|
||||
resolution: "sql.js@npm:1.14.1"
|
||||
@@ -1698,6 +2220,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ssri@npm:^13.0.0":
|
||||
version: 13.0.1
|
||||
resolution: "ssri@npm:13.0.1"
|
||||
dependencies:
|
||||
minipass: "npm:^7.0.3"
|
||||
checksum: 10c0/cf6408a18676c57ff2ed06b8a20dc64bb3e748e5c7e095332e6aecaa2b8422b1e94a739a8453bf65156a8a47afe23757ba4ab52d3ea3b62322dc40875763e17a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string-width@npm:8.1.0":
|
||||
version: 8.1.0
|
||||
resolution: "string-width@npm:8.1.0"
|
||||
@@ -1753,6 +2284,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tar@npm:^7.5.4":
|
||||
version: 7.5.13
|
||||
resolution: "tar@npm:7.5.13"
|
||||
dependencies:
|
||||
"@isaacs/fs-minipass": "npm:^4.0.0"
|
||||
chownr: "npm:^3.0.0"
|
||||
minipass: "npm:^7.1.2"
|
||||
minizlib: "npm:^3.1.0"
|
||||
yallist: "npm:^5.0.0"
|
||||
checksum: 10c0/5c65b8084799bde7a791593a1c1a45d3d6ee98182e3700b24c247b7b8f8654df4191642abbdb07ff25043d45dcff35620827c3997b88ae6c12040f64bed5076b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"test-exclude@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "test-exclude@npm:8.0.0"
|
||||
@@ -1764,6 +2308,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tinyglobby@npm:^0.2.12":
|
||||
version: 0.2.16
|
||||
resolution: "tinyglobby@npm:0.2.16"
|
||||
dependencies:
|
||||
fdir: "npm:^6.5.0"
|
||||
picomatch: "npm:^4.0.4"
|
||||
checksum: 10c0/f2e09fd93dd95c41e522113b686ff6f7c13020962f8698a864a257f3d7737599afc47722b7ab726e12f8a813f779906187911ff8ee6701ede65072671a7e934b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tinyglobby@npm:~0.2.15":
|
||||
version: 0.2.15
|
||||
resolution: "tinyglobby@npm:0.2.15"
|
||||
@@ -1774,6 +2328,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"toml@npm:^4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "toml@npm:4.1.1"
|
||||
checksum: 10c0/077bc02ac1ce82091ea073f675d7e2a1df487d1b18bbc7e653daba4956d545954b7095e979b8792f0837339b901ee190ad4464342e5e377c36bbdeca8903e079
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"type-check@npm:^0.4.0, type-check@npm:~0.4.0":
|
||||
version: 0.4.0
|
||||
resolution: "type-check@npm:0.4.0"
|
||||
@@ -1826,6 +2387,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"uuid@npm:^13.0.0":
|
||||
version: 13.0.0
|
||||
resolution: "uuid@npm:13.0.0"
|
||||
bin:
|
||||
uuid: dist-node/bin/uuid
|
||||
checksum: 10c0/950e4c18d57fef6c69675344f5700a08af21e26b9eff2bf2180427564297368c538ea11ac9fb2e6528b17fc3966a9fd2c5049361b0b63c7d654f3c550c9b3d67
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"v8-to-istanbul@npm:^9.0.0":
|
||||
version: 9.3.0
|
||||
resolution: "v8-to-istanbul@npm:9.3.0"
|
||||
@@ -1848,6 +2418,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"which@npm:^6.0.0":
|
||||
version: 6.0.1
|
||||
resolution: "which@npm:6.0.1"
|
||||
dependencies:
|
||||
isexe: "npm:^4.0.0"
|
||||
bin:
|
||||
node-which: bin/which.js
|
||||
checksum: 10c0/7e710e54ea36d2d6183bee2f9caa27a3b47b9baf8dee55a199b736fcf85eab3b9df7556fca3d02b50af7f3dfba5ea3a45644189836df06267df457e354da66d5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"word-wrap@npm:^1.2.5":
|
||||
version: 1.2.5
|
||||
resolution: "word-wrap@npm:1.2.5"
|
||||
@@ -1873,6 +2454,29 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yallist@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "yallist@npm:4.0.0"
|
||||
checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yallist@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "yallist@npm:5.0.0"
|
||||
checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yaml@npm:^2.8.3":
|
||||
version: 2.8.3
|
||||
resolution: "yaml@npm:2.8.3"
|
||||
bin:
|
||||
yaml: bin.mjs
|
||||
checksum: 10c0/ddff0e11c1b467728d7eb4633db61c5f5de3d8e9373cf84d08fb0cdee03e1f58f02b9f1c51a4a8a865751695addbd465a77f73f1079be91fe5493b29c305fd77
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs-parser@npm:^21.1.1":
|
||||
version: 21.1.1
|
||||
resolution: "yargs-parser@npm:21.1.1"
|
||||
|
||||
Reference in New Issue
Block a user