fix: shorten plugin slug to ecc

This commit is contained in:
Affaan Mustafa 2026-04-05 14:31:30 -07:00
parent 908116d736
commit 1346f83b08
27 changed files with 233 additions and 144 deletions

View File

@ -1,11 +1,11 @@
{ {
"name": "everything-claude-code", "name": "ecc",
"interface": { "interface": {
"displayName": "Everything Claude Code" "displayName": "Everything Claude Code"
}, },
"plugins": [ "plugins": [
{ {
"name": "everything-claude-code", "name": "ecc",
"source": { "source": {
"source": "local", "source": "local",
"path": "../.." "path": "../.."

View File

@ -1,6 +1,6 @@
{ {
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json", "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "everything-claude-code", "name": "ecc",
"description": "Battle-tested Claude Code configurations from an Anthropic hackathon winner — agents, skills, hooks, rules, and legacy command shims evolved over 10+ months of intensive daily use", "description": "Battle-tested Claude Code configurations from an Anthropic hackathon winner — agents, skills, hooks, rules, and legacy command shims evolved over 10+ months of intensive daily use",
"owner": { "owner": {
"name": "Affaan Mustafa", "name": "Affaan Mustafa",
@ -11,7 +11,7 @@
}, },
"plugins": [ "plugins": [
{ {
"name": "everything-claude-code", "name": "ecc",
"source": "./", "source": "./",
"description": "The most comprehensive Claude Code plugin — 38 agents, 156 skills, 72 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning", "description": "The most comprehensive Claude Code plugin — 38 agents, 156 skills, 72 legacy command shims, selective install profiles, and production-ready hooks for TDD, security scanning, code review, and continuous learning",
"version": "1.10.0", "version": "1.10.0",

View File

@ -1,5 +1,5 @@
{ {
"name": "everything-claude-code", "name": "ecc",
"version": "1.10.0", "version": "1.10.0",
"description": "Battle-tested Claude Code plugin for engineering teams — 38 agents, 156 skills, 72 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use", "description": "Battle-tested Claude Code plugin for engineering teams — 38 agents, 156 skills, 72 legacy command shims, production-ready hooks, and selective install workflows evolved through continuous real-world use",
"author": { "author": {

View File

@ -30,6 +30,9 @@ codex plugin install ./
Run this from the repository root so `./` points to the repo root and `.mcp.json` resolves correctly. Run this from the repository root so `./` points to the repo root and `.mcp.json` resolves correctly.
``` ```
The installed plugin registers under the short slug `ecc` so tool and command names
stay below provider length limits.
## MCP Servers Included ## MCP Servers Included
| Server | Purpose | | Server | Purpose |

View File

@ -1,5 +1,5 @@
{ {
"name": "everything-claude-code", "name": "ecc",
"version": "1.10.0", "version": "1.10.0",
"description": "Battle-tested Codex workflows — 156 shared ECC skills, production-ready MCP configs, and selective-install-aligned conventions for TDD, security scanning, code review, and autonomous development.", "description": "Battle-tested Codex workflows — 156 shared ECC skills, production-ready MCP configs, and selective-install-aligned conventions for TDD, security scanning, code review, and autonomous development.",
"author": { "author": {

View File

@ -173,7 +173,7 @@ Get up and running in under 2 minutes:
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install plugin # Install plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### Step 2: Install Rules (Required) ### Step 2: Install Rules (Required)
@ -227,13 +227,13 @@ For manual install instructions see the README in the `rules/` folder. When copy
# Existing slash-style command names still work while ECC migrates off commands/. # Existing slash-style command names still work while ECC migrates off commands/.
# Plugin install uses the namespaced form # Plugin install uses the namespaced form
/everything-claude-code:plan "Add user authentication" /ecc:plan "Add user authentication"
# Manual install keeps the shorter slash form: # Manual install keeps the shorter slash form:
# /plan "Add user authentication" # /plan "Add user authentication"
# Check available commands # Check available commands
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**That's it!** You now have access to 38 agents, 159 skills, and 72 legacy command shims. **That's it!** You now have access to 38 agents, 159 skills, and 72 legacy command shims.
@ -621,7 +621,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 /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install the plugin # Install the plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
Or add directly to your `~/.claude/settings.json`: Or add directly to your `~/.claude/settings.json`:
@ -629,7 +629,7 @@ Or add directly to your `~/.claude/settings.json`:
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -637,7 +637,7 @@ Or add directly to your `~/.claude/settings.json`:
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```
@ -781,8 +781,8 @@ Not sure where to start? Use this quick reference. Skills are the canonical work
| I want to... | Use this command | Agent used | | I want to... | Use this command | Agent used |
|--------------|-----------------|------------| |--------------|-----------------|------------|
| Plan a new feature | `/everything-claude-code:plan "Add auth"` | planner | | Plan a new feature | `/ecc:plan "Add auth"` | planner |
| Design system architecture | `/everything-claude-code:plan` + architect agent | architect | | Design system architecture | `/ecc:plan` + architect agent | architect |
| Write code with tests first | `/tdd` | tdd-guide | | Write code with tests first | `/tdd` | tdd-guide |
| Review code I just wrote | `/code-review` | code-reviewer | | Review code I just wrote | `/code-review` | code-reviewer |
| Fix a failing build | `/build-fix` | build-error-resolver | | Fix a failing build | `/build-fix` | build-error-resolver |
@ -801,7 +801,7 @@ Slash forms below are shown because they are still the fastest familiar entrypoi
**Starting a new feature:** **Starting a new feature:**
``` ```
/everything-claude-code:plan "Add user authentication with OAuth" /ecc:plan "Add user authentication with OAuth"
→ planner creates implementation blueprint → planner creates implementation blueprint
/tdd → tdd-guide enforces write-tests-first /tdd → tdd-guide enforces write-tests-first
/code-review → code-reviewer checks your work /code-review → code-reviewer checks your work
@ -829,7 +829,7 @@ Slash forms below are shown because they are still the fastest familiar entrypoi
<summary><b>How do I check which agents/commands are installed?</b></summary> <summary><b>How do I check which agents/commands are installed?</b></summary>
```bash ```bash
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
This shows all available agents, commands, and skills from the plugin. This shows all available agents, commands, and skills from the plugin.

View File

@ -71,7 +71,7 @@
/plugin marketplace add affaan-m/everything-claude-code /plugin marketplace add affaan-m/everything-claude-code
# 安装插件 # 安装插件
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### 第二步:安装规则(必需) ### 第二步:安装规则(必需)
@ -97,13 +97,13 @@ cp -r everything-claude-code/rules/perl ~/.claude/rules/
```bash ```bash
# 尝试一个命令(插件安装使用命名空间形式) # 尝试一个命令(插件安装使用命名空间形式)
/everything-claude-code:plan "添加用户认证" /ecc:plan "添加用户认证"
# 手动安装选项2使用简短形式 # 手动安装选项2使用简短形式
# /plan "添加用户认证" # /plan "添加用户认证"
# 查看可用命令 # 查看可用命令
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**完成!** 你现在可以使用 38 个代理、159 个技能和 72 个命令。 **完成!** 你现在可以使用 38 个代理、159 个技能和 72 个命令。
@ -339,7 +339,7 @@ everything-claude-code/
/plugin marketplace add affaan-m/everything-claude-code /plugin marketplace add affaan-m/everything-claude-code
# 安装插件 # 安装插件
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
或直接添加到你的 `~/.claude/settings.json` 或直接添加到你的 `~/.claude/settings.json`
@ -347,7 +347,7 @@ everything-claude-code/
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -355,7 +355,7 @@ everything-claude-code/
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```

View File

@ -370,7 +370,7 @@ chmod -R u+rwX,go+rX ~/.claude/homunculus
```bash ```bash
# Install plugin dependencies # Install plugin dependencies
cd ~/.claude/plugins/cache/everything-claude-code cd ~/.claude/plugins/cache/ecc
npm install npm install
# Or for manual install # Or for manual install

View File

@ -11,6 +11,7 @@ Public ECC plugin repo for agents, skills, commands, hooks, rules, install surfa
- Default branch: `main` - Default branch: `main`
- Public release surface is aligned at `v1.10.0` - Public release surface is aligned at `v1.10.0`
- Public catalog truth is `38` agents, `72` commands, and `159` skills - Public catalog truth is `38` agents, `72` commands, and `159` skills
- Public plugin slug is now `ecc`; legacy `everything-claude-code` install paths remain supported for compatibility
- Release discussion: `#1272` - Release discussion: `#1272`
- ECC 2.0 exists in-tree and builds, but it is still alpha rather than GA - ECC 2.0 exists in-tree and builds, but it is still alpha rather than GA
- Main active operational work: - Main active operational work:

View File

@ -110,7 +110,7 @@
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# プラグインをインストール # プラグインをインストール
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### ステップ2ルールをインストール必須 ### ステップ2ルールをインストール必須
@ -134,13 +134,13 @@ cp -r everything-claude-code/rules/golang/* ~/.claude/rules/
```bash ```bash
# コマンドを試す(プラグインはネームスペース形式) # コマンドを試す(プラグインはネームスペース形式)
/everything-claude-code:plan "ユーザー認証を追加" /ecc:plan "ユーザー認証を追加"
# 手動インストールオプション2は短縮形式 # 手動インストールオプション2は短縮形式
# /plan "ユーザー認証を追加" # /plan "ユーザー認証を追加"
# 利用可能なコマンドを確認 # 利用可能なコマンドを確認
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**完了です!** これで13のエージェント、43のスキル、31のコマンドにアクセスできます。 **完了です!** これで13のエージェント、43のスキル、31のコマンドにアクセスできます。
@ -427,7 +427,7 @@ Duplicate hook file detected: ./hooks/hooks.json is already resolved to a loaded
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# プラグインをインストール # プラグインをインストール
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
または、`~/.claude/settings.json` に直接追加: または、`~/.claude/settings.json` に直接追加:
@ -435,7 +435,7 @@ Duplicate hook file detected: ./hooks/hooks.json is already resolved to a loaded
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -443,7 +443,7 @@ Duplicate hook file detected: ./hooks/hooks.json is already resolved to a loaded
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```

View File

@ -17,7 +17,7 @@ Everything Claude Code プロジェクトのインタラクティブなステッ
## 前提条件 ## 前提条件
このスキルは起動前に Claude Code からアクセス可能である必要があります。ブートストラップには2つの方法があります このスキルは起動前に Claude Code からアクセス可能である必要があります。ブートストラップには2つの方法があります
1. **プラグイン経由**: `/plugin install everything-claude-code` — プラグインがこのスキルを自動的にロードします 1. **プラグイン経由**: `/plugin install ecc@ecc` — プラグインがこのスキルを自動的にロードします
2. **手動**: このスキルのみを `~/.claude/skills/configure-ecc/SKILL.md` にコピーし、"configure ecc" と言って起動します 2. **手動**: このスキルのみを `~/.claude/skills/configure-ecc/SKILL.md` にコピーし、"configure ecc" と言って起動します
--- ---

View File

@ -115,7 +115,7 @@
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# 플러그인 설치 # 플러그인 설치
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### 2단계: 룰 설치 (필수) ### 2단계: 룰 설치 (필수)
@ -141,13 +141,13 @@ cd everything-claude-code
```bash ```bash
# 커맨드 실행 (플러그인 설치 시 네임스페이스 형태 사용) # 커맨드 실행 (플러그인 설치 시 네임스페이스 형태 사용)
/everything-claude-code:plan "사용자 인증 추가" /ecc:plan "사용자 인증 추가"
# 수동 설치(옵션 2) 시에는 짧은 형태를 사용: # 수동 설치(옵션 2) 시에는 짧은 형태를 사용:
# /plan "사용자 인증 추가" # /plan "사용자 인증 추가"
# 사용 가능한 커맨드 확인 # 사용 가능한 커맨드 확인
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**끝!** 이제 16개 에이전트, 65개 스킬, 40개 커맨드를 사용할 수 있습니다. **끝!** 이제 16개 에이전트, 65개 스킬, 40개 커맨드를 사용할 수 있습니다.
@ -359,7 +359,7 @@ Claude Code v2.1+는 설치된 플러그인의 `hooks/hooks.json`을 **자동으
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# 플러그인 설치 # 플러그인 설치
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
또는 `~/.claude/settings.json`에 직접 추가: 또는 `~/.claude/settings.json`에 직접 추가:
@ -367,7 +367,7 @@ Claude Code v2.1+는 설치된 플러그인의 `hooks/hooks.json`을 **자동으
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -375,7 +375,7 @@ Claude Code v2.1+는 설치된 플러그인의 `hooks/hooks.json`을 **자동으
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```
@ -489,8 +489,8 @@ rules/
| 하고 싶은 것 | 사용할 커맨드 | 사용되는 에이전트 | | 하고 싶은 것 | 사용할 커맨드 | 사용되는 에이전트 |
|-------------|-------------|-----------------| |-------------|-------------|-----------------|
| 새 기능 계획하기 | `/everything-claude-code:plan "인증 추가"` | planner | | 새 기능 계획하기 | `/ecc:plan "인증 추가"` | planner |
| 시스템 아키텍처 설계 | `/everything-claude-code:plan` + architect 에이전트 | architect | | 시스템 아키텍처 설계 | `/ecc:plan` + architect 에이전트 | architect |
| 테스트를 먼저 작성하며 코딩 | `/tdd` | tdd-guide | | 테스트를 먼저 작성하며 코딩 | `/tdd` | tdd-guide |
| 방금 작성한 코드 리뷰 | `/code-review` | code-reviewer | | 방금 작성한 코드 리뷰 | `/code-review` | code-reviewer |
| 빌드 실패 수정 | `/build-fix` | build-error-resolver | | 빌드 실패 수정 | `/build-fix` | build-error-resolver |
@ -507,7 +507,7 @@ rules/
**새로운 기능 시작:** **새로운 기능 시작:**
``` ```
/everything-claude-code:plan "OAuth를 사용한 사용자 인증 추가" /ecc:plan "OAuth를 사용한 사용자 인증 추가"
→ planner가 구현 청사진 작성 → planner가 구현 청사진 작성
/tdd → tdd-guide가 테스트 먼저 작성 강제 /tdd → tdd-guide가 테스트 먼저 작성 강제
/code-review → code-reviewer가 코드 검토 /code-review → code-reviewer가 코드 검토
@ -535,7 +535,7 @@ rules/
<summary><b>설치된 에이전트/커맨드 확인은 어떻게 하나요?</b></summary> <summary><b>설치된 에이전트/커맨드 확인은 어떻게 하나요?</b></summary>
```bash ```bash
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
플러그인에서 사용할 수 있는 모든 에이전트, 커맨드, 스킬을 보여줍니다. 플러그인에서 사용할 수 있는 모든 에이전트, 커맨드, 스킬을 보여줍니다.

View File

@ -115,7 +115,7 @@ Comece em menos de 2 minutos:
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Instalar plugin # Instalar plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### Passo 2: Instalar as Regras (Obrigatório) ### Passo 2: Instalar as Regras (Obrigatório)
@ -152,13 +152,13 @@ npx ecc-install typescript
```bash ```bash
# Experimente um comando (a instalação do plugin usa forma com namespace) # Experimente um comando (a instalação do plugin usa forma com namespace)
/everything-claude-code:plan "Adicionar autenticação de usuário" /ecc:plan "Adicionar autenticação de usuário"
# Instalação manual (Opção 2) usa a forma mais curta: # Instalação manual (Opção 2) usa a forma mais curta:
# /plan "Adicionar autenticação de usuário" # /plan "Adicionar autenticação de usuário"
# Verificar comandos disponíveis # Verificar comandos disponíveis
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**Pronto!** Você agora tem acesso a 28 agentes, 116 skills e 59 comandos. **Pronto!** Você agora tem acesso a 28 agentes, 116 skills e 59 comandos.
@ -304,7 +304,7 @@ claude --version
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Instalar o plugin # Instalar o plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
Ou adicione diretamente ao seu `~/.claude/settings.json`: Ou adicione diretamente ao seu `~/.claude/settings.json`:
@ -312,7 +312,7 @@ Ou adicione diretamente ao seu `~/.claude/settings.json`:
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -320,7 +320,7 @@ Ou adicione diretamente ao seu `~/.claude/settings.json`:
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```
@ -399,8 +399,8 @@ Regras são diretrizes sempre seguidas, organizadas em `common/` (agnóstico à
| Quero... | Use este comando | Agente usado | | Quero... | Use este comando | Agente usado |
|----------|-----------------|--------------| |----------|-----------------|--------------|
| Planejar um novo recurso | `/everything-claude-code:plan "Adicionar auth"` | planner | | Planejar um novo recurso | `/ecc:plan "Adicionar auth"` | planner |
| Projetar arquitetura de sistema | `/everything-claude-code:plan` + agente architect | architect | | Projetar arquitetura de sistema | `/ecc:plan` + agente architect | architect |
| Escrever código com testes primeiro | `/tdd` | tdd-guide | | Escrever código com testes primeiro | `/tdd` | tdd-guide |
| Revisar código que acabei de escrever | `/code-review` | code-reviewer | | Revisar código que acabei de escrever | `/code-review` | code-reviewer |
| Corrigir build com falha | `/build-fix` | build-error-resolver | | Corrigir build com falha | `/build-fix` | build-error-resolver |
@ -415,7 +415,7 @@ Regras são diretrizes sempre seguidas, organizadas em `common/` (agnóstico à
**Começando um novo recurso:** **Começando um novo recurso:**
``` ```
/everything-claude-code:plan "Adicionar autenticação de usuário com OAuth" /ecc:plan "Adicionar autenticação de usuário com OAuth"
→ planner cria blueprint de implementação → planner cria blueprint de implementação
/tdd → tdd-guide aplica escrita de testes primeiro /tdd → tdd-guide aplica escrita de testes primeiro
/code-review → code-reviewer verifica seu trabalho /code-review → code-reviewer verifica seu trabalho
@ -443,7 +443,7 @@ Regras são diretrizes sempre seguidas, organizadas em `common/` (agnóstico à
<summary><b>Como verificar quais agentes/comandos estão instalados?</b></summary> <summary><b>Como verificar quais agentes/comandos estão instalados?</b></summary>
```bash ```bash
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
</details> </details>

View File

@ -116,7 +116,7 @@ Bu repository yalnızca ham kodu içerir. Rehberler her şeyi açıklıyor.
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Plugin'i kur # Plugin'i kur
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### Adım 2: Rule'ları Kurun (Gerekli) ### Adım 2: Rule'ları Kurun (Gerekli)
@ -155,13 +155,13 @@ Manuel kurulum talimatları için `rules/` klasöründeki README'ye bakın.
```bash ```bash
# Bir command deneyin (plugin kurulumu namespace'li form kullanır) # Bir command deneyin (plugin kurulumu namespace'li form kullanır)
/everything-claude-code:plan "Kullanıcı kimlik doğrulaması ekle" /ecc:plan "Kullanıcı kimlik doğrulaması ekle"
# Manuel kurulum (Seçenek 2) daha kısa formu kullanır: # Manuel kurulum (Seçenek 2) daha kısa formu kullanır:
# /plan "Kullanıcı kimlik doğrulaması ekle" # /plan "Kullanıcı kimlik doğrulaması ekle"
# Mevcut command'ları kontrol edin # Mevcut command'ları kontrol edin
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**Bu kadar!** Artık 28 agent, 116 skill ve 59 command'a erişiminiz var. **Bu kadar!** Artık 28 agent, 116 skill ve 59 command'a erişiminiz var.
@ -299,8 +299,8 @@ Nereden başlayacağınızdan emin değil misiniz? Bu hızlı referansı kullan
| Yapmak istediğim... | Bu command'ı kullan | Kullanılan agent | | Yapmak istediğim... | Bu command'ı kullan | Kullanılan agent |
|---------------------|---------------------|------------------| |---------------------|---------------------|------------------|
| Yeni bir feature planla | `/everything-claude-code:plan "Auth ekle"` | planner | | Yeni bir feature planla | `/ecc:plan "Auth ekle"` | planner |
| Sistem mimarisi tasarla | `/everything-claude-code:plan` + architect agent | architect | | Sistem mimarisi tasarla | `/ecc:plan` + architect agent | architect |
| Önce testlerle kod yaz | `/tdd` | tdd-guide | | Önce testlerle kod yaz | `/tdd` | tdd-guide |
| Yazdığım kodu incele | `/code-review` | code-reviewer | | Yazdığım kodu incele | `/code-review` | code-reviewer |
| Başarısız bir build'i düzelt | `/build-fix` | build-error-resolver | | Başarısız bir build'i düzelt | `/build-fix` | build-error-resolver |
@ -315,7 +315,7 @@ Nereden başlayacağınızdan emin değil misiniz? Bu hızlı referansı kullan
**Yeni bir feature başlatma:** **Yeni bir feature başlatma:**
``` ```
/everything-claude-code:plan "OAuth ile kullanıcı kimlik doğrulaması ekle" /ecc:plan "OAuth ile kullanıcı kimlik doğrulaması ekle"
→ planner implementasyon planı oluşturur → planner implementasyon planı oluşturur
/tdd → tdd-guide önce-test-yaz'ı zorunlu kılar /tdd → tdd-guide önce-test-yaz'ı zorunlu kılar
/code-review → code-reviewer çalışmanızı kontrol eder /code-review → code-reviewer çalışmanızı kontrol eder
@ -343,7 +343,7 @@ Nereden başlayacağınızdan emin değil misiniz? Bu hızlı referansı kullan
<summary><b>Hangi agent/command'ların kurulu olduğunu nasıl kontrol ederim?</b></summary> <summary><b>Hangi agent/command'ların kurulu olduğunu nasıl kontrol ederim?</b></summary>
```bash ```bash
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
Bu, plugin'den mevcut tüm agent'ları, command'ları ve skill'leri gösterir. Bu, plugin'den mevcut tüm agent'ları, command'ları ve skill'leri gösterir.

View File

@ -370,7 +370,7 @@ chmod -R u+rwX,go+rX ~/.claude/homunculus
```bash ```bash
# Eklenti bağımlılıklarını kur # Eklenti bağımlılıklarını kur
cd ~/.claude/plugins/cache/everything-claude-code cd ~/.claude/plugins/cache/ecc
npm install npm install
# Veya manuel kurulum için # Veya manuel kurulum için

View File

@ -161,7 +161,7 @@
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install plugin # Install plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### 步骤 2安装规则必需 ### 步骤 2安装规则必需
@ -200,13 +200,13 @@ npx ecc-install typescript
```bash ```bash
# Try a command (plugin install uses namespaced form) # Try a command (plugin install uses namespaced form)
/everything-claude-code:plan "Add user authentication" /ecc:plan "Add user authentication"
# Manual install (Option 2) uses the shorter form: # Manual install (Option 2) uses the shorter form:
# /plan "Add user authentication" # /plan "Add user authentication"
# Check available commands # Check available commands
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**搞定!** 你现在可以使用 38 个智能体、159 项技能和 72 个命令了。 **搞定!** 你现在可以使用 38 个智能体、159 项技能和 72 个命令了。
@ -585,7 +585,7 @@ Claude Code v2.1+ **会自动加载** 任何已安装插件中的 `hooks/hooks.j
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# Install the plugin # Install the plugin
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
或者直接添加到您的 `~/.claude/settings.json` 或者直接添加到您的 `~/.claude/settings.json`
@ -593,7 +593,7 @@ Claude Code v2.1+ **会自动加载** 任何已安装插件中的 `hooks/hooks.j
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -601,7 +601,7 @@ Claude Code v2.1+ **会自动加载** 任何已安装插件中的 `hooks/hooks.j
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```
@ -744,8 +744,8 @@ rules/
| 我想要... | 使用此命令 | 使用的智能体 | | 我想要... | 使用此命令 | 使用的智能体 |
|--------------|-----------------|------------| |--------------|-----------------|------------|
| 规划新功能 | `/everything-claude-code:plan "Add auth"` | planner | | 规划新功能 | `/ecc:plan "Add auth"` | planner |
| 设计系统架构 | `/everything-claude-code:plan` + architect agent | architect | | 设计系统架构 | `/ecc:plan` + architect agent | architect |
| 先写测试再写代码 | `/tdd` | tdd-guide | | 先写测试再写代码 | `/tdd` | tdd-guide |
| 评审我刚写的代码 | `/code-review` | code-reviewer | | 评审我刚写的代码 | `/code-review` | code-reviewer |
| 修复失败的构建 | `/build-fix` | build-error-resolver | | 修复失败的构建 | `/build-fix` | build-error-resolver |
@ -763,7 +763,7 @@ rules/
**开始新功能:** **开始新功能:**
``` ```
/everything-claude-code:plan "使用 OAuth 添加用户身份验证" /ecc:plan "使用 OAuth 添加用户身份验证"
→ 规划器创建实现蓝图 → 规划器创建实现蓝图
/tdd → tdd-guide 强制执行先写测试 /tdd → tdd-guide 强制执行先写测试
/code-review → 代码审查员检查你的工作 /code-review → 代码审查员检查你的工作
@ -793,7 +793,7 @@ rules/
<summary><b>如何检查已安装的代理/命令?</b></summary> <summary><b>如何检查已安装的代理/命令?</b></summary>
```bash ```bash
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
这会显示插件中所有可用的代理、命令和技能。 这会显示插件中所有可用的代理、命令和技能。

View File

@ -394,7 +394,7 @@ chmod -R u+rwX,go+rX ~/.claude/homunculus
```bash ```bash
# Install plugin dependencies # Install plugin dependencies
cd ~/.claude/plugins/cache/everything-claude-code cd ~/.claude/plugins/cache/ecc
npm install npm install
# Or for manual install # Or for manual install

View File

@ -19,7 +19,7 @@ origin: ECC
此技能必须在激活前对 Claude Code 可访问。有两种引导方式: 此技能必须在激活前对 Claude Code 可访问。有两种引导方式:
1. **通过插件**: `/plugin install everything-claude-code` — 插件会自动加载此技能 1. **通过插件**: `/plugin install ecc@ecc` — 插件会自动加载此技能
2. **手动**: 仅将此技能复制到 `~/.claude/skills/configure-ecc/SKILL.md`,然后通过说 "configure ecc" 激活 2. **手动**: 仅将此技能复制到 `~/.claude/skills/configure-ecc/SKILL.md`,然后通过说 "configure ecc" 激活
*** ***

View File

@ -70,7 +70,7 @@
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# 安裝外掛程式 # 安裝外掛程式
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
### 第二步:安裝規則(必需) ### 第二步:安裝規則(必需)
@ -89,13 +89,13 @@ cp -r everything-claude-code/rules/* ~/.claude/rules/
```bash ```bash
# 嘗試一個指令(外掛安裝使用命名空間形式) # 嘗試一個指令(外掛安裝使用命名空間形式)
/everything-claude-code:plan "新增使用者認證" /ecc:plan "新增使用者認證"
# 手動安裝選項2使用簡短形式 # 手動安裝選項2使用簡短形式
# /plan "新增使用者認證" # /plan "新增使用者認證"
# 查看可用指令 # 查看可用指令
/plugin list everything-claude-code@everything-claude-code /plugin list ecc@ecc
``` ```
**完成!** 您現在使用 15+ 代理程式、30+ 技能和 20+ 指令。 **完成!** 您現在使用 15+ 代理程式、30+ 技能和 20+ 指令。
@ -270,7 +270,7 @@ everything-claude-code/
/plugin marketplace add https://github.com/affaan-m/everything-claude-code /plugin marketplace add https://github.com/affaan-m/everything-claude-code
# 安裝外掛程式 # 安裝外掛程式
/plugin install everything-claude-code@everything-claude-code /plugin install ecc@ecc
``` ```
或直接新增到您的 `~/.claude/settings.json` 或直接新增到您的 `~/.claude/settings.json`
@ -278,7 +278,7 @@ everything-claude-code/
```json ```json
{ {
"extraKnownMarketplaces": { "extraKnownMarketplaces": {
"everything-claude-code": { "ecc": {
"source": { "source": {
"source": "github", "source": "github",
"repo": "affaan-m/everything-claude-code" "repo": "affaan-m/everything-claude-code"
@ -286,7 +286,7 @@ everything-claude-code/
} }
}, },
"enabledPlugins": { "enabledPlugins": {
"everything-claude-code@everything-claude-code": true "ecc@ecc": true
} }
} }
``` ```

View File

@ -305,7 +305,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:format-typecheck','scripts/hooks/stop-format-typecheck.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:300000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:format-typecheck','scripts/hooks/stop-format-typecheck.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:300000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"timeout": 300 "timeout": 300
} }
], ],
@ -317,7 +317,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:check-console-log','scripts/hooks/check-console-log.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"" "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:check-console-log','scripts/hooks/check-console-log.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\""
} }
], ],
"description": "Check for console.log in modified files after each response", "description": "Check for console.log in modified files after each response",
@ -328,7 +328,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:session-end','scripts/hooks/session-end.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:session-end','scripts/hooks/session-end.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"async": true, "async": true,
"timeout": 10 "timeout": 10
} }
@ -341,7 +341,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:evaluate-session','scripts/hooks/evaluate-session.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:evaluate-session','scripts/hooks/evaluate-session.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"async": true, "async": true,
"timeout": 10 "timeout": 10
} }
@ -354,7 +354,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:cost-tracker','scripts/hooks/cost-tracker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:cost-tracker','scripts/hooks/cost-tracker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"async": true, "async": true,
"timeout": 10 "timeout": 10
} }
@ -367,7 +367,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:desktop-notify','scripts/hooks/desktop-notify.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:desktop-notify','scripts/hooks/desktop-notify.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"async": true, "async": true,
"timeout": 10 "timeout": 10
} }
@ -382,7 +382,7 @@
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
"command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{const cacheBase=path.join(claudeDir,'plugins','cache','everything-claude-code');for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'session:end:marker','scripts/hooks/session-end-marker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[SessionEnd] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[SessionEnd] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"", "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'session:end:marker','scripts/hooks/session-end-marker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[SessionEnd] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[SessionEnd] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
"async": true, "async": true,
"timeout": 10 "timeout": 10
} }

View File

@ -188,12 +188,22 @@ function detectTargetMode(rootDir) {
function findPluginInstall(rootDir) { function findPluginInstall(rootDir) {
const homeDir = process.env.HOME || ''; const homeDir = process.env.HOME || '';
const candidates = [ const pluginDirs = [
path.join(rootDir, '.claude', 'plugins', 'everything-claude-code', '.claude-plugin', 'plugin.json'), 'ecc',
path.join(rootDir, '.claude', 'plugins', 'everything-claude-code', 'plugin.json'), 'ecc@ecc',
homeDir && path.join(homeDir, '.claude', 'plugins', 'everything-claude-code', '.claude-plugin', 'plugin.json'), 'everything-claude-code',
homeDir && path.join(homeDir, '.claude', 'plugins', 'everything-claude-code', 'plugin.json'), 'everything-claude-code@everything-claude-code',
];
const candidateRoots = [
path.join(rootDir, '.claude', 'plugins'),
homeDir && path.join(homeDir, '.claude', 'plugins'),
].filter(Boolean); ].filter(Boolean);
const candidates = candidateRoots.flatMap((pluginsDir) =>
pluginDirs.flatMap((pluginDir) => [
path.join(pluginsDir, pluginDir, '.claude-plugin', 'plugin.json'),
path.join(pluginsDir, pluginDir, 'plugin.json'),
])
);
return candidates.find(candidate => fs.existsSync(candidate)) || null; return candidates.find(candidate => fs.existsSync(candidate)) || null;
} }
@ -480,7 +490,7 @@ function getConsumerChecks(rootDir) {
category: 'Tool Coverage', category: 'Tool Coverage',
points: 4, points: 4,
scopes: ['repo'], scopes: ['repo'],
path: '~/.claude/plugins/everything-claude-code/', path: '~/.claude/plugins/ecc/ (legacy everything-claude-code paths also supported)',
description: 'Everything Claude Code is installed for the active user or project', description: 'Everything Claude Code is installed for the active user or project',
pass: Boolean(pluginInstall), pass: Boolean(pluginInstall),
fix: 'Install the ECC plugin for this user or project before auditing project-specific harness quality.', fix: 'Install the ECC plugin for this user or project before auditing project-specific harness quality.',

View File

@ -30,6 +30,18 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const { spawnSync } = require('child_process'); const { spawnSync } = require('child_process');
const CURRENT_PLUGIN_SLUG = 'ecc';
const LEGACY_PLUGIN_SLUG = 'everything-claude-code';
const KNOWN_PLUGIN_PATHS = [
[CURRENT_PLUGIN_SLUG],
[`${CURRENT_PLUGIN_SLUG}@${CURRENT_PLUGIN_SLUG}`],
['marketplace', CURRENT_PLUGIN_SLUG],
[LEGACY_PLUGIN_SLUG],
[`${LEGACY_PLUGIN_SLUG}@${LEGACY_PLUGIN_SLUG}`],
['marketplace', LEGACY_PLUGIN_SLUG],
];
const CACHE_PLUGIN_SLUGS = [CURRENT_PLUGIN_SLUG, LEGACY_PLUGIN_SLUG];
// Read the raw JSON event from stdin // Read the raw JSON event from stdin
const raw = fs.readFileSync(0, 'utf8'); const raw = fs.readFileSync(0, 'utf8');
@ -52,8 +64,8 @@ function hasRunnerRoot(candidate) {
* Resolves the ECC plugin root using the following priority order: * Resolves the ECC plugin root using the following priority order:
* 1. CLAUDE_PLUGIN_ROOT environment variable * 1. CLAUDE_PLUGIN_ROOT environment variable
* 2. ~/.claude (direct install) * 2. ~/.claude (direct install)
* 3. Several well-known plugin sub-paths under ~/.claude/plugins/ * 3. Several well-known plugin sub-paths under ~/.claude/plugins/ (current + legacy)
* 4. Versioned cache directories under ~/.claude/plugins/cache/everything-claude-code/ * 4. Versioned cache directories under ~/.claude/plugins/cache/{ecc,everything-claude-code}/
* 5. Falls back to ~/.claude if nothing else matches * 5. Falls back to ~/.claude if nothing else matches
* *
* @returns {string} * @returns {string}
@ -71,11 +83,9 @@ function resolvePluginRoot() {
return claudeDir; return claudeDir;
} }
const knownPaths = [ const knownPaths = KNOWN_PLUGIN_PATHS.map((segments) =>
path.join(claudeDir, 'plugins', 'everything-claude-code'), path.join(claudeDir, 'plugins', ...segments)
path.join(claudeDir, 'plugins', 'everything-claude-code@everything-claude-code'), );
path.join(claudeDir, 'plugins', 'marketplace', 'everything-claude-code'),
];
for (const candidate of knownPaths) { for (const candidate of knownPaths) {
if (hasRunnerRoot(candidate)) { if (hasRunnerRoot(candidate)) {
@ -83,16 +93,18 @@ function resolvePluginRoot() {
} }
} }
// Walk versioned cache: ~/.claude/plugins/cache/everything-claude-code/<org>/<version>/ // Walk versioned cache: ~/.claude/plugins/cache/{ecc,everything-claude-code}/<org>/<version>/
try { try {
const cacheBase = path.join(claudeDir, 'plugins', 'cache', 'everything-claude-code'); for (const slug of CACHE_PLUGIN_SLUGS) {
for (const org of fs.readdirSync(cacheBase, { withFileTypes: true })) { const cacheBase = path.join(claudeDir, 'plugins', 'cache', slug);
if (!org.isDirectory()) continue; for (const org of fs.readdirSync(cacheBase, { withFileTypes: true })) {
for (const version of fs.readdirSync(path.join(cacheBase, org.name), { withFileTypes: true })) { if (!org.isDirectory()) continue;
if (!version.isDirectory()) continue; for (const version of fs.readdirSync(path.join(cacheBase, org.name), { withFileTypes: true })) {
const candidate = path.join(cacheBase, org.name, version.name); if (!version.isDirectory()) continue;
if (hasRunnerRoot(candidate)) { const candidate = path.join(cacheBase, org.name, version.name);
return candidate; if (hasRunnerRoot(candidate)) {
return candidate;
}
} }
} }
} }

View File

@ -4,14 +4,28 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const os = require('os'); const os = require('os');
const CURRENT_PLUGIN_SLUG = 'ecc';
const LEGACY_PLUGIN_SLUG = 'everything-claude-code';
const CURRENT_PLUGIN_HANDLE = `${CURRENT_PLUGIN_SLUG}@${CURRENT_PLUGIN_SLUG}`;
const LEGACY_PLUGIN_HANDLE = `${LEGACY_PLUGIN_SLUG}@${LEGACY_PLUGIN_SLUG}`;
const PLUGIN_CACHE_SLUGS = [CURRENT_PLUGIN_SLUG, LEGACY_PLUGIN_SLUG];
const PLUGIN_ROOT_SEGMENTS = [
[CURRENT_PLUGIN_SLUG],
[CURRENT_PLUGIN_HANDLE],
['marketplace', CURRENT_PLUGIN_SLUG],
[LEGACY_PLUGIN_SLUG],
[LEGACY_PLUGIN_HANDLE],
['marketplace', LEGACY_PLUGIN_SLUG],
];
/** /**
* Resolve the ECC source root directory. * Resolve the ECC source root directory.
* *
* Tries, in order: * Tries, in order:
* 1. CLAUDE_PLUGIN_ROOT env var (set by Claude Code for hooks, or by user) * 1. CLAUDE_PLUGIN_ROOT env var (set by Claude Code for hooks, or by user)
* 2. Standard install location (~/.claude/) when scripts exist there * 2. Standard install location (~/.claude/) when scripts exist there
* 3. Exact legacy plugin roots under ~/.claude/plugins/ * 3. Known plugin roots under ~/.claude/plugins/ (current + legacy slugs)
* 4. Plugin cache auto-detection scans ~/.claude/plugins/cache/everything-claude-code/ * 4. Plugin cache auto-detection scans ~/.claude/plugins/cache/{ecc,everything-claude-code}/
* 5. Fallback to ~/.claude/ (original behaviour) * 5. Fallback to ~/.claude/ (original behaviour)
* *
* @param {object} [options] * @param {object} [options]
@ -41,11 +55,9 @@ function resolveEccRoot(options = {}) {
// Exact legacy plugin install locations. These preserve backwards // Exact legacy plugin install locations. These preserve backwards
// compatibility without scanning arbitrary plugin trees. // compatibility without scanning arbitrary plugin trees.
const legacyPluginRoots = [ const legacyPluginRoots = PLUGIN_ROOT_SEGMENTS.map((segments) =>
path.join(claudeDir, 'plugins', 'everything-claude-code'), path.join(claudeDir, 'plugins', ...segments)
path.join(claudeDir, 'plugins', 'everything-claude-code@everything-claude-code'), );
path.join(claudeDir, 'plugins', 'marketplace', 'everything-claude-code')
];
for (const candidate of legacyPluginRoots) { for (const candidate of legacyPluginRoots) {
if (fs.existsSync(path.join(candidate, probe))) { if (fs.existsSync(path.join(candidate, probe))) {
@ -56,25 +68,27 @@ function resolveEccRoot(options = {}) {
// Plugin cache — Claude Code stores marketplace plugins under // Plugin cache — Claude Code stores marketplace plugins under
// ~/.claude/plugins/cache/<plugin-name>/<org>/<version>/ // ~/.claude/plugins/cache/<plugin-name>/<org>/<version>/
try { try {
const cacheBase = path.join(claudeDir, 'plugins', 'cache', 'everything-claude-code'); for (const slug of PLUGIN_CACHE_SLUGS) {
const orgDirs = fs.readdirSync(cacheBase, { withFileTypes: true }); const cacheBase = path.join(claudeDir, 'plugins', 'cache', slug);
const orgDirs = fs.readdirSync(cacheBase, { withFileTypes: true });
for (const orgEntry of orgDirs) { for (const orgEntry of orgDirs) {
if (!orgEntry.isDirectory()) continue; if (!orgEntry.isDirectory()) continue;
const orgPath = path.join(cacheBase, orgEntry.name); const orgPath = path.join(cacheBase, orgEntry.name);
let versionDirs; let versionDirs;
try { try {
versionDirs = fs.readdirSync(orgPath, { withFileTypes: true }); versionDirs = fs.readdirSync(orgPath, { withFileTypes: true });
} catch { } catch {
continue; continue;
} }
for (const verEntry of versionDirs) { for (const verEntry of versionDirs) {
if (!verEntry.isDirectory()) continue; if (!verEntry.isDirectory()) continue;
const candidate = path.join(orgPath, verEntry.name); const candidate = path.join(orgPath, verEntry.name);
if (fs.existsSync(path.join(candidate, probe))) { if (fs.existsSync(path.join(candidate, probe))) {
return candidate; return candidate;
}
} }
} }
} }
@ -96,7 +110,7 @@ function resolveEccRoot(options = {}) {
* const _r = <paste INLINE_RESOLVE>; * const _r = <paste INLINE_RESOLVE>;
* const sm = require(_r + '/scripts/lib/session-manager'); * const sm = require(_r + '/scripts/lib/session-manager');
*/ */
const INLINE_RESOLVE = `(()=>{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 l of [p.join(d,'plugins','everything-claude-code'),p.join(d,'plugins','everything-claude-code@everything-claude-code'),p.join(d,'plugins','marketplace','everything-claude-code')])if(f.existsSync(p.join(l,q)))return l;try{var b=p.join(d,'plugins','cache','everything-claude-code');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 INLINE_RESOLVE = `(()=>{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 ${JSON.stringify(PLUGIN_ROOT_SEGMENTS)}){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of ${JSON.stringify(PLUGIN_CACHE_SLUGS)}){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})()`;
module.exports = { module.exports = {
resolveEccRoot, resolveEccRoot,

View File

@ -18,7 +18,7 @@ An interactive, step-by-step installation wizard for the Everything Claude Code
## Prerequisites ## Prerequisites
This skill must be accessible to Claude Code before activation. Two ways to bootstrap: This skill must be accessible to Claude Code before activation. Two ways to bootstrap:
1. **Via Plugin**: `/plugin install everything-claude-code` — the plugin loads this skill automatically 1. **Via Plugin**: `/plugin install ecc@ecc` — the plugin loads this skill automatically
2. **Manual**: Copy only this skill to `~/.claude/skills/configure-ecc/SKILL.md`, then activate by saying "configure ecc" 2. **Manual**: Copy only this skill to `~/.claude/skills/configure-ecc/SKILL.md`, then activate by saying "configure ecc"
--- ---

View File

@ -47,10 +47,10 @@ function setupLegacyPluginInstall(homeDir, segments) {
fs.writeFileSync(path.join(scriptDir, 'utils.js'), '// stub'); fs.writeFileSync(path.join(scriptDir, 'utils.js'), '// stub');
return legacyDir; return legacyDir;
} }
function setupPluginCache(homeDir, orgName, version) { function setupPluginCache(homeDir, pluginSlug, orgName, version) {
const cacheDir = path.join( const cacheDir = path.join(
homeDir, '.claude', 'plugins', 'cache', homeDir, '.claude', 'plugins', 'cache',
'everything-claude-code', orgName, version pluginSlug, orgName, version
); );
const scriptDir = path.join(cacheDir, 'scripts', 'lib'); const scriptDir = path.join(cacheDir, 'scripts', 'lib');
fs.mkdirSync(scriptDir, { recursive: true }); fs.mkdirSync(scriptDir, { recursive: true });
@ -111,6 +111,28 @@ function runTests() {
} }
})) passed++; else failed++; })) passed++; else failed++;
if (test('finds current plugin install at ~/.claude/plugins/ecc', () => {
const homeDir = createTempDir();
try {
const expected = setupLegacyPluginInstall(homeDir, ['ecc']);
const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, expected);
} finally {
fs.rmSync(homeDir, { recursive: true, force: true });
}
})) passed++; else failed++;
if (test('finds current plugin install at ~/.claude/plugins/ecc@ecc', () => {
const homeDir = createTempDir();
try {
const expected = setupLegacyPluginInstall(homeDir, ['ecc@ecc']);
const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, expected);
} finally {
fs.rmSync(homeDir, { recursive: true, force: true });
}
})) passed++; else failed++;
if (test('finds exact legacy plugin install at ~/.claude/plugins/everything-claude-code', () => { if (test('finds exact legacy plugin install at ~/.claude/plugins/everything-claude-code', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
@ -133,6 +155,17 @@ function runTests() {
} }
})) passed++; else failed++; })) passed++; else failed++;
if (test('finds marketplace current plugin install at ~/.claude/plugins/marketplace/ecc', () => {
const homeDir = createTempDir();
try {
const expected = setupLegacyPluginInstall(homeDir, ['marketplace', 'ecc']);
const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, expected);
} finally {
fs.rmSync(homeDir, { recursive: true, force: true });
}
})) passed++; else failed++;
if (test('finds marketplace legacy plugin install at ~/.claude/plugins/marketplace/everything-claude-code', () => { if (test('finds marketplace legacy plugin install at ~/.claude/plugins/marketplace/everything-claude-code', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
@ -147,8 +180,8 @@ function runTests() {
if (test('prefers exact legacy plugin install over plugin cache', () => { if (test('prefers exact legacy plugin install over plugin cache', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
const expected = setupLegacyPluginInstall(homeDir, ['marketplace', 'everything-claude-code']); const expected = setupLegacyPluginInstall(homeDir, ['marketplace', 'ecc']);
setupPluginCache(homeDir, 'everything-claude-code', '1.8.0'); setupPluginCache(homeDir, 'ecc', 'affaan-m', '1.10.0');
const result = resolveEccRoot({ envRoot: '', homeDir }); const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, expected); assert.strictEqual(result, expected);
} finally { } finally {
@ -160,7 +193,7 @@ function runTests() {
if (test('discovers plugin root from cache directory', () => { if (test('discovers plugin root from cache directory', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
const expected = setupPluginCache(homeDir, 'everything-claude-code', '1.8.0'); const expected = setupPluginCache(homeDir, 'ecc', 'affaan-m', '1.10.0');
const result = resolveEccRoot({ envRoot: '', homeDir }); const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, expected); assert.strictEqual(result, expected);
} finally { } finally {
@ -172,7 +205,7 @@ function runTests() {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
const claudeDir = setupStandardInstall(homeDir); const claudeDir = setupStandardInstall(homeDir);
setupPluginCache(homeDir, 'everything-claude-code', '1.8.0'); setupPluginCache(homeDir, 'ecc', 'affaan-m', '1.10.0');
const result = resolveEccRoot({ envRoot: '', homeDir }); const result = resolveEccRoot({ envRoot: '', homeDir });
assert.strictEqual(result, claudeDir, assert.strictEqual(result, claudeDir,
'Standard install should take precedence over plugin cache'); 'Standard install should take precedence over plugin cache');
@ -184,13 +217,13 @@ function runTests() {
if (test('handles multiple versions in plugin cache', () => { if (test('handles multiple versions in plugin cache', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
setupPluginCache(homeDir, 'everything-claude-code', '1.7.0'); setupPluginCache(homeDir, 'everything-claude-code', 'legacy-org', '1.7.0');
const expected = setupPluginCache(homeDir, 'everything-claude-code', '1.8.0'); const expected = setupPluginCache(homeDir, 'ecc', 'affaan-m', '1.10.0');
const result = resolveEccRoot({ envRoot: '', homeDir }); const result = resolveEccRoot({ envRoot: '', homeDir });
// Should find one of them (either is valid) // Should find one of them (either is valid)
assert.ok( assert.ok(
result === expected || result === expected ||
result === path.join(homeDir, '.claude', 'plugins', 'cache', 'everything-claude-code', 'everything-claude-code', '1.7.0'), result === path.join(homeDir, '.claude', 'plugins', 'cache', 'everything-claude-code', 'legacy-org', '1.7.0'),
'Should resolve to a valid plugin cache directory' 'Should resolve to a valid plugin cache directory'
); );
} finally { } finally {
@ -262,7 +295,7 @@ function runTests() {
if (test('INLINE_RESOLVE discovers exact legacy plugin root when env var is unset', () => { if (test('INLINE_RESOLVE discovers exact legacy plugin root when env var is unset', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
const expected = setupLegacyPluginInstall(homeDir, ['marketplace', 'everything-claude-code']); const expected = setupLegacyPluginInstall(homeDir, ['marketplace', 'ecc']);
const { execFileSync } = require('child_process'); const { execFileSync } = require('child_process');
const result = execFileSync('node', [ const result = execFileSync('node', [
'-e', `console.log(${INLINE_RESOLVE})`, '-e', `console.log(${INLINE_RESOLVE})`,
@ -278,7 +311,7 @@ function runTests() {
if (test('INLINE_RESOLVE discovers plugin cache when env var is unset', () => { if (test('INLINE_RESOLVE discovers plugin cache when env var is unset', () => {
const homeDir = createTempDir(); const homeDir = createTempDir();
try { try {
const expected = setupPluginCache(homeDir, 'everything-claude-code', '1.10.0'); const expected = setupPluginCache(homeDir, 'ecc', 'affaan-m', '1.10.0');
const { execFileSync } = require('child_process'); const { execFileSync } = require('child_process');
const result = execFileSync('node', [ const result = execFileSync('node', [
'-e', `console.log(${INLINE_RESOLVE})`, '-e', `console.log(${INLINE_RESOLVE})`,

View File

@ -79,6 +79,10 @@ test('claude plugin.json has version field', () => {
assert.ok(claudePlugin.version, 'Expected version field'); assert.ok(claudePlugin.version, 'Expected version field');
}); });
test('claude plugin.json uses short plugin slug', () => {
assert.strictEqual(claudePlugin.name, 'ecc');
});
test('claude plugin.json agents is an array', () => { test('claude plugin.json agents is an array', () => {
assert.ok(Array.isArray(claudePlugin.agents), 'Expected agents to be an array (not a string/directory)'); assert.ok(Array.isArray(claudePlugin.agents), 'Expected agents to be an array (not a string/directory)');
}); });
@ -146,6 +150,10 @@ test('codex plugin.json has name field', () => {
assert.ok(codexPlugin.name, 'Expected name field'); assert.ok(codexPlugin.name, 'Expected name field');
}); });
test('codex plugin.json uses short plugin slug', () => {
assert.strictEqual(codexPlugin.name, 'ecc');
});
test('codex plugin.json has version field', () => { test('codex plugin.json has version field', () => {
assert.ok(codexPlugin.version, 'Expected version field'); assert.ok(codexPlugin.version, 'Expected version field');
}); });
@ -240,6 +248,10 @@ test('marketplace.json has name field', () => {
assert.ok(marketplace.name, 'Expected name field'); assert.ok(marketplace.name, 'Expected name field');
}); });
test('marketplace.json uses short marketplace slug', () => {
assert.strictEqual(marketplace.name, 'ecc');
});
test('marketplace.json has plugins array with at least one entry', () => { test('marketplace.json has plugins array with at least one entry', () => {
assert.ok(Array.isArray(marketplace.plugins) && marketplace.plugins.length > 0, 'Expected plugins array'); assert.ok(Array.isArray(marketplace.plugins) && marketplace.plugins.length > 0, 'Expected plugins array');
}); });
@ -253,6 +265,10 @@ test('marketplace.json plugin entries have required fields', () => {
} }
}); });
test('marketplace.json plugin entry uses short plugin slug', () => {
assert.strictEqual(marketplace.plugins[0].name, 'ecc');
});
test('marketplace local plugin path resolves to the repo-root Codex bundle', () => { test('marketplace local plugin path resolves to the repo-root Codex bundle', () => {
for (const plugin of marketplace.plugins) { for (const plugin of marketplace.plugins) {
if (!plugin.source || plugin.source.source !== 'local') { if (!plugin.source || plugin.source.source !== 'local') {

View File

@ -99,10 +99,10 @@ function runTests() {
const projectRoot = createTempDir('harness-audit-project-'); const projectRoot = createTempDir('harness-audit-project-');
try { try {
fs.mkdirSync(path.join(homeDir, '.claude', 'plugins', 'everything-claude-code', '.claude-plugin'), { recursive: true }); fs.mkdirSync(path.join(homeDir, '.claude', 'plugins', 'ecc', '.claude-plugin'), { recursive: true });
fs.writeFileSync( fs.writeFileSync(
path.join(homeDir, '.claude', 'plugins', 'everything-claude-code', '.claude-plugin', 'plugin.json'), path.join(homeDir, '.claude', 'plugins', 'ecc', '.claude-plugin', 'plugin.json'),
JSON.stringify({ name: 'everything-claude-code' }, null, 2) JSON.stringify({ name: 'ecc' }, null, 2)
); );
fs.mkdirSync(path.join(projectRoot, '.github', 'workflows'), { recursive: true }); fs.mkdirSync(path.join(projectRoot, '.github', 'workflows'), { recursive: true });