Repository navigation
fix(claude-code-docs): vendor plugin into the marketplace #297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4a189f5
7c18b6b
a468f56
4aee077
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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", | ||
|
amondnet marked this conversation as resolved.
Resolved
|
||
| "license": "MIT", | ||
| "keywords": [ | ||
| "claude-code", | ||
| "docs", | ||
| "markdown", | ||
| "webfetch", | ||
| "hooks" | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <page>.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 | ||
|
Check failure on line 9 in plugins/claude-code-docs/hooks/rewrite-docs-url.sh
|
||
|
|
||
| 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 | ||
|
Check failure on line 23 in plugins/claude-code-docs/hooks/rewrite-docs-url.sh
|
||
| *.*) exit 0 ;; | ||
| esac | ||
|
|
||
| # Only rewrite real pages under a locale segment (/docs/<locale>/<page...>), | ||
| # not the docs root itself | ||
| rest="${path#https://code.claude.com/docs/}" | ||
| case "$rest" in | ||
| */*) ;; | ||
| *) exit 0 ;; | ||
| esac | ||
|
amondnet marked this conversation as resolved.
Resolved
|
||
|
|
||
| jq --arg url "${path}.md" '{ | ||
| hookSpecificOutput: { | ||
| hookEventName: "PreToolUse", | ||
| permissionDecision: "allow", | ||
|
amondnet marked this conversation as resolved.
Resolved
|
||
| permissionDecisionReason: ("Rewrote Claude Code docs URL to markdown source: " + $url), | ||
| updatedInput: (.tool_input | .url = $url) | ||
| } | ||
| }' <<<"$input" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
Check warning on line 8 in plugins/claude-code-docs/hooks/rewrite-docs-url.test.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 | ||
|
Check warning on line 14 in plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh
|
||
| } | ||
|
|
||
| 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 | ||
|
Check failure on line 19 in plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh
|
||
| } | ||
|
|
||
| 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 | ||
|
Check failure on line 39 in plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh
|
||
|
|
||
| echo "passed: $pass, failed: $fail" | ||
| [ "$fail" -eq 0 ] | ||
|
Check failure on line 42 in plugins/claude-code-docs/hooks/rewrite-docs-url.test.sh
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
|
amondnet marked this conversation as resolved.
Resolved
|
||
| ``` | ||
|
|
||
| `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 "<keyword>" "$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 `<page-url>.md` (this plugin's hook rewrites page URLs to `.md` automatically). Then answer as in step 3. | ||
Uh oh!
There was an error while loading. Please reload this page.