Cross-session WebFetch cache for Claude Code. WebFetches disappear after 15 minutes — claude-webcache makes them persist.
claude-webcache defines 9 tools with complete input schemas and descriptions. Naming is clear and verb-driven (cached_*, cache_*). Descriptions are detailed (100-200 chars) and explain WHEN to use each tool. However, output schemas are entirely undocumented, LLMs cannot predict what fields to expect from cache_stats, cache_list, or cache_warm. Parameter descriptions are present but lack constraints (e.g., cache_list.limit has no min/max; cache_clear.older_than_days has no range). Error handling is minimal, no recovery guidance or actionable error messages. Security is weak: cache_store accepts arbitrary 'output' text with no validation; cache_clear requires a string confirmation 'YES' rather than a boolean, inviting prompt injection. No tool annotations (readOnlyHint, destructiveHint) despite clear risk levels.
Bulk-delete cache entries in the current namespace. Provide either older_than_days (safe, partial) OR confirm:"YES" (full wipe, dangerous). Returns number of entries deleted.
Delete all cache entries for a specific URL in the current namespace (across all prompts). Returns the number of entries deleted.
List recently cached URLs in the current namespace (most recent first).
Force re-fetch of a URL: invalidates the existing cached entry and returns "[CACHE_MISS] <url>" so the assistant triggers WebFetch. Use when you know the upstream content changed.
Return cache statistics for the current namespace: total entries, total hits, miss count, hit rate, db size in bytes, evicted count, oversize_skipped count, last hook error timestamp, top 5 URLs by hit count.
Store a WebFetch result in the cache after a CACHE_MISS. Pass the original url, prompt, and the output text returned by WebFetch.
Output schemas completely undocumented. cache_stats, cache_list, cache_warm, and cache_store return values are not specified. LLMs cannot plan downstream operations or extract required fields without guessing.
No parameter constraints (min/max, enums, patterns). cache_list.limit and cache_clear.older_than_days lack bounds; cache_clear.confirm accepts a string 'YES' instead of a boolean, inviting prompt injection and ambiguous parsing.
No tool annotations. cache_invalidate and cache_clear are destructive but lack destructiveHint; cached_fetch and cache_list are read-only but lack readOnlyHint. LLMs cannot distinguish safe from risky operations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 67 | 2026-07-28+ | v2 |
Batch cache pre-flight check. Pass either {entries: [{url, prompt}, ...]} for per-entry prompts OR {urls: [...], prompt} to apply the same prompt to all URLs. Returns {hits, misses, invalid} arrays — pipeline then WebFetches only misses, saving N round-trips.
Look up a URL+prompt pair in the local WebFetch cache. Returns cached output if present (instant), or "[CACHE_MISS] <url>" if not. On CACHE_MISS, call WebFetch, then call cache_store with the result. Same URL+prompt across sessions hits the cache.
Look up a WebSearch query in the local cache ('websearch' namespace, short TTL). Returns cached results if a fresh entry exists, or "[CACHE_MISS] <query>" if not. On CACHE_MISS, run WebSearch — the PostToolUse hook stores the result automatically.
Error handling lacks recovery guidance. No actionable error messages (e.g., 'Invalid URL: must start with http:// or https://. Try cache_list to see valid cached URLs.'). Errors return bare text with no classification (retryable vs fatal).
cache_store accepts arbitrary 'output' text with no validation or size limits. No protection against storing malicious or oversized payloads. cache_clear confirmation uses string 'YES' instead of boolean, risking prompt injection.