diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 79f7c3ec..adacfabc 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -559,8 +559,8 @@ { "name": "claude-code-docs", "source": { - "source": "url", - "url": "https://github.com/pleaseai/claude-code-docs.git" + "source": "local", + "path": "./plugins/claude-code-docs" }, "policy": { "installation": "AVAILABLE", diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4cc58d51..e2ed33a0 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -772,10 +772,7 @@ "filesRead": ["**/.claude-plugin/**", "**/.claude/settings.json", "**/hooks/hooks.json"] } }, - "source": { - "source": "github", - "repo": "pleaseai/claude-code-docs" - }, + "source": "./plugins/claude-code-docs", "homepage": "https://github.com/pleaseai/claude-code-docs" }, { diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index e4ef0ac8..41f4d3c9 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -199,6 +199,11 @@ "source": "./plugins/fetch", "description": "Fetch web content in multiple formats - HTML, JSON, plain text, Markdown, readable articles, and YouTube transcripts" }, + { + "name": "claude-code-docs", + "source": "./plugins/claude-code-docs", + "description": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs" + }, { "name": "semble", "source": "./plugins/semble", diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ba8b9e65..89262474 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -54,6 +54,7 @@ "plugins/graphite": "2.3.0", "plugins/bun": "1.4.0", "plugins/portone": "1.3.0", + "plugins/claude-code-docs": "1.0.0", "plugins/claude-md-management": "1.1.0", "plugins/cubic": "1.1.0", "plugins/fetch": "1.2.0", diff --git a/README.md b/README.md index bc03d632..7ff8ef22 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,6 @@ Skills for the Cloudflare developer platform: Workers, Durable Objects, Agents S **Install:** `/plugin install cloudflare@pleaseai` | **Repository:** [cloudflare/skills](https://github.com/cloudflare/skills) -#### Claude Code Docs -Fetch Claude Code docs as markdown — rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs. - -**Install:** `/plugin install claude-code-docs@pleaseai` | **Repository:** [pleaseai/claude-code-docs](https://github.com/pleaseai/claude-code-docs) - #### Run Verify Run and verify code changes by driving the real app — the `run`, `verify`, and `run-skill-generator` skills, generalized for Claude Code, Codex, and Antigravity. @@ -498,6 +493,12 @@ Token-efficient browser automation CLI for coding agents — navigate, interact, **Install:** `/plugin install playwright-cli@pleaseai` | **Source:** [plugins/playwright-cli](https://github.com/pleaseai/claude-code-plugins/tree/main/plugins/playwright-cli) +#### Claude Code Docs + +Fetch Claude Code docs as markdown — rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs. The docs mirror itself stays at [pleaseai/claude-code-docs](https://github.com/pleaseai/claude-code-docs). + +**Install:** `/plugin install claude-code-docs@pleaseai` | **Source:** [plugins/claude-code-docs](https://github.com/pleaseai/claude-code-plugins/tree/main/plugins/claude-code-docs) + ## Quick Start The fastest way to get started — install the marketplace and let the plugin recommender auto-detect what you need: @@ -600,7 +601,6 @@ Once the marketplace is added (or files copied), the following plugins are avail /plugin install vercel@pleaseai /plugin install gemini@pleaseai /plugin install cloudflare@pleaseai -/plugin install claude-code-docs@pleaseai /plugin install firecrawl@pleaseai /plugin install ask@pleaseai @@ -683,6 +683,7 @@ Once the marketplace is added (or files copied), the following plugins are avail /plugin install tosspayments@pleaseai /plugin install vercel-sandbox@pleaseai /plugin install playwright-cli@pleaseai +/plugin install claude-code-docs@pleaseai ``` ## What Are Claude Code Plugins? diff --git a/plugins/claude-code-docs/.claude-plugin/plugin.json b/plugins/claude-code-docs/.claude-plugin/plugin.json new file mode 100644 index 00000000..013d1e34 --- /dev/null +++ b/plugins/claude-code-docs/.claude-plugin/plugin.json @@ -0,0 +1,18 @@ +{ + "name": "claude-code-docs", + "version": "1.0.0", + "description": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "author": { + "name": "PleaseAI", + "url": "https://github.com/pleaseai" + }, + "homepage": "https://github.com/pleaseai/claude-code-docs", + "license": "MIT", + "keywords": [ + "claude-code", + "docs", + "markdown", + "webfetch", + "hooks" + ] +} diff --git a/plugins/claude-code-docs/.codex-plugin/plugin.json b/plugins/claude-code-docs/.codex-plugin/plugin.json new file mode 100644 index 00000000..b764a72a --- /dev/null +++ b/plugins/claude-code-docs/.codex-plugin/plugin.json @@ -0,0 +1,32 @@ +{ + "name": "claude-code-docs", + "version": "1.0.0", + "description": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "author": { + "name": "PleaseAI", + "url": "https://github.com/pleaseai" + }, + "interface": { + "displayName": "Claude Code Docs", + "shortDescription": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "longDescription": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "developerName": "PleaseAI", + "category": "Tooling", + "capabilities": [ + "Skill" + ], + "defaultPrompt": [ + "Help me use Claude Code Docs for my current task." + ], + "websiteURL": "https://github.com/pleaseai/claude-code-docs" + }, + "homepage": "https://github.com/pleaseai/claude-code-docs", + "license": "MIT", + "keywords": [ + "claude-code", + "docs", + "markdown", + "webfetch", + "hooks" + ] +} diff --git a/plugins/claude-code-docs/.cursor-plugin/plugin.json b/plugins/claude-code-docs/.cursor-plugin/plugin.json new file mode 100644 index 00000000..4950ba94 --- /dev/null +++ b/plugins/claude-code-docs/.cursor-plugin/plugin.json @@ -0,0 +1,23 @@ +{ + "name": "claude-code-docs", + "displayName": "Claude Code Docs", + "description": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "version": "1.0.0", + "author": { + "name": "PleaseAI" + }, + "category": "Tooling", + "homepage": "https://github.com/pleaseai/claude-code-docs", + "license": "MIT", + "keywords": [ + "claude-code", + "docs", + "markdown", + "webfetch", + "hooks" + ], + "tags": [ + "hooks", + "docs" + ] +} diff --git a/plugins/claude-code-docs/hooks.json b/plugins/claude-code-docs/hooks.json new file mode 100644 index 00000000..da6a7411 --- /dev/null +++ b/plugins/claude-code-docs/hooks.json @@ -0,0 +1,17 @@ +{ + "description": "Rewrites code.claude.com/docs page URLs to their .md source so WebFetch gets clean markdown instead of the HTML app shell", + "hooks": { + "PreToolUse": [ + { + "matcher": "WebFetch", + "hooks": [ + { + "type": "command", + "command": "bash \"./hooks/rewrite-docs-url.sh\"", + "timeout": 5 + } + ] + } + ] + } +} diff --git a/plugins/claude-code-docs/hooks/hooks.json b/plugins/claude-code-docs/hooks/hooks.json new file mode 100644 index 00000000..f4dbced7 --- /dev/null +++ b/plugins/claude-code-docs/hooks/hooks.json @@ -0,0 +1,17 @@ +{ + "description": "Rewrites code.claude.com/docs page URLs to their .md source so WebFetch gets clean markdown instead of the HTML app shell", + "hooks": { + "PreToolUse": [ + { + "matcher": "WebFetch", + "hooks": [ + { + "type": "command", + "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/rewrite-docs-url.sh\"", + "timeout": 5 + } + ] + } + ] + } +} diff --git a/plugins/claude-code-docs/hooks/rewrite-docs-url.sh b/plugins/claude-code-docs/hooks/rewrite-docs-url.sh new file mode 100755 index 00000000..1f6e8950 --- /dev/null +++ b/plugins/claude-code-docs/hooks/rewrite-docs-url.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# PreToolUse hook for WebFetch: rewrite Claude Code docs page URLs to their +# markdown source (https://code.claude.com/docs/en/agents -> .../agents.md). +# Every docs page serves a clean markdown twin at .md; fetching it skips +# the HTML app shell entirely. Silent exit 0 = no opinion, normal flow. + +input=$(cat) +url=$(jq -r '.tool_input.url // empty' <<<"$input") +[ -z "$url" ] && exit 0 + +case "$url" in + https://code.claude.com/docs/*) ;; + *) exit 0 ;; +esac + +# Drop fragment and query: hooks#pretooluse-decision-control -> hooks +path="${url%%#*}" +path="${path%%\?*}" +path="${path%/}" + +# Already a raw file (page .md, llms.txt, images, ...) - leave untouched. +# Check the last path segment only; the domain always contains dots. +case "${path##*/}" in + *.*) exit 0 ;; +esac + +# Only rewrite real pages under a locale segment (/docs//), +# not the docs root itself +rest="${path#https://code.claude.com/docs/}" +case "$rest" in + */*) ;; + *) exit 0 ;; +esac + +jq --arg url "${path}.md" '{ + hookSpecificOutput: { + hookEventName: "PreToolUse", + permissionDecision: "allow", + permissionDecisionReason: ("Rewrote Claude Code docs URL to markdown source: " + $url), + updatedInput: (.tool_input | .url = $url) + } +}' <<<"$input" diff --git a/plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh b/plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh new file mode 100755 index 00000000..3f78d419 --- /dev/null +++ b/plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Tests for rewrite-docs-url.sh. Run: bash hooks/rewrite-docs-url.test.sh +set -u +cd "$(dirname "$0")" +pass=0 fail=0 + +run() { + echo "$1" | bash ./rewrite-docs-url.sh +} + +expect_rewrite() { # input-url expected-url + out=$(run "{\"tool_name\":\"WebFetch\",\"tool_input\":{\"url\":\"$1\",\"prompt\":\"p\"}}") + got=$(jq -r '.hookSpecificOutput.updatedInput.url // empty' <<<"$out") + if [ "$got" = "$2" ]; then pass=$((pass+1)); else fail=$((fail+1)); echo "FAIL: $1 -> '$got' (expected $2)"; fi +} + +expect_silent() { # input-url + out=$(run "{\"tool_name\":\"WebFetch\",\"tool_input\":{\"url\":\"$1\",\"prompt\":\"p\"}}") + if [ -z "$out" ]; then pass=$((pass+1)); else fail=$((fail+1)); echo "FAIL: $1 should pass through, got: $out"; fi +} + +expect_rewrite "https://code.claude.com/docs/en/agents" "https://code.claude.com/docs/en/agents.md" +expect_rewrite "https://code.claude.com/docs/en/agents/" "https://code.claude.com/docs/en/agents.md" +expect_rewrite "https://code.claude.com/docs/en/hooks#pretooluse-decision-control" "https://code.claude.com/docs/en/hooks.md" +expect_rewrite "https://code.claude.com/docs/en/agent-sdk/python" "https://code.claude.com/docs/en/agent-sdk/python.md" +expect_rewrite "https://code.claude.com/docs/en/hooks?foo=bar" "https://code.claude.com/docs/en/hooks.md" + +expect_silent "https://code.claude.com/docs/en/agents.md" +expect_silent "https://code.claude.com/docs/llms.txt" +expect_silent "https://code.claude.com/docs/llms-full.txt" +expect_silent "https://code.claude.com/docs/en" +expect_silent "https://code.claude.com/docs" +expect_silent "https://example.com/docs/en/agents" +expect_silent "https://docs.claude.com/en/api/overview" + +# prompt must survive updatedInput (it replaces the whole input object) +out=$(run '{"tool_name":"WebFetch","tool_input":{"url":"https://code.claude.com/docs/en/agents","prompt":"summarize"}}') +got=$(jq -r '.hookSpecificOutput.updatedInput.prompt' <<<"$out") +if [ "$got" = "summarize" ]; then pass=$((pass+1)); else fail=$((fail+1)); echo "FAIL: prompt lost: $got"; fi + +echo "passed: $pass, failed: $fail" +[ "$fail" -eq 0 ] diff --git a/plugins/claude-code-docs/plugin.json b/plugins/claude-code-docs/plugin.json new file mode 100644 index 00000000..96f7ed0e --- /dev/null +++ b/plugins/claude-code-docs/plugin.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://antigravity.google/schemas/v1/plugin.json", + "name": "claude-code-docs", + "version": "1.0.0", + "description": "Fetch Claude Code docs as markdown - rewrites code.claude.com/docs page URLs to their .md source before WebFetch runs", + "author": { + "name": "PleaseAI", + "url": "https://github.com/pleaseai" + }, + "homepage": "https://github.com/pleaseai/claude-code-docs", + "license": "MIT", + "keywords": [ + "claude-code", + "docs", + "markdown", + "webfetch", + "hooks" + ] +} diff --git a/plugins/claude-code-docs/skills/claude-code-docs/SKILL.md b/plugins/claude-code-docs/skills/claude-code-docs/SKILL.md new file mode 100644 index 00000000..a5b33f14 --- /dev/null +++ b/plugins/claude-code-docs/skills/claude-code-docs/SKILL.md @@ -0,0 +1,69 @@ +--- +name: claude-code-docs +description: Answer questions about Claude Code (features, hooks, plugins, skills, MCP, Agent SDK, settings, CLI) from the official docs. Uses the ask CLI to resolve a version-pinned local mirror and csp for semantic search, falling back to grep and WebFetch. Use when the user asks how Claude Code works, what a configuration field does, or whether Claude Code supports something. +argument-hint: [question] +arguments: [question] +--- + +Answer this question about Claude Code using the official documentation: + +**$question** + +## How to find the answer + +Work through these steps, falling back gracefully when a tool is missing. + +### 1. Resolve the docs mirror + +```bash +DOCS="$(ask src github:pleaseai/claude-code-docs)/docs" +``` + +`ask src` prints the root of a cached checkout of the docs mirror (clones on first use). If the `ask` CLI is not on PATH, run it via npx/bunx instead: + +```bash +DOCS="$(npx -y @pleaseai/ask src github:pleaseai/claude-code-docs)/docs" +``` + +Only fall back to step 4 (WebFetch) when neither works, such as offline sandboxes without npm registry access. + +### 2. Search for relevant pages + +Prefer semantic search with csp, scoped to the per-page markdown: + +```bash +csp search "$question" "$DOCS" --content docs --top-k 8 +``` + +Or equivalently via ask (requires csp on PATH): + +```bash +ask search github:pleaseai/claude-code-docs "$question" --content docs --top-k 8 +``` + +If csp is not on PATH, run it via npx/bunx: + +```bash +npx -y @pleaseai/csp search "$question" "$DOCS" --content docs --top-k 8 +``` + +If that fails too, fall back to grep over the mirror — search for 2-3 distinct keyword variants, not one long phrase: + +```bash +grep -ril "" "$DOCS" +``` + +The manifest at `$DOCS/../llms.txt` lists every page with a one-line summary; reading it is a fast way to shortlist pages when keyword search is noisy. + +### 3. Read and answer + +Read the top matching pages (whole pages — they are small). Ground every claim in what the pages actually say: + +- Answer in the user's language; keep code identifiers, field names, and flags verbatim. +- Cite each source page with its canonical URL: a mirror file `$DOCS/hooks.md` corresponds to `https://code.claude.com/docs/en/hooks`. +- Quote exact field names, JSON shapes, and version requirements (`min-version` markers) when they matter. +- If the docs do not answer the question, say so explicitly — do not fill gaps from memory. + +### 4. Fallback: WebFetch + +If the `ask` CLI is unavailable, fetch `https://code.claude.com/docs/llms.txt`, pick the relevant page URLs from the manifest, and fetch each as `.md` (this plugin's hook rewrites page URLs to `.md` automatically). Then answer as in step 3. diff --git a/release-please-config.json b/release-please-config.json index f9173b7d..b78610d8 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -831,6 +831,32 @@ } ] }, + "plugins/claude-code-docs": { + "release-type": "simple", + "component": "claude-code-docs", + "extra-files": [ + { + "type": "json", + "path": ".claude-plugin/plugin.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": ".codex-plugin/plugin.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "plugin.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": ".cursor-plugin/plugin.json", + "jsonpath": "$.version" + } + ] + }, "plugins/claude-md-management": { "release-type": "simple", "component": "claude-md-management",