diff --git a/.claude/skills/ai-context/SKILL.md b/.claude/skills/ai-context/SKILL.md index ab870dc..20ed5ba 100644 --- a/.claude/skills/ai-context/SKILL.md +++ b/.claude/skills/ai-context/SKILL.md @@ -1,6 +1,6 @@ --- name: ai-context -description: Generates, updates, and maintains AGENTS-first AI IDE context files with AGENTS.md as canonical shared context and thin tool-specific bridges. Use this skill when the user wants to create a CLAUDE.md, generate AGENTS.md, set up context files for a project, update or fix out-of-date context files, refresh stale CLAUDE.md or AGENTS.md, bootstrap context for a new repo, move or promote MEMORY.md patterns into CLAUDE.md, audit context for drift, or generate cursorrules, copilot instructions, clinerules, windsurfrules, or GEMINI.md. This is the right skill for updating, regenerating, or fixing context files — not just checking them. Use proactively whenever context files may need attention, even if not explicitly requested. +description: Generates, updates, and maintains AGENTS-first AI IDE context files with AGENTS.md as canonical shared context and thin tool-specific bridges. Works across Claude Code, Codex CLI, Gemini CLI, OpenCode, Cursor, Copilot, Windsurf, and Cline. Use this skill when the user wants to create context files, generate AGENTS.md, set up CLAUDE.md or bridge files for a project, update or fix out-of-date context files, bootstrap context for a new repo, promote MEMORY.md patterns, audit context for drift, or generate cursorrules, copilot instructions, clinerules, windsurfrules, or GEMINI.md. This is the right skill for updating, regenerating, or fixing context files — not just checking them. Use proactively whenever context files may need attention, even if not explicitly requested. --- # AI Context File Generator @@ -37,14 +37,14 @@ Describe the **end state** you want, not step-by-step instructions. Consider fix | File | Role | Purpose | |------|------|---------| | `AGENTS.md` | Canonical shared context | Shared identity, commands, conventions, constraints, security notes, and monorepo guidance | -| `CLAUDE.md` | Thin bridge | `@AGENTS.md` import plus Claude-specific rules, key files, and workflow notes | +| `CLAUDE.md` | Thin bridge | Claude-specific rules, key files, and workflow notes (use `@AGENTS.md` import in Claude Code) | | `.cursorrules` | Thin bridge | Cursor-specific rule scoping or metadata only | | `.github/copilot-instructions.md` | Thin bridge | Copilot-specific review and PR guidance only | -| `.windsurfrules` | Compatibility bridge | Windsurf compatibility while AGENTS.md adoption continues | +| `.windsurfrules` | Thin bridge | Windsurf-specific rule activation or metadata only | | `.clinerules` | Thin bridge | Cline-specific autonomy boundaries and commit checklist | -| `GEMINI.md` | Compatibility bridge | Gemini-specific discovery shim while keeping AGENTS.md canonical | +| `GEMINI.md` | Thin bridge | Gemini-specific discovery or extension notes only | -**CLAUDE.md vs MEMORY.md:** CLAUDE.md contains instructions *for* Claude (shared via git). MEMORY.md contains notes *by* Claude (local only). Promote recurring MEMORY.md insights to CLAUDE.md. +**Context file vs memory:** Context files contain instructions *for* the agent (shared via git). Memory files (MEMORY.md, agent-memory/) are notes *by* the agent (local only). Promote recurring memory insights to the appropriate context file. ## Generation Workflow @@ -57,7 +57,7 @@ Describe the **end state** you want, not step-by-step instructions. Consider fix **AGENTS.md** (~120 lines): Identity, commands, non-default conventions, hard constraints, security notes, monorepo guidance. Omit Project Structure, architecture, dependency dumps, and key file tables. -**CLAUDE.md** (~10-20 lines, hard max 80): `@AGENTS.md`, then only Claude-specific additions such as `.claude/rules/` references, key file pointers, or path-scoped guidance. Do not restate shared commands and conventions unless Claude-specific formatting requires it. +**CLAUDE.md** (~10-20 lines, hard max 80): In Claude Code, use `@AGENTS.md` to import the canonical context, then add only Claude-specific additions (`.claude/rules/` references, key file pointers, path-scoped guidance). In other tools, CLAUDE.md is not used — AGENTS.md is loaded directly. **Other bridge files** (~10-20 lines each, hard max 60): reference or subset `AGENTS.md`, then add only tool-specific fields. Cline may add a `## Before Committing` checklist. `.windsurfrules` and `GEMINI.md` are compatibility bridges for now — keep them especially lean. @@ -90,6 +90,14 @@ Tracks [agents.md spec](https://github.com/agentsmd/agents.md) v1.0 via `upstrea - Don't repeat framework docs — agents know React, Express, Django - Don't include secrets or session-specific state -## Claude Code Reference +## Platform Notes -For advanced agent/skill frontmatter fields, variable substitution, dynamic context injection, bundled resource patterns, CLAUDE.md advanced features (@import, directory walking, claudeMdExcludes, managed policy), rules system (path-scoped rules, recursive discovery, user-level rules, symlinks), and plugin system (installation scopes, .lsp.json, output styles, plugin settings), load the companion reference: `SKILL-reference.md` +**AGENTS.md auto-load:** Codex CLI, OpenCode, Cursor, Windsurf, Cline, and Copilot load AGENTS.md natively. Claude Code requires `@AGENTS.md` in CLAUDE.md. Gemini CLI is configurable via `context.fileName` in settings.json. + +**Hooks:** Context Guard hooks are available on Claude Code (12 events), Gemini CLI (11), Copilot (8, preview), Cursor (4+), Cline (3), and Codex CLI (2, experimental). See the context-guard skill for per-platform setup. + +**Standalone verification:** Run `bin/context-verify.sh` on any platform for 0-100 health scoring without a plugin system. + +## Advanced Reference (Claude Code) + +For agent/skill frontmatter fields, variable substitution, dynamic context injection, bundled resources, CLAUDE.md advanced features (@import, directory walking, claudeMdExcludes, managed policy), rules system (path-scoped rules, recursive discovery, symlinks), and plugin system (installation scopes, output styles, plugin settings), load the companion reference: `SKILL-reference.md` diff --git a/.claude/skills/context-guard/SKILL.md b/.claude/skills/context-guard/SKILL.md index edb4ef3..c763190 100644 --- a/.claude/skills/context-guard/SKILL.md +++ b/.claude/skills/context-guard/SKILL.md @@ -1,6 +1,6 @@ --- name: context-guard -description: Installs opt-in Claude Code hooks with two-tier enforcement for AI context file freshness. Use this skill when the user wants to install context hooks, set up commit guards for context files, prevent stale CLAUDE.md or AGENTS.md from being committed, detect context drift, add content filter guards for OSS files, check context guard status, or uninstall context hooks. Covers install, install strict, uninstall, and status. Claude Code only — hooks do not work in OpenCode, Codex CLI, or other tools. +description: Installs context freshness hooks with two-tier enforcement. Full automation on Claude Code (12 hook events). Gemini CLI (11 events), Copilot (8, preview), Cursor (4+), and Cline (3) support hooks with platform-specific setup. Use this skill when the user wants to install context hooks, set up commit guards for context files, prevent stale CLAUDE.md or AGENTS.md from being committed, detect context drift, add content filter guards, check context guard status, or uninstall context hooks. Covers install, install strict, uninstall, and status. --- # Context Guard @@ -9,7 +9,7 @@ description: Installs opt-in Claude Code hooks with two-tier enforcement for AI Hooks and a quality rule to keep AI context files in sync with the codebase. Prevents content filter errors on standard OSS files. Two-tier enforcement for context doc freshness. -**Claude Code only.** OpenCode, Codex CLI, Cursor, Windsurf, Cline, and Gemini CLI do not support Claude Code hooks. Cross-tool features (skills, AGENTS.md) work without Context Guard. +**Primary platform: Claude Code** (full automation, 12 hook events). Other platforms with hook support — Gemini CLI (11 events), Copilot (8, preview), Cursor (4+), Cline (3) — can use adapted hooks from `platforms/` packages (coming soon). For platforms without hooks (Codex CLI, OpenCode, Windsurf), use `bin/context-verify.sh` as a manual or CI-based alternative. ## Enforcement Tiers diff --git a/.claude/skills/context-verify/SKILL.md b/.claude/skills/context-verify/SKILL.md index b826e24..5ea1857 100644 --- a/.claude/skills/context-verify/SKILL.md +++ b/.claude/skills/context-verify/SKILL.md @@ -1,6 +1,6 @@ --- name: context-verify -description: Validates AI context file quality with 13 checks and 0-100 health scoring. Use this skill when the user wants to check context file health, validate line budgets, detect stale paths, verify AGENTS-to-bridge consistency, run a context quality audit, score context files for CI, or check for discoverable content and MEMORY.md drift. Use proactively before releases or after structural changes. +description: Validates AI context file quality with 13 checks and 0-100 health scoring. Works on any platform — also available as a standalone CLI script (bin/context-verify.sh). Use this skill when the user wants to check context file health, validate line budgets, detect stale paths, verify AGENTS-to-bridge consistency, run a context quality audit, score context files for CI, or check for discoverable content and MEMORY.md drift. Use proactively before releases or after structural changes. --- # Context Verifier @@ -39,9 +39,9 @@ Treat `AGENTS.md` as the canonical shared context. Bridge files may subset or re If a project MEMORY.md exists, check for convention-like patterns ("Always", "Never", "Use") not yet promoted to CLAUDE.md. -### 6. Context Guard Status +### 6. Context Guard Status *(Claude Code, Gemini CLI, Copilot, Cursor)* -Check for hook scripts in `.claude/hooks/context-*.sh` and entries in `.claude/settings.json`. +Check for hook scripts and registration entries. In Claude Code: `.claude/hooks/context-*.sh` and `.claude/settings.json`. Other platforms use their own hook directories. ### 7. Context Load (Aggregate Token Estimate) @@ -104,6 +104,18 @@ If `.claude-plugin/plugin.json` exists, verify required fields: `name`, `version Report includes per-dimension breakdown and specific actions to reach grade A. +## Standalone CLI + +For platforms without skill support, or for CI pipelines, use the standalone script: + +```bash +bin/context-verify.sh # Interactive report +bin/context-verify.sh --ci # CI mode (exit 1 below threshold) +bin/context-verify.sh --ci --min-score 90 # Custom threshold +``` + +The CLI implements checks 1, 3, 5–14 automatically (bash + git). Check 2 (discoverable content) and check 4 (bridge consistency) are partially automated — full semantic analysis requires this AI-powered skill. + ## CI Integration -With `ci` argument, output machine-readable format and exit code 1 on failures. Accept `--min-score N` to fail the CI job below a threshold. +With `ci` argument (skill or CLI), output machine-readable format and exit code 1 on failures. Accept `--min-score N` to fail the CI job below a threshold. diff --git a/AGENTS.md b/AGENTS.md index d27da95..59f2a32 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,9 +19,9 @@ Skills are loaded on-demand. Each lives at `.claude/skills//SKILL.md`. The | Skill | What It Provides | |-------|-----------------| -| `ai-context` | AGENTS-first AI IDE context generation — builds canonical `AGENTS.md`, then emits thin bridges for Claude, Copilot, Cursor, Windsurf, Cline, and Gemini, with init/update/promote/audit lifecycle support | -| `context-guard` | Context Guard hook installation — two-tier enforcement, SessionStart health check, settings.json configuration, companion reference for 17 hook events and 4 handler types, troubleshooting *(Claude Code only)* | -| `context-verify` | Context file validation — line budgets, discoverable content detection, stale paths, @import validation, rule path-scope and symlink checks, .mcp.json validation, agent memory hygiene, plugin manifest completeness, AGENTS-to-bridge consistency, aggregate context load, and 0–100 health scoring with CI integration | +| `ai-context` | AGENTS-first AI IDE context generation across 8 tools — builds canonical `AGENTS.md`, then emits thin bridges for Claude, Copilot, Cursor, Windsurf, Cline, and Gemini, with init/update/promote/audit lifecycle support | +| `context-guard` | Context Guard hook installation — two-tier enforcement, SessionStart health check, settings.json configuration, companion reference for 17 hook events and 4 handler types, troubleshooting. Primary: Claude Code (12 events); cross-platform: Gemini CLI (11), Copilot (8), Cursor (4+), Cline (3) | +| `context-verify` | Context file validation — line budgets, discoverable content detection, stale paths, @import validation, rule path-scope and symlink checks, .mcp.json validation, agent memory hygiene, plugin manifest completeness, AGENTS-to-bridge consistency, aggregate context load, and 0–100 health scoring with CI integration. Also available as standalone CLI (`bin/context-verify.sh`) | ## Workflow Commands @@ -30,7 +30,7 @@ Invoke as `/contextdocs:command-name` in Claude Code, or as prompts in Codex CLI | Command | What It Does | |---------|-------------| | `ai-context` | Generate AGENTS-first AI context using Signal Gate — supports `all`, `claude`, `agents`, `cursor`, `copilot`, `windsurf`, `cline`, `gemini`, `init`, `update`, `promote`, `audit` | -| `context-guard` | Install, uninstall, or check status of Context Guard hooks with tiered enforcement *(Claude Code only)* | +| `context-guard` | Install, uninstall, or check status of Context Guard hooks with tiered enforcement — primarily Claude Code, with cross-platform hooks for Gemini CLI, Copilot, Cursor, and Cline | | `context-verify` | Validate context file quality — line budgets, stale paths, bridge consistency, health scoring, CI integration | ## Rules (Claude Code Only) @@ -40,9 +40,9 @@ Invoke as `/contextdocs:command-name` in Claude Code, or as prompts in Codex CLI - `doc-standards.md` — documentation quality standards, 4-Question Test, Lobby Principle, banned phrases (auto-loaded, PitchDocs) - `docs-awareness.md` — documentation trigger map, suggests PitchDocs commands when docs-relevant work is detected (auto-loaded, PitchDocs) -## Hooks (Claude Code Only) +## Hooks -7 opt-in hooks, installed via `/contextdocs:context-guard install`. Hooks reference the context-updater agent for autonomous action: +7 opt-in hooks for Claude Code, installed via `/contextdocs:context-guard install`. Adapted hooks for Gemini CLI, Copilot, Cursor, and Cline via `platforms/` packages (coming soon). For platforms without hooks, use `bin/context-verify.sh` as a CI-based alternative. - `context-session-start.sh` — session-start context health check (advisory) - `context-forced-eval.sh` — keyword-gated skill evaluation on context-related prompts (advisory) diff --git a/bin/context-verify.sh b/bin/context-verify.sh new file mode 100755 index 0000000..af8230c --- /dev/null +++ b/bin/context-verify.sh @@ -0,0 +1,758 @@ +#!/usr/bin/env bash +# context-verify.sh — Standalone AI context file health scorer +# Works on any platform with bash + git. No plugin system required. +# +# Usage: +# ./bin/context-verify.sh # Interactive report +# ./bin/context-verify.sh --ci # CI mode (exit 1 on score < 80) +# ./bin/context-verify.sh --ci --min-score 90 # Custom threshold +# +# Implements 10 of the 13 context-verify checks from ContextDocs. +# Checks 2 (discoverable content) and 4 (AGENTS-to-bridge consistency) +# are partially automated — full analysis requires the AI-powered skill. +set -euo pipefail + +# --- Configuration --- +CI_MODE=false +MIN_SCORE=80 +VERBOSE=false + +while [[ $# -gt 0 ]]; do + case $1 in + --ci) CI_MODE=true; shift ;; + --min-score) MIN_SCORE="$2"; shift 2 ;; + --verbose|-v) VERBOSE=true; shift ;; + --help|-h) + echo "Usage: context-verify.sh [--ci] [--min-score N] [--verbose]" + echo "" + echo "Options:" + echo " --ci CI mode: machine-readable output, exit 1 below threshold" + echo " --min-score N Minimum passing score (default: 80)" + echo " --verbose Show detailed check output" + echo "" + echo "Runs 10 automated context file health checks and produces a 0-100 score." + echo "Works on any platform — no plugin or AI tool required." + exit 0 + ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +# --- Scoring --- +score=100 +deductions=() +warnings=() +errors=() + +deduct() { + local points=$1 + local reason=$2 + score=$((score - points)) + if [ "$score" -lt 0 ]; then score=0; fi + deductions+=(" -${points}: ${reason}") +} + +warn() { + warnings+=(" ! $1") +} + +info() { + if [ "$VERBOSE" = true ] || [ "$CI_MODE" = false ]; then + echo "$1" + fi +} + +# --- Find project root (walk up to git root) --- +find_root() { + local dir + dir=$(git rev-parse --show-toplevel 2>/dev/null) || { + echo "ERROR: Not in a git repository" >&2 + exit 1 + } + echo "$dir" +} + +ROOT=$(find_root) +cd "$ROOT" + +# --- Detect context files --- +declare -a CONTEXT_FILES=() +declare -A FILE_ROLES=() + +add_file() { + local path=$1 role=$2 + if [ -f "$path" ]; then + CONTEXT_FILES+=("$path") + FILE_ROLES["$path"]="$role" + fi +} + +add_file "AGENTS.md" "canonical" +add_file "CLAUDE.md" "bridge" +add_file ".cursorrules" "bridge" +add_file ".github/copilot-instructions.md" "bridge" +add_file ".windsurfrules" "bridge" +add_file ".clinerules" "bridge" +add_file "GEMINI.md" "bridge" + +if [ ${#CONTEXT_FILES[@]} -eq 0 ]; then + echo "No AI context files found in ${ROOT}" + echo "Run your AI tool's context generation command to create them." + exit 0 +fi + +info "=== Context Verify — ${ROOT} ===" +info "Files found: ${#CONTEXT_FILES[@]}" +info "" + +# ============================================================ +# CHECK 1: Line Budget Compliance (max 20 points) +# ============================================================ +info "--- Check 1: Line Budgets ---" +check1_deductions=0 + +for f in "${CONTEXT_FILES[@]}"; do + lines=$(wc -l < "$f") + role=${FILE_ROLES["$f"]} + + if [ "$role" = "canonical" ]; then + # AGENTS.md: warning >120, over >160 + if [ "$lines" -gt 160 ]; then + deduct 5 "${f}: ${lines} lines (budget: 160)" + check1_deductions=$((check1_deductions + 5)) + info " OVER: ${f} — ${lines} lines (max 160)" + elif [ "$lines" -gt 120 ]; then + deduct 2 "${f}: ${lines} lines (warning: 120)" + check1_deductions=$((check1_deductions + 2)) + info " WARN: ${f} — ${lines} lines (target: 120)" + else + info " OK: ${f} — ${lines} lines" + fi + elif [ "$f" = "CLAUDE.md" ]; then + # CLAUDE.md bridge: warning >20, over >80 + if [ "$lines" -gt 80 ]; then + deduct 5 "${f}: ${lines} lines (budget: 80)" + check1_deductions=$((check1_deductions + 5)) + info " OVER: ${f} — ${lines} lines (max 80)" + elif [ "$lines" -gt 20 ]; then + deduct 2 "${f}: ${lines} lines (warning: 20)" + check1_deductions=$((check1_deductions + 2)) + info " WARN: ${f} — ${lines} lines (target: 20)" + else + info " OK: ${f} — ${lines} lines" + fi + else + # Other bridges: warning >20, over >60 + if [ "$lines" -gt 60 ]; then + deduct 5 "${f}: ${lines} lines (budget: 60)" + check1_deductions=$((check1_deductions + 5)) + info " OVER: ${f} — ${lines} lines (max 60)" + elif [ "$lines" -gt 20 ]; then + deduct 2 "${f}: ${lines} lines (warning: 20)" + check1_deductions=$((check1_deductions + 2)) + info " WARN: ${f} — ${lines} lines (target: 20)" + else + info " OK: ${f} — ${lines} lines" + fi + fi +done + +# Cap check 1 deductions at 20 +if [ "$check1_deductions" -gt 20 ]; then + score=$((score + check1_deductions - 20)) +fi +info "" + +# ============================================================ +# CHECK 2: Discoverable Content Detection (max 5 from signal quality) +# ============================================================ +info "--- Check 2: Discoverable Content ---" +check2_count=0 + +for f in "${CONTEXT_FILES[@]}"; do + # File tree characters + if grep -qP '├──|└──|│\s+' "$f" 2>/dev/null; then + check2_count=$((check2_count + 1)) + info " FOUND: ${f} contains file tree characters (├── └──)" + fi + + # "Project Structure" heading with content + if grep -qi '^#.*project structure' "$f" 2>/dev/null; then + check2_count=$((check2_count + 1)) + deduct 3 "${f}: contains 'Project Structure' section (discoverable)" + info " FOUND: ${f} has 'Project Structure' section" + fi +done + +# -1 per discoverable instance, max -5 +discoverable_deduct=$((check2_count > 5 ? 5 : check2_count)) +if [ "$check2_count" -gt 0 ] && [ "$discoverable_deduct" -gt 0 ]; then + # Only deduct for tree characters (Project Structure already deducted above) + tree_instances=$((check2_count - $(grep -rliP '^#.*project structure' "${CONTEXT_FILES[@]}" 2>/dev/null | wc -l))) + if [ "$tree_instances" -gt 0 ]; then + tree_deduct=$((tree_instances > 5 ? 5 : tree_instances)) + deduct "$tree_deduct" "Discoverable content: ${tree_instances} file tree instances" + fi +fi +if [ "$check2_count" -eq 0 ]; then + info " OK: No discoverable content detected" +fi +info "" + +# ============================================================ +# CHECK 3: Stale Path Detection (max 10 from path accuracy) +# ============================================================ +info "--- Check 3: Stale Paths ---" +stale_count=0 +stale_max=5 + +for f in "${CONTEXT_FILES[@]}"; do + # Extract backtick-quoted paths that look like file paths + while IFS= read -r path; do + # Skip empty, URLs, commands, variables, wildcards, templates + [[ -z "$path" ]] && continue + [[ "$path" =~ ^https?:// ]] && continue + [[ "$path" =~ ^git@ ]] && continue + [[ "$path" =~ ^\$ ]] && continue + [[ "$path" =~ \* ]] && continue + [[ "$path" =~ \<.*\> ]] && continue # Template placeholders + [[ "$path" =~ ^npm|^pip|^curl|^bash|^python ]] && continue + [[ "$path" =~ ^@ ]] && continue + [[ "$path" =~ ^# ]] && continue + [[ "$path" =~ : ]] && continue # Slash commands, protocols + [[ "$path" =~ ^/ ]] && continue # Absolute paths (system refs) + # Skip generic/example paths + [[ "$path" =~ /\.\.\./|example|your- ]] && continue + # Skip table-style documentation references (paths in | table | cells) + # These describe what files look like, not actual project paths + # Heuristic: skip if the path starts with . and contains no / (likely a file extension ref) + # and also skip well-known bridge file names mentioned in documentation tables + case "$path" in + .cursorrules|.clinerules|.windsurfrules|.windsurfrules.md) continue ;; + .github/copilot-instructions.md|.github/instructions/*) continue ;; + .cursor/rules/*|.windsurf/rules/*|.windsurf/skills/*) continue ;; + .clinerules/*|.agents/skills/*|.opencode/agents/*) continue ;; + GEMINI.md|CONVENTIONS.md|CLAUDE.md|AGENTS.md) continue ;; + gemini-extension.json|opencode.json|plugin.json) continue ;; + esac + # Must contain / to be treated as a relative path + # Bare filenames (no /) are usually documentation references, not path assertions + if [[ "$path" =~ / ]]; then + # Skip ALL_CAPS + [[ "$path" =~ ^[A-Z_]+$ ]] && continue + # Normalise: strip trailing punctuation + clean_path="${path%,}" + clean_path="${clean_path%.}" + clean_path="${clean_path%:}" + clean_path="${clean_path%)}" + if [ ! -e "$clean_path" ] && [ ! -d "$clean_path" ]; then + stale_count=$((stale_count + 1)) + if [ "$stale_count" -le "$stale_max" ]; then + info " STALE: ${f}: \`${clean_path}\` not found" + fi + fi + fi + done < <(grep -oP '`([^`]+)`' "$f" 2>/dev/null | sed 's/^`//;s/`$//') +done + +if [ "$stale_count" -gt 0 ]; then + path_deduct=$((stale_count * 2)) + if [ "$path_deduct" -gt 10 ]; then path_deduct=10; fi + deduct "$path_deduct" "Stale paths: ${stale_count} paths not found on disk" + if [ "$stale_count" -gt "$stale_max" ]; then + info " ... and $((stale_count - stale_max)) more" + fi +else + info " OK: All referenced paths exist" +fi +info "" + +# ============================================================ +# CHECK 4: AGENTS-to-Bridge Consistency (max 15 from consistency) +# ============================================================ +info "--- Check 4: Bridge Consistency ---" + +if [ -f "AGENTS.md" ]; then + # Check CLAUDE.md has @AGENTS.md import + if [ -f "CLAUDE.md" ]; then + if ! grep -q '@AGENTS.md\|@agents.md' "CLAUDE.md" 2>/dev/null; then + # Check if CLAUDE.md references AGENTS.md in some way + if ! grep -qi 'AGENTS.md' "CLAUDE.md" 2>/dev/null; then + deduct 2 "CLAUDE.md: missing @AGENTS.md import or reference" + info " WARN: CLAUDE.md does not reference AGENTS.md" + else + info " OK: CLAUDE.md references AGENTS.md" + fi + else + info " OK: CLAUDE.md imports @AGENTS.md" + fi + fi + + # Check bridge files aren't larger than AGENTS.md (sign of duplication) + agents_lines=$(wc -l < "AGENTS.md") + for f in "${CONTEXT_FILES[@]}"; do + [ "$f" = "AGENTS.md" ] && continue + bridge_lines=$(wc -l < "$f") + if [ "$bridge_lines" -gt "$agents_lines" ]; then + deduct 3 "${f}: ${bridge_lines} lines > AGENTS.md ${agents_lines} lines (likely duplicating shared content)" + info " WARN: ${f} (${bridge_lines} lines) is longer than AGENTS.md (${agents_lines} lines)" + fi + done +else + deduct 5 "No AGENTS.md found — cannot verify bridge consistency" + info " WARN: No AGENTS.md — bridges have no canonical source" +fi +info "" + +# ============================================================ +# CHECK 5: MEMORY.md Drift (max 2 from freshness) +# ============================================================ +info "--- Check 5: MEMORY.md Drift ---" + +# Look for MEMORY.md in common locations +memory_file="" +for candidate in "MEMORY.md" ".claude/MEMORY.md" ".claude/memory/MEMORY.md"; do + if [ -f "$candidate" ]; then + memory_file="$candidate" + break + fi +done + +# Also check user-level memory for this project +if [ -z "$memory_file" ]; then + # Check ~/.claude/projects/ for a project-specific MEMORY.md + project_hash=$(echo "$ROOT" | sed 's|/|-|g; s|^-||') + user_memory="$HOME/.claude/projects/${project_hash}/memory/MEMORY.md" + if [ -f "$user_memory" ]; then + memory_file="$user_memory" + fi +fi + +if [ -n "$memory_file" ]; then + # Check for convention-like patterns not in CLAUDE.md + convention_patterns=0 + if [ -f "CLAUDE.md" ]; then + while IFS= read -r line; do + # Look for "Always", "Never", "Use", "Prefer" patterns + if echo "$line" | grep -qiP '^\s*-?\s*(always|never|use|prefer|don.t|do not)\b'; then + # Check if this convention is already in CLAUDE.md + keyword=$(echo "$line" | grep -oP '(always|never|use|prefer|don.t|do not)\s+\w+' | head -1) + if [ -n "$keyword" ] && ! grep -qi "$keyword" "CLAUDE.md" 2>/dev/null; then + convention_patterns=$((convention_patterns + 1)) + fi + fi + done < "$memory_file" + fi + + if [ "$convention_patterns" -gt 0 ]; then + deduct 2 "MEMORY.md: ${convention_patterns} convention patterns not yet promoted to CLAUDE.md" + info " WARN: ${convention_patterns} patterns in ${memory_file} could be promoted" + else + info " OK: No unpromotable patterns detected" + fi +else + info " SKIP: No MEMORY.md found" +fi +info "" + +# ============================================================ +# CHECK 6: Context Guard Status (informational, no score impact) +# ============================================================ +info "--- Check 6: Context Guard Status ---" + +hook_count=0 +if [ -d ".claude/hooks" ]; then + hook_count=$(find .claude/hooks -name 'context-*.sh' -type f 2>/dev/null | wc -l) +fi + +settings_hooks=0 +if [ -f ".claude/settings.json" ]; then + # Check if hooks are registered + if command -v jq &>/dev/null; then + settings_hooks=$(jq -r '.hooks // {} | keys | length' .claude/settings.json 2>/dev/null || echo 0) + fi +fi + +if [ "$hook_count" -gt 0 ]; then + info " OK: ${hook_count} Context Guard hook scripts found" + if [ "$settings_hooks" -gt 0 ]; then + info " OK: Hooks registered in settings.json (${settings_hooks} events)" + else + warn "Hook scripts exist but may not be registered in settings.json" + info " WARN: Hook scripts exist but no events in settings.json" + fi +else + info " INFO: No Context Guard hooks installed (optional, Claude Code only)" +fi +info "" + +# ============================================================ +# CHECK 7: Context Load / Aggregate Token Estimate (max 10) +# ============================================================ +info "--- Check 7: Context Load ---" + +# Estimate tokens per tool based on which files they load +# Approximation: 1 token ≈ 4 characters for English markdown +estimate_tokens() { + local file=$1 + if [ -f "$file" ]; then + local chars + chars=$(wc -c < "$file") + echo $((chars / 4)) + else + echo 0 + fi +} + +# Claude Code loads: CLAUDE.md + AGENTS.md (via @import) + .claude/rules/*.md +claude_tokens=0 +claude_tokens=$((claude_tokens + $(estimate_tokens "CLAUDE.md"))) +claude_tokens=$((claude_tokens + $(estimate_tokens "AGENTS.md"))) +if [ -d ".claude/rules" ]; then + for f in .claude/rules/*.md; do + [ -f "$f" ] || continue + claude_tokens=$((claude_tokens + $(estimate_tokens "$f"))) + done +fi + +# Codex CLI / OpenCode: AGENTS.md only (native) +codex_tokens=$(estimate_tokens "AGENTS.md") + +# Cursor: .cursorrules + AGENTS.md + .cursor/rules/*.md +cursor_tokens=0 +cursor_tokens=$((cursor_tokens + $(estimate_tokens ".cursorrules"))) +cursor_tokens=$((cursor_tokens + $(estimate_tokens "AGENTS.md"))) +if [ -d ".cursor/rules" ]; then + for f in .cursor/rules/*.md .cursor/rules/*.mdc; do + [ -f "$f" ] || continue + cursor_tokens=$((cursor_tokens + $(estimate_tokens "$f"))) + done +fi + +# Copilot: .github/copilot-instructions.md + AGENTS.md + .github/instructions/*.md +copilot_tokens=0 +copilot_tokens=$((copilot_tokens + $(estimate_tokens ".github/copilot-instructions.md"))) +copilot_tokens=$((copilot_tokens + $(estimate_tokens "AGENTS.md"))) +if [ -d ".github/instructions" ]; then + for f in .github/instructions/*.md; do + [ -f "$f" ] || continue + copilot_tokens=$((copilot_tokens + $(estimate_tokens "$f"))) + done +fi + +# Gemini CLI: GEMINI.md (or AGENTS.md if configured) +gemini_tokens=$(($(estimate_tokens "GEMINI.md") + $(estimate_tokens "AGENTS.md"))) + +# Windsurf: .windsurfrules + AGENTS.md + .windsurf/rules/*.md +windsurf_tokens=0 +windsurf_tokens=$((windsurf_tokens + $(estimate_tokens ".windsurfrules"))) +windsurf_tokens=$((windsurf_tokens + $(estimate_tokens "AGENTS.md"))) +if [ -d ".windsurf/rules" ]; then + for f in .windsurf/rules/*.md; do + [ -f "$f" ] || continue + windsurf_tokens=$((windsurf_tokens + $(estimate_tokens "$f"))) + done +fi + +# Cline: .clinerules + AGENTS.md +cline_tokens=0 +cline_tokens=$((cline_tokens + $(estimate_tokens ".clinerules"))) +cline_tokens=$((cline_tokens + $(estimate_tokens "AGENTS.md"))) +if [ -d ".clinerules" ] && [ ! -f ".clinerules" ]; then + for f in .clinerules/*.md .clinerules/*.txt; do + [ -f "$f" ] || continue + cline_tokens=$((cline_tokens + $(estimate_tokens "$f"))) + done +fi + +# Report and score +declare -A tool_tokens=( + ["Claude Code"]=$claude_tokens + ["Codex CLI"]=$codex_tokens + ["Cursor"]=$cursor_tokens + ["Copilot"]=$copilot_tokens + ["Gemini CLI"]=$gemini_tokens + ["Windsurf"]=$windsurf_tokens + ["Cline"]=$cline_tokens +) + +for tool in "Claude Code" "Codex CLI" "Cursor" "Copilot" "Gemini CLI" "Windsurf" "Cline"; do + tokens=${tool_tokens["$tool"]} + if [ "$tokens" -eq 0 ]; then continue; fi + + if [ "$tokens" -gt 10000 ]; then + deduct 5 "${tool}: ~${tokens} tokens (over 10K budget)" + info " OVER: ${tool} — ~${tokens} tokens" + elif [ "$tokens" -gt 5000 ]; then + deduct 3 "${tool}: ~${tokens} tokens (warning: 5K)" + info " WARN: ${tool} — ~${tokens} tokens" + else + info " OK: ${tool} — ~${tokens} tokens" + fi +done +info "" + +# ============================================================ +# CHECK 8: @import Path Validation (part of path accuracy) +# ============================================================ +info "--- Check 8: @import Validation ---" +import_errors=0 + +for f in "${CONTEXT_FILES[@]}"; do + while IFS= read -r import_path; do + [[ -z "$import_path" ]] && continue + if [ ! -f "$import_path" ]; then + import_errors=$((import_errors + 1)) + info " BROKEN: ${f}: @${import_path} — target not found" + fi + done < <(grep -oP '^@(.+)$' "$f" 2>/dev/null | sed 's/^@//') +done + +if [ "$import_errors" -gt 0 ]; then + deduct $((import_errors * 2)) "@import: ${import_errors} broken imports" +else + info " OK: All @imports resolve" +fi +info "" + +# ============================================================ +# CHECK 9: Rule Path-Scope Validation (part of path accuracy) +# ============================================================ +info "--- Check 9: Rule Path Scopes ---" +orphaned_rules=0 + +if [ -d ".claude/rules" ]; then + for f in .claude/rules/*.md; do + [ -f "$f" ] || continue + # Extract paths: from YAML frontmatter + in_frontmatter=false + in_paths=false + while IFS= read -r line; do + if [[ "$line" == "---" ]]; then + if [ "$in_frontmatter" = true ]; then break; fi + in_frontmatter=true + continue + fi + if [ "$in_frontmatter" = true ]; then + if [[ "$line" =~ ^paths: ]]; then + in_paths=true + continue + fi + if [ "$in_paths" = true ]; then + if [[ "$line" =~ ^[[:space:]]+-[[:space:]] ]]; then + glob_pattern=$(echo "$line" | sed 's/^[[:space:]]*-[[:space:]]*//' | tr -d '"' | tr -d "'") + # Check if glob matches anything + if ! compgen -G "$glob_pattern" >/dev/null 2>&1; then + orphaned_rules=$((orphaned_rules + 1)) + info " ORPHAN: ${f}: paths pattern '${glob_pattern}' matches nothing" + fi + else + in_paths=false + fi + fi + fi + done < "$f" + done +fi + +if [ "$orphaned_rules" -gt 0 ]; then + deduct $((orphaned_rules * 2)) "Rule path-scopes: ${orphaned_rules} patterns match no files" +else + info " OK: All rule path-scope patterns match files (or no path-scoped rules)" +fi +info "" + +# ============================================================ +# CHECK 10: Rule Symlink Targets (part of path accuracy) +# ============================================================ +info "--- Check 10: Rule Symlinks ---" +broken_symlinks=0 + +if [ -d ".claude/rules" ]; then + for f in .claude/rules/*.md; do + if [ -L "$f" ]; then + target=$(readlink "$f") + if [ ! -e "$f" ]; then + broken_symlinks=$((broken_symlinks + 1)) + info " BROKEN: ${f} -> ${target} (target missing)" + else + info " OK: ${f} -> ${target}" + fi + fi + done +fi + +if [ "$broken_symlinks" -gt 0 ]; then + deduct $((broken_symlinks * 2)) "Rule symlinks: ${broken_symlinks} broken" +else + info " OK: No broken rule symlinks" +fi +info "" + +# ============================================================ +# CHECK 11: .mcp.json Validation (part of path accuracy) +# ============================================================ +info "--- Check 11: .mcp.json ---" + +if [ -f ".mcp.json" ]; then + if command -v jq &>/dev/null; then + if ! jq empty .mcp.json 2>/dev/null; then + deduct 2 ".mcp.json: invalid JSON" + info " ERROR: .mcp.json is not valid JSON" + elif ! jq -e '.mcpServers' .mcp.json >/dev/null 2>&1; then + deduct 2 ".mcp.json: missing mcpServers object" + info " WARN: .mcp.json missing mcpServers object" + else + server_count=$(jq '.mcpServers | length' .mcp.json 2>/dev/null || echo 0) + info " OK: .mcp.json valid with ${server_count} servers" + fi + else + info " SKIP: jq not installed — cannot validate .mcp.json" + fi +else + info " SKIP: No .mcp.json found" +fi +info "" + +# ============================================================ +# CHECK 12: Agent Memory Directory Hygiene (part of signal quality) +# ============================================================ +info "--- Check 12: Agent Memory Hygiene ---" + +memory_tracked=false +for dir in ".claude/agent-memory" ".claude/agent-memory-local"; do + if [ -d "$dir" ]; then + # Check if tracked in git + if git ls-files --error-unmatch "$dir" >/dev/null 2>&1; then + memory_tracked=true + deduct 3 "${dir}: tracked in git (should be gitignored)" + info " WARN: ${dir} is tracked in git — add to .gitignore" + fi + fi +done + +if [ "$memory_tracked" = false ]; then + info " OK: No agent memory directories tracked in git" +fi +info "" + +# ============================================================ +# CHECK 13: Plugin Manifest Completeness (part of consistency) +# ============================================================ +info "--- Check 13: Plugin Manifest ---" + +if [ -f ".claude-plugin/plugin.json" ]; then + if command -v jq &>/dev/null; then + missing_required=0 + missing_optional=0 + + for field in name version description; do + if ! jq -e ".${field}" .claude-plugin/plugin.json >/dev/null 2>&1; then + missing_required=$((missing_required + 1)) + info " MISSING: required field '${field}'" + fi + done + + for field in keywords author repository; do + if ! jq -e ".${field}" .claude-plugin/plugin.json >/dev/null 2>&1; then + missing_optional=$((missing_optional + 1)) + if [ "$VERBOSE" = true ]; then + info " OPTIONAL: field '${field}' not set" + fi + fi + done + + if [ "$missing_required" -gt 0 ]; then + deduct $((missing_required * 2)) "Plugin manifest: ${missing_required} required fields missing" + fi + + if [ "$missing_required" -eq 0 ] && [ "$missing_optional" -eq 0 ]; then + info " OK: Plugin manifest complete" + elif [ "$missing_required" -eq 0 ]; then + info " OK: Required fields present (${missing_optional} optional fields missing)" + fi + else + info " SKIP: jq not installed — cannot validate plugin.json" + fi +else + info " SKIP: No plugin manifest found" +fi +info "" + +# ============================================================ +# CHECK 14: Freshness (stale >90 days) (part of freshness score) +# ============================================================ +info "--- Check 14: Freshness ---" +stale_files=0 + +for f in "${CONTEXT_FILES[@]}"; do + if git log -1 --format="%at" -- "$f" >/dev/null 2>&1; then + last_modified=$(git log -1 --format="%at" -- "$f" 2>/dev/null || echo 0) + now=$(date +%s) + age_days=$(( (now - last_modified) / 86400 )) + if [ "$age_days" -gt 90 ]; then + stale_files=$((stale_files + 1)) + deduct 3 "${f}: last modified ${age_days} days ago" + info " STALE: ${f} — ${age_days} days since last update" + elif [ "$age_days" -gt 60 ]; then + info " AGING: ${f} — ${age_days} days since last update" + else + info " OK: ${f} — ${age_days} days old" + fi + fi +done +info "" + +# ============================================================ +# REPORT +# ============================================================ +echo "=== Health Score ===" +echo "" + +# Determine grade +grade="" +label="" +if [ "$score" -ge 90 ]; then + grade="A"; label="Lean and current" +elif [ "$score" -ge 80 ]; then + grade="B"; label="Minor tuning needed" +elif [ "$score" -ge 70 ]; then + grade="C"; label="Needs attention" +elif [ "$score" -ge 60 ]; then + grade="D"; label="Significant drift" +else + grade="F"; label="Overhaul recommended" +fi + +echo "Score: ${score}/100 (${grade} — ${label})" +echo "" + +if [ ${#deductions[@]} -gt 0 ]; then + echo "Deductions:" + for d in "${deductions[@]}"; do + echo "$d" + done + echo "" +fi + +if [ ${#warnings[@]} -gt 0 ]; then + echo "Warnings:" + for w in "${warnings[@]}"; do + echo "$w" + done + echo "" +fi + +# CI mode: exit with appropriate code +if [ "$CI_MODE" = true ]; then + echo "ci_score=${score}" + echo "ci_grade=${grade}" + echo "ci_threshold=${MIN_SCORE}" + if [ "$score" -lt "$MIN_SCORE" ]; then + echo "FAIL: Score ${score} is below threshold ${MIN_SCORE}" + exit 1 + else + echo "PASS: Score ${score} meets threshold ${MIN_SCORE}" + exit 0 + fi +fi diff --git a/docs/guides/troubleshooting.md b/docs/guides/troubleshooting.md index 04aafb2..92b20ff 100644 --- a/docs/guides/troubleshooting.md +++ b/docs/guides/troubleshooting.md @@ -94,14 +94,40 @@ The `promote` command moves confirmed patterns from MEMORY.md into CLAUDE.md: ## Cross-Tool Compatibility -| Feature | Claude Code | OpenCode | Codex CLI | Cursor | Windsurf | Cline | Gemini CLI | -|---------|------------|----------|-----------|--------|----------|-------|------------| -| Plugin install | Yes | Yes | No | No | No | No | No | -| Context file generation | Yes | Yes | Manual | Manual | Manual | Manual | Manual | -| Context Guard hooks | Yes | No | No | No | No | No | No | -| Context verification | Yes | Yes | Manual | Manual | Manual | Manual | Manual | - -For tools without plugin support, copy the relevant context file into your project manually. The generated files (.cursorrules, .windsurfrules, etc.) work with their respective tools automatically. +The AI coding tool landscape has converged around shared primitives. Most tools now support AGENTS.md, skills (SKILL.md), and hooks — not just static context files. + +### Platform Support Matrix (March 2026) + +| Feature | Claude Code | Gemini CLI | Copilot | Cursor | Codex CLI | OpenCode | Cline | Windsurf | +|---------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| AGENTS.md auto-load | via @import | configurable | yes | yes | native | native | fallback | yes | +| Skills (SKILL.md) | yes | yes | yes | yes | yes | yes | merged | yes | +| Hooks | 12 events | 11 events | 8 (preview) | 4+ events | 2 (exp) | partial | 3 events | enterprise | +| Custom agents | yes | yes (exp) | yes | yes | yes | yes | read-only | limited | +| Rules directory | yes | via ext | yes | yes | no | partial | yes | yes | +| Plugin/extension model | plugin.json | extension | .github/ | marketplace | skills pkg | config | MCP | MCP | + +### What ContextDocs Delivers Per Platform + +| Tier | Platforms | Experience | +|------|----------|------------| +| **Full** | Claude Code | Skills + hooks + agents + rules + autonomous maintenance | +| **Tier 1** | Gemini CLI, Cursor, Copilot | Skills + hooks + agents (near-parity, coming soon) | +| **Tier 2** | Codex CLI, OpenCode, Cline | Skills + agents, manual verification | +| **Tier 3** | Windsurf | Skills + rules, no automated hooks | +| **Tier 4** | Aider | Context files only (`--read AGENTS.md`) | + +### Getting Started by Platform + +**Claude Code / OpenCode**: Install as a plugin — `/install github:littlebearapps/contextdocs` + +**Codex CLI / Gemini CLI**: AGENTS.md is auto-loaded natively. Skills work if placed in the standard skills directory. + +**Cursor / Copilot / Windsurf / Cline**: Run `/contextdocs:ai-context init` in Claude Code to generate all bridge files, or manually create the relevant context file (`.cursorrules`, `.github/copilot-instructions.md`, `.windsurfrules`, `.clinerules`). + +**All platforms**: Run `bin/context-verify.sh` for 0-100 health scoring — no plugin system required. + +See `docs/references/platform-capabilities.md` for detailed per-tool capability documentation. --- diff --git a/docs/references/platform-capabilities.md b/docs/references/platform-capabilities.md new file mode 100644 index 0000000..69388c5 --- /dev/null +++ b/docs/references/platform-capabilities.md @@ -0,0 +1,176 @@ +--- +title: "Platform Capabilities Reference" +description: "Detailed capability matrix for AI coding tools — what each platform supports and how ContextDocs integrates." +type: reference +last_verified: "1.5.0" # x-release-please-version +--- + +# Platform Capabilities Reference + +> **Last researched:** March 2026. The AI coding tool landscape evolves rapidly — verify against each tool's latest release notes. + +--- + +## Capability Matrix + +| Capability | Claude Code | Gemini CLI | Copilot | Cursor | Codex CLI | OpenCode | Cline | Windsurf | Aider | +|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| **Context files** | | | | | | | | | | +| AGENTS.md auto-load | via @import | configurable | yes | yes | native | native | fallback | yes | no | +| Context file | CLAUDE.md | GEMINI.md | copilot-instructions.md | .cursor/rules/ | AGENTS.md | AGENTS.md | .clinerules/ | .windsurf/rules/ | CONVENTIONS.md | +| @import syntax | yes | yes | no | no | no | no | no | no | no | +| **Extensibility** | | | | | | | | | | +| Skills (SKILL.md) | yes | yes | yes | yes | yes | yes | merged w/cmds | yes | no | +| Custom agents | yes | yes (exp) | yes | yes (v2.4) | yes | yes | read-only | limited | no | +| Rules directory | .claude/rules/ | via extensions | .github/instructions/ | .cursor/rules/ | no | partial | .clinerules/ | .windsurf/rules/ | no | +| Plugin/extension model | plugin.json | gemini-extension.json | .github/ plugins | marketplace | skills pkg | config | MCP self-install | MCP marketplace | no | +| MCP servers | yes | yes | yes | yes | yes | yes | yes | yes | no | +| Slash commands | yes | yes | via .prompt.md | via skills | yes (25+) | yes | merged w/skills | via workflows | yes (15+) | +| **Hooks** | | | | | | | | | | +| Session start | yes | yes | yes (preview) | no | yes (exp) | no | no | no | no | +| Pre-tool use | yes | yes (BeforeTool) | yes (preview) | yes | no | no | yes | enterprise | no | +| Post-tool use | yes | yes (AfterTool) | yes (preview) | yes | no | no | yes | enterprise | no | +| Session end / Stop | yes | yes | yes (preview) | yes | yes (exp) | no | no | no | no | +| User prompt submit | yes | no | yes (preview) | yes | no | no | yes | no | no | +| Total hook events | 12 | 11 | 8 | 4+ | 2 | partial | 3 | enterprise | 0 | + +--- + +## Per-Tool Details + +### Claude Code + +**Context loading:** Auto-loads `CLAUDE.md` from project root and ancestor directories. Does NOT auto-load `AGENTS.md` — use `@AGENTS.md` import in CLAUDE.md. Rules in `.claude/rules/*.md` are auto-loaded. + +**Extension model:** Full plugin system via `.claude-plugin/plugin.json`. Supports skills, agents, hooks, rules, commands, MCP servers. Installed globally or per-project. + +**Hooks:** 12 event types — PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, UserPromptSubmit, SubagentStop, PreCompact, Notification, and more. Four handler types: command (bash), http (webhook), prompt (single-turn LLM), agent (agentic verifier). + +**ContextDocs support:** Full — all skills, hooks, agents, rules, and commands. + +### Gemini CLI + +**Context loading:** Auto-loads `GEMINI.md` from workspace and parent directories. Configurable via `settings.json` to load `AGENTS.md` as fallback (`context.fileName: ["AGENTS.md", "GEMINI.md"]`). Supports `@file.md` import syntax. + +**Extension model:** Full extension framework via `gemini-extension.json`. Extensions bundle MCP servers, context files, slash commands, skills, agents, hooks, and policy rules. Installable from npm or local directories. + +**Hooks:** 11 events — SessionStart, SessionEnd, BeforeAgent, AfterAgent, BeforeModel, AfterModel, BeforeToolSelection, BeforeTool, AfterTool, PreCompress, Notification. JSON stdin/stdout communication. Exit code 2 blocks execution. + +**Agents:** Experimental (requires `experimental.enableAgents: true`). Local and remote subagents. Agent definitions as `.md` files in `agents/` directory. + +**ContextDocs support:** Tier 1 — skills, hooks, agents, and policies all portable. Extension package planned. + +### GitHub Copilot + +**Context loading:** Auto-loads `.github/copilot-instructions.md` (repo-wide) and `.github/instructions/*.instructions.md` (path-scoped with `applyTo` glob). Also loads `AGENTS.md` from anywhere in the tree (nearest takes precedence). Custom agents in `.github/agents/*.agent.md`. + +**Extension model:** Plugins with 5 primitives — agents, skills, hooks, MCP servers, and instructions. Marketplace available. `/plugin install owner/repo` syntax. + +**Hooks:** 8 events (Preview) — sessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse, agentStop, subagentStop, errorOccurred. Configured in `.github/hooks/*.json`. preToolUse can approve or deny. + +**Skills:** Open Agent Skills standard in `.github/skills//SKILL.md` or `.claude/skills/`. Cross-tool compatible (VS Code, CLI, coding agent). + +**ContextDocs support:** Tier 1 — skills, hooks, agents, and instructions all portable. Package planned. + +### Cursor + +**Context loading:** `.cursor/rules/*.mdc` (modern, replacing deprecated `.cursorrules`). Also loads `AGENTS.md` with directory-scoped overrides. Four activation modes: Always Apply, Apply Intelligently, Apply to Specific Files (globs), Apply Manually. + +**Extension model:** Plugin marketplace (since v2.4, Feb 2026). Plugins package skills, subagents, MCP servers, hooks, and rules. `/plugin install owner/repo` syntax. + +**Hooks:** 4+ events — stop, beforeSubmitPrompt, PreToolUse, PostToolUse. + +**Agents:** Subagents since v2.4. Custom subagents with own context, prompts, tool access, and models. Can load resources from `~/.claude/{skills,agents}`. + +**ContextDocs support:** Tier 1 — skills, hooks, agents, and rules all portable. Plugin planned. + +### Codex CLI + +**Context loading:** `AGENTS.md` auto-loaded natively — walked from git root to CWD (hierarchical). Also checks `~/.codex/AGENTS.md` (global). Max combined size 32 KiB default. + +**Extension model:** Open Agent Skills standard. Skills scanned from `.agents/skills` at CWD, repo root, `$HOME`, `/etc/codex/`, and bundled. Activated via `/skills`, `$skillname` mention, or auto-selected by description. + +**Hooks:** Experimental — only SessionStart and Stop events. No PreToolUse/PostToolUse yet. + +**Agents:** Yes. Subagents spawn on explicit request. Each runs independently with own model and tool access. Configured in `[agents]` section of `config.toml`. + +**ContextDocs support:** Tier 2 — skills and agents work, hooks limited to session events. + +### OpenCode + +**Context loading:** `AGENTS.md` from project root (primary). `CLAUDE.md` as fallback (Claude Code compatibility). `~/.config/opencode/AGENTS.md` (global). Additional files via `instructions` field in `opencode.json`. + +**Extension model:** Custom agents in `opencode.json` or `.opencode/agents/*.md`. Claude Code skill directory compatibility (`.claude/skills/`). Can be disabled via `OPENCODE_DISABLE_CLAUDE_CODE=1`. + +**Hooks:** Partial. Does not natively run Claude Code JSON hooks. Open issue for compatibility. + +**Agents:** Four built-in (Build, Plan, General, Explore) + custom agents. Per-agent tool permissions, model overrides, step limits. + +**ContextDocs support:** Tier 2 — skills and agents work, no automated hooks. + +### Cline + +**Context loading:** `.clinerules` file or `.clinerules/` directory at project root. Auto-detects fallbacks: `.cursorrules`, `.windsurfrules`, `AGENTS.md`. Supports path-based conditional activation via `paths:` YAML frontmatter. + +**Extension model:** MCP self-install. Hooks in `.clinerules/hooks/` (project) or `~/Documents/Cline/Rules/Hooks/` (global). + +**Hooks:** 3 events — PreToolUse, PostToolUse, UserPromptSubmit. JSON stdin/stdout. macOS and Linux only (no Windows). + +**Agents:** Subagents (disabled by default). Read-only — can explore but cannot write or run destructive commands. + +**ContextDocs support:** Tier 2 — skills (merged with commands), hooks (3 events), read-only agents. + +### Windsurf + +**Context loading:** `.windsurf/rules/*.md` (workspace, 12,000 chars per file). `.windsurfrules` at root (legacy). `AGENTS.md` at root and subdirectories. Four activation modes: always_on, model_decision, glob, manual. + +**Extension model:** MCP Marketplace for one-click installs. Skills in `.windsurf/skills//SKILL.md`. Workflows invoked via slash commands. + +**Hooks:** Enterprise only — hooks on prompts for logging/policy, hooks on responses for auditing. Not developer-extensible. + +**Agents:** Limited. Cascade is the primary agent. Fast Context subagent for code search. No custom subagent system. + +**ContextDocs support:** Tier 3 — skills and rules work, no hooks or agents for non-enterprise. + +### Aider + +**Context loading:** No auto-loaded context file. Uses `CONVENTIONS.md` loaded via `--read` flag or `.aider.conf.yml` config. No native AGENTS.md support (feature requested). + +**Extension model:** None. Slash commands only (15+ built-in). No skills, hooks, or agents. No MCP (PR pending). + +**ContextDocs support:** Tier 4 — AGENTS.md loadable via `--read AGENTS.md`. Use `bin/context-verify.sh` for health scoring. + +--- + +## ContextDocs Feature Portability + +| ContextDocs Feature | Portable? | Notes | +|---|---|---| +| Signal Gate principle | Yes | Tool-agnostic methodology | +| AGENTS-first architecture | Yes | AGENTS.md widely supported | +| Line budgets | Yes | Measurable standards, any tool | +| ai-context skill | Yes | SKILL.md is cross-tool standard | +| context-verify skill | Yes | Checks are tool-agnostic | +| context-verify CLI | Yes | Bash script, no plugin needed | +| context-guard hooks | Partial | Need per-tool hook adapters | +| context-updater agent | Partial | Agent format differs per tool | +| Rules (auto-loaded) | Partial | Directory varies per tool | +| Plugin manifest | No | Claude Code specific | +| settings.json hooks | No | Claude Code specific | +| @AGENTS.md import | Partial | Claude Code + Gemini CLI only | + +--- + +## Sources + +| Tool | Documentation | Last Verified | +|---|---|---| +| Claude Code | [code.claude.com/docs](https://code.claude.com/docs) | March 2026 | +| Gemini CLI | [geminicli.com/docs](https://geminicli.com/docs) | March 2026 | +| GitHub Copilot | [docs.github.com/copilot](https://docs.github.com/copilot) | March 2026 | +| Cursor | [cursor.com/docs](https://cursor.com/docs) | March 2026 | +| Codex CLI | [developers.openai.com/codex](https://developers.openai.com/codex) | March 2026 | +| OpenCode | [opencode.ai/docs](https://opencode.ai/docs) | March 2026 | +| Cline | [docs.cline.bot](https://docs.cline.bot) | March 2026 | +| Windsurf | [docs.windsurf.com](https://docs.windsurf.com) | March 2026 | +| Aider | [aider.chat/docs](https://aider.chat/docs) | March 2026 |