From 4a189f543e787d532edfc0412e863e9ef5456c06 Mon Sep 17 00:00:00 2001 From: Minsu Lee <1964421+amondnet@users.noreply.github.com> Date: Fri, 30 Oct 2026 15:42:56 +0900 Subject: [PATCH 1/3] fix(claude-code-docs): vendor plugin into the marketplace Move the plugin code (skills/, hooks/, .claude-plugin/) from pleaseai/claude-code-docs@72ef109 into plugins/claude-code-docs and switch the marketplace source to the local path. Installing the plugin, or any plugin that depends on it, no longer clones the 44 MB docs mirror. The skill already resolves the docs through `ask src`, so the mirror repo stays as is. --- .agents/plugins/marketplace.json | 4 +- .claude-plugin/marketplace.json | 5 +- .cursor-plugin/marketplace.json | 5 ++ .release-please-manifest.json | 1 + README.md | 11 +-- .../.claude-plugin/plugin.json | 18 +++++ .../.codex-plugin/plugin.json | 32 +++++++++ .../.cursor-plugin/plugin.json | 23 +++++++ plugins/claude-code-docs/hooks.json | 17 +++++ plugins/claude-code-docs/hooks/hooks.json | 17 +++++ .../hooks/rewrite-docs-url.sh | 42 +++++++++++ .../hooks/rewrite-docs-url.test.sh | 42 +++++++++++ plugins/claude-code-docs/plugin.json | 19 +++++ .../skills/claude-code-docs/SKILL.md | 69 +++++++++++++++++++ release-please-config.json | 26 +++++++ 15 files changed, 320 insertions(+), 11 deletions(-) create mode 100644 plugins/claude-code-docs/.claude-plugin/plugin.json create mode 100644 plugins/claude-code-docs/.codex-plugin/plugin.json create mode 100644 plugins/claude-code-docs/.cursor-plugin/plugin.json create mode 100644 plugins/claude-code-docs/hooks.json create mode 100644 plugins/claude-code-docs/hooks/hooks.json create mode 100755 plugins/claude-code-docs/hooks/rewrite-docs-url.sh create mode 100755 plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh create mode 100644 plugins/claude-code-docs/plugin.json create mode 100644 plugins/claude-code-docs/skills/claude-code-docs/SKILL.md diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 7821e12a..f177746b 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 45d417ab..a7920bcb 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 7bb9ddf0..01bd203a 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 b418b940..754089fe 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 ee2080aa..36cf8617 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,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. @@ -492,6 +487,12 @@ End-to-end typesafe APIs with oRPC v2 — the core `os` builder, routers, middle **Install:** `/plugin install orpc@pleaseai` | **Source:** [plugins/orpc](https://github.com/pleaseai/claude-code-plugins/tree/main/plugins/orpc) +#### 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: 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..6dc2591d --- /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..fc0a3422 --- /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 e18707a2..b07696cb 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", From 7c18b6bca7c8f5b96c6b57162bbacf044138bf82 Mon Sep 17 00:00:00 2001 From: Minsu Lee <1964421+amondnet@users.noreply.github.com> Date: Fri, 30 Oct 2026 15:54:16 +0900 Subject: [PATCH 2/3] fix(claude-code-docs): quote ${CLAUDE_PLUGIN_ROOT} in the WebFetch hook command An unquoted plugin root splits into several words when the install path contains a space, so bash fails to find the script and the hook never runs. The Antigravity hooks.json is regenerated by multi-format. --- plugins/claude-code-docs/hooks.json | 2 +- plugins/claude-code-docs/hooks/hooks.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/claude-code-docs/hooks.json b/plugins/claude-code-docs/hooks.json index 6dc2591d..da6a7411 100644 --- a/plugins/claude-code-docs/hooks.json +++ b/plugins/claude-code-docs/hooks.json @@ -7,7 +7,7 @@ "hooks": [ { "type": "command", - "command": "bash ./hooks/rewrite-docs-url.sh", + "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 index fc0a3422..f4dbced7 100644 --- a/plugins/claude-code-docs/hooks/hooks.json +++ b/plugins/claude-code-docs/hooks/hooks.json @@ -7,7 +7,7 @@ "hooks": [ { "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/rewrite-docs-url.sh", + "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/rewrite-docs-url.sh\"", "timeout": 5 } ] From 4aee077039b4df6c8bce95734b9d85aac0cd999f Mon Sep 17 00:00:00 2001 From: Minsu Lee <1964421+amondnet@users.noreply.github.com> Date: Mon, 2 Nov 2026 10:27:46 +0900 Subject: [PATCH 3/3] docs(readme): list claude-code-docs under built-in plugins in the install block --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96e1d842..7ff8ef22 100644 --- a/README.md +++ b/README.md @@ -601,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 @@ -684,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?