ccc-ecc · diff

git:20260801.0de5ac7 to git:20261013.fbe187d

78 added, 95 removed. Audit A to A.

---
name: ccc-ecc
- description: "Selective ECC loader: pick one Everything Claude Code skill, agent, or hook and link/copy it into ~/.claude without installing the full ECC harness."
+ description: "Selective ECC loader: pick one Everything Claude Code skill, agent or hook from the vendored checkout and symlink or copy only that component into ~/.claude, with a backup, never the full harness. Use when the user wants a single ECC component without installing ECC."
allowed-tools:
- Read
- Bash
- AskUserQuestion
+ argument-hint: "[skill | agent | hook | list]"
+ model: sonnet
+ effort: medium
+ disable-model-invocation: true
---
- # /ccc-ecc — Selective ECC Loader
-
- Load one specific **Everything Claude Code (ECC)** component into `~/.claude/` without copying the whole ECC harness.
-
- ECC source lives at `vendor/everything-claude-code/`. This is a click-first picker: choose a skill, agent, or hook; then symlink or copy only that component.
-
- ## Safety model
+ # /ccc-ecc — one ECC component, nothing else
- - Prefer **symlink** so updates follow the pinned ECC vendor checkout.
- - Offer **copy** for an editable local snapshot.
- - Back up before replacing anything under `~/.claude/`.
- - Never install ECC settings, commands, or the full harness.
+ **CC Commander** · /ccc-ecc · installs a single Everything Claude Code (ECC) skill, agent or hook into `~/.claude/` from the pinned vendor checkout.
- ## Steps
+ ## When to use / when not to
- ### 1. Locate ECC
+ - Use when the user wants one ECC skill, agent or hook (for example a reviewer agent or a single hook script) without ECC's installer, settings, commands or rules.
+ - Do not use to install or update the whole ECC harness, to change `settings.json`, or to edit ECC itself. For refreshing vendor checkouts use `/ccc-upgrade`.
- ```bash
- git rev-parse --show-toplevel
- test -d vendor/everything-claude-code && echo ok || echo missing
- ```
+ ECC is vendored as a git submodule at `vendor/everything-claude-code/` (upstream `affaan-m/everything-claude-code`). Its components live in `skills/<name>/SKILL.md`, `agents/<name>.md` and `scripts/hooks/<name>.js` (hook wiring is declared in its `hooks/hooks.json`).
- If missing, stop with:
+ ## What happens
- > ECC vendor checkout not found at `vendor/everything-claude-code/`. Run `/ccc-upgrade` or initialize submodules first.
+ 1. **Locate ECC.** From a CC Commander checkout:
- ### 2. Ask what to do
+ ```bash
+ ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
+ for c in "$ROOT/vendor/everything-claude-code" "${CLAUDE_PLUGIN_ROOT}/../../vendor/everything-claude-code"; do
+ [ -d "$c/skills" ] && { ECC="$(cd "$c" && pwd)"; break; }
+ done
+ echo "${ECC:-missing}"
+ ```
- ```
- question: "What ECC component do you want to load?"
- header: "ECC"
- multiSelect: false
- options:
- - label: "Load a skill"
- - label: "Load an agent"
- - label: "Load a hook"
- - label: "List available ECC components"
- ```
+ If it prints `missing`, stop: "ECC vendor checkout not found at `vendor/everything-claude-code/`. Run `git submodule update --init vendor/everything-claude-code` in a CC Commander checkout, or `/ccc-upgrade`." Plugin installs from a marketplace do not carry `vendor/`, so this skill needs a repo checkout.
- ### 3. Inventory candidates
+ 2. **Ask the component type** with the type picker (an argument of `skill`, `agent`, `hook` or `list` skips it).
- ```bash
- ECC="vendor/everything-claude-code"
- find "$ECC" \( -path '*/node_modules/*' -o -path '*/.git/*' -o -path '*/dist/*' -o -path '*/build/*' \) -prune -o \
- \( -path '*/skills/*/SKILL.md' -o -path '*/agents/*.md' -o -path '*/hooks/*.js' -o -path '*/hooks/*.sh' \) -print
- ```
+ 3. **Inventory candidates.**
- Classify `skills/<name>/SKILL.md` as skills, `agents/*.md` as agents, and `hooks/*.{js,sh}` as hooks. If the user chose "List available", render grouped markdown tables and stop.
+ ```bash
+ find "$ECC" \( -path '*/node_modules' -o -path '*/.git' -o -path '*/dist' -o -path '*/build' \) -prune -o \
+ \( -path "$ECC/skills/*/SKILL.md" -o -path "$ECC/agents/*.md" -o -path "$ECC/scripts/hooks/*.js" -o -path "$ECC/scripts/hooks/*.sh" \) -print
+ ```
- ### 4. Ask which component — two-level AUQ cascade, never a typed-name table
+ Classify `skills/<name>/SKILL.md` as skills, `agents/*.md` as agents, `scripts/hooks/*.{js,sh}` as hooks. Read counts from this output; never quote a remembered count. For "List available ECC components", render grouped markdown tables (name, relative path) and stop.
- ECC ships 156+ skills — never dump them into one picker (max 4 options) and never fall back to "type the exact name" as a first resort; that reintroduces the numbered-list anti-pattern this plugin exists to avoid.
+ 4. **Pick one component with a cascade, never a typed-name table.** A picker holds at most four options.
+ - **Level 1, category.** When more than four candidates match: if they group by directory prefix, offer up to three buckets plus "More categories…"; otherwise split alphabetically into about four buckets of `ceil(N/4)` computed from the real names. Never hardcode letter ranges such as "A–F"; they skew on real names. Each option's description is "<N> components".
+ - **Level 2, component.** Four or fewer left: offer them directly (label = component name, description = path relative to the ECC root). Still more than four: repeat Level 1 on that subset.
+ - **Typed filter, last resort only.** If two cascades still leave a bucket with more than 16 candidates, ask for a substring, then present the matches as a picker (cascading again if needed). Never ask for an exact name or path as the first move.
- **Level 1 — category.** If the matched candidates (skills, agents, or hooks) number more than 4:
- - If they group meaningfully by directory prefix (e.g. `skills/testing/*`, `skills/security/*`), present up to 3 category buckets + "More categories…" as an `AskUserQuestion` (≤4 options).
- - Otherwise (a flat namespace), bucket alphabetically into roughly-equal groups computed from the actual candidate count (e.g. ~4 buckets sized `ceil(N/4)` each) and present those buckets as the picker — do not hardcode fixed letter ranges like "A-F"; they skew badly on a real name distribution.
+ 5. **Ask symlink or copy** with the mode picker.
+ - Hooks that load sibling modules must be symlinked: check with `grep -lE "require\(['\"]\.\./|from ['\"]\.\./" "$SRC"`. A match means a copy would break the hook; offer Symlink and Cancel only, and say why.
- ```
- question: "Which category?"
- header: "ECC · <skill|agent|hook>"
- options:
- - label: "<category or letter-range bucket>"
- description: "<N> components"
- ```
+ 6. **Map the destination.**
- **Level 2 — component.** Within the chosen bucket:
- - If ≤4 remain, present them directly as an `AskUserQuestion` (the original step-4 shape below).
- - If still >4, repeat Level 1's bucketing recursively on that subset (cascade again, ≤4 options each time) until a bucket has ≤4 candidates.
+ | Component | Source | Destination |
+ |---|---|---|
+ | Skill | `$ECC/skills/<name>/` (whole directory, so its references and scripts come along) | `~/.claude/skills/<name>/` |
+ | Agent | `$ECC/agents/<name>.md` | `~/.claude/agents/<name>.md` |
+ | Hook | `$ECC/scripts/hooks/<name>.js` or `.sh` | `~/.claude/hooks/<name>.js` or `.sh` |
- ```
- question: "Pick one ECC <skill|agent|hook> to load."
- header: "Pick"
- options:
- - label: "<component-name>"
- description: "<relative path under vendor/everything-claude-code>"
- ```
+ ```bash
+ mkdir -p "$(dirname "$DEST")"
+ test -e "$DEST" -o -L "$DEST" && echo exists || echo free
+ ```
- **Typed-name fallback — last resort only.** Only if cascading twice still leaves a bucket with more than 16 candidates (an extreme skew the alphabetical split can't converge on quickly), ask the user for a substring to filter by, then present the filtered matches as an `AskUserQuestion` (≤4, cascading again if the filter still returns too many). Never ask for the exact literal name or path as the first move.
+ If it exists, ask the conflict picker. On "Replace with backup": `mv "$DEST" "$DEST.backup-$(date +%Y%m%d-%H%M%S)"`.
- ### 5. Ask symlink or copy
+ 7. **Install.**
- ```
- question: "Install this ECC component as a symlink or a copy?"
- header: "Mode"
- options:
- - label: "Symlink (recommended)"
- - label: "Copy"
- - label: "Cancel"
- ```
+ ```bash
+ # Symlink mode (SRC is absolute, so the link survives a cwd change)
+ ln -s "$SRC" "$DEST"
+ # Copy mode
+ cp -R "$SRC" "$DEST"
+ ```
- ### 6. Map destination
+ 8. **Verify and report.**
- - Skill `skills/<name>/SKILL.md` → `~/.claude/skills/<name>/SKILL.md`
- - Agent `<name>.md` → `~/.claude/agents/<name>.md`
- - Hook `<name>.js|sh` → `~/.claude/hooks/<name>.js|sh`
+ ```bash
+ ls -ld "$DEST"; [ -L "$DEST" ] && readlink "$DEST"
+ [ -d "$DEST" ] && test -f "$DEST/SKILL.md" && echo "skill ok"
+ ```
- ```bash
- mkdir -p "$DEST_DIR"
- ```
+ Report source, destination, mode, the backup path if one was made, and the next step: a skill or agent loads in the next session; a hook is only a file until the user registers it in their own `settings.json` hooks block (point them at ECC's `hooks/hooks.json` entry for that script as the reference shape).
- If the destination exists, ask: "Keep existing" or "Replace with backup". On backup, move the existing target to `.backup-YYYYMMDD-HHMMSS` before installing.
+ ## Decision points
- ### 7. Install + verify
+ - **Type** (header "ECC"): 🟢 **Load a skill** (most ECC value is here) · **Load an agent** · **Load a hook** (file only; wiring stays manual) · **List available ECC components** (read-only).
+ - **Mode** (header "Mode"): 🟢 **Symlink** (follows the pinned vendor checkout on every submodule update) · **Copy** (editable snapshot that no longer updates) · **Cancel**.
+ - **Conflict** (header "Exists"): 🟢 **Keep existing** (nothing changes) · **Replace with backup** (moves the current file aside first).
- ```bash
- # Symlink mode
- ln -s "$ABS_SOURCE" "$DEST"
+ In Codex or any surface without `AskUserQuestion`, ask the same choices as one plain-text question.
- # Copy mode
- cp -R "$ABS_SOURCE" "$DEST"
+ ## Done when
- # Verify
- test -e "$DEST" && ls -l "$DEST"
- ```
+ - `ls -ld "$DEST"` shows the component, and for symlinks `readlink` points inside `vendor/everything-claude-code/`.
+ - A skill destination contains `SKILL.md`.
+ - The report names source, destination, mode and any backup.
- Report the source, destination, mode, and whether a backup was made.
+ ## Guardrails
- ## Anti-patterns — DO NOT
+ - Installing into `~/.claude/` changes the user's configuration; do it only for the component the user picked in this conversation.
+ - Never copy the full ECC harness, its command tree, rules, `settings.json` or installer output into `~/.claude/`.
+ - Never overwrite an existing skill, agent or hook without the conflict picker and a backup.
+ - Never edit files under `vendor/everything-claude-code/`.
+ - Never install binaries, `node_modules` or dependency folders, and never run ECC's `install.sh`.
+ - Never register an ECC hook in settings automatically.
- - Do not copy the full ECC harness, command tree, or settings into `~/.claude/`.
- - Do not overwrite existing local skills, agents, or hooks without a backup and confirmation.
- - Do not edit files under `vendor/everything-claude-code/`.
- - Do not install unknown binary files or dependency folders.
- - Do not add ECC hooks to settings automatically; install the file and tell the user where it landed.
+ ## See also
- ---
+ - `/ccc-upgrade` — refresh vendor checkouts, including ECC.
+ - `/ccc-suggest` — find a skill or plugin for the task at hand.
+ - `/ccc-settings` — inspect and edit Claude Code settings, including hooks.
> ⚙️ **Fable contract:** plan before build · verifier ≠ worker · prove before alarm · loops need gates · leave durable state — `rules/fable-method.md`