cc-vision-hook
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 7 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Claude Code hook toolkit that gives vision-blind models a text description of pasted/tool-produced images.
cc-vision-hook
Give vision-blind Claude Code models eyes — without touching your prompt.
cvh is a local-only Claude Code Hook toolkit. When you paste an image, or a tool (Read / Bash / MCP) produces a screenshot, cvh sends it to a vision model of your choice and injects the description back into Claude Code's context as additionalContext — so a model that would otherwise silently ignore the image can actually "see" it.
Why
Not every model behind Claude Code understands images. Depending on the backend, an unsupported image request fails in one of two very different ways:
| Failure mode | What happens | Can cvh fix it? |
|---|---|---|
| Silently ignoring | The API call succeeds (HTTP 200), but the model never actually looks at the image — it guesses, hallucinates, or just says "I can't see the image." | ✅ Yes — this is exactly what cvh is built for |
| Protocol-level hard rejection | The API call fails outright (e.g. 404 No endpoints found that support image input), and the entire turn fails, text included. |
❌ No — see Scope & limitations |
cvh targets the first case. It never touches the original image content block — it only appends a text description generated by a vision model you configure, via Claude Code's additionalContext hook output. That's the whole trick: no schema surgery, no risky content replacement, just an honest text description sitting next to the image the main model can't parse.
✅ Verified against a real Claude Code session. A model that silently ignores images was tested with and without
cvh: without it, it guessed the wrong color for a test image; withcvhinstalled, the hook transcript showsadditionalContextbeing injected and the model answering correctly. SeeCHANGELOG.mdfor details.
How it works
flowchart LR
A["User pastes image /<br/>tool returns screenshot"] --> B{cvh enabled?}
B -- no --> Z["passthrough, no-op"]
B -- yes --> C["Extract image bytes<br/>(UserPromptSubmit / PostToolUse)"]
C --> D{"Cached by<br/>content hash?"}
D -- hit --> F
D -- miss --> E["Ask your vision model<br/>(via AI SDK)"]
E --> F["additionalContext<br/>injected into Claude Code"]
UserPromptSubmithook scans~/.claude/image-cache/<session_id>/for newly pasted images.PostToolUsehook (matcher: "*") runs a generic recursive extractor over any tool'stool_response— verified against three real, structurally different shapes:Read's discriminated object, MCP's content-block array, andBash/PowerShell's flatisImage+ data-URI string.- Both hooks only ever output
additionalContext— neverupdatedToolOutput. This keepscvhsimple and safe: no per-tool schema replication, no risk of a silently-dropped hook output because the replacement shape didn't match. - Vision inference goes through the Vercel AI SDK, so you can point
cvhat OpenAI (Chat Completions or Responses), Anthropic, or Gemini — or any OpenAI/Anthropic-compatible gateway. - Descriptions are cached on disk by image content hash (
~/.claude/cc-vision-hook/cache/), shared globally, with a 7-day lazy-expiring TTL — the same image is only ever described once, no matter where it came from.
Scope & limitations
cvh only helps with models that silently ignore images. If your model hard-rejects image input at the protocol level (the request itself fails), cvh cannot help — it never replaces or removes the original image content block, so the upstream will still see (and reject) it. Run cvh doctor or send a manual test request to figure out which category your model falls into before enabling cvh.
Other known limitations:
- Hard-rejection models are out of scope (see above).
- Support for "user pastes an image" relies on an unofficial implementation detail of Claude Code (
~/.claude/image-cache/directory scanning). This could break in a future Claude Code release;cvhdoes not attempt version detection or graceful degradation. cvhdoes not auto-detect model capabilities. It's a plainenable/disableswitch — you decide when to turn it on.- Claude Code only. No support for other agent hosts.
- Images are sent to whichever third-party vision provider you configure. You are responsible for that data flow — review your provider's data handling policy if your screenshots may contain sensitive information.
Install
npm install -g cc-vision-hook
cvh install # create config + register hooks (idempotent)
cvh config set provider anthropic # or: oai / responses / gemini
cvh config set model <your-vision-model>
cvh config set apiKey <your-api-key>
cvh doctor # sanity-check config + connectivity
cvh enable
Commands
| Command | Description |
|---|---|
cvh install |
Create config + register hooks (idempotent, safe to re-run) |
cvh uninstall [--purge] |
Remove hook registration; --purge also deletes config and cache |
cvh enable / cvh disable |
The one and only runtime switch |
cvh status |
Show current state, hook registration, cache stats |
cvh doctor |
Self-check config / hooks / vision model connectivity, plus a boundary reminder |
cvh config get / cvh config set <key> <value> |
Read/write config (provider/model/baseUrl/apiKey/timeoutMs/maxTokens) |
cvh test-image <path> |
Manually verify the pipeline: local image → vision model → description |
Every command supports --json output for scripting.
Configuration
~/.claude/cc-vision-hook.json:
{
"enabled": true,
"provider": "oai",
"model": "gpt-4o-mini",
"baseUrl": "https://api.openai.com/v1",
"apiKey": "sk-...",
"timeoutMs": 45000,
"maxTokens": 1200,
"cache": { "ttlDays": 7 }
}
The API key is stored in plaintext; the file permission is automatically set to 0600 (owner read/write only).
Environment variable overrides (take priority over the config file): CVH_ENABLED / CVH_PROVIDER / CVH_MODEL / CVH_BASE_URL / CVH_API_KEY / CVH_TIMEOUT_MS / CVH_MAX_TOKENS.
Roadmap
-
cvh init— interactive setup wizard. - MCP tools (
vision_ask,vision_describe_image,vision_describe_data_url) so an agent can follow up on a previously seen image. The on-disk cache already stores everything needed — the MCP surface just hasn't been wired up yet.
Troubleshooting
- Installed but nothing happens — Claude Code reads
$HOME/.claude/settings.json(not$HOMEitself). Make sure the pathcvh installwrote to matches the one Claude Code actually loads. Runcvh statusand confirm both hooks aretrueandenabledistrue. doctorreports a connectivity failure — runcvh test-image <local-image>first to isolate whether the problem is in the vision-model call itself or in hook wiring.- The model errors out entirely / the whole turn fails when an image is involved — you're using a hard-rejection model.
cvhcannot help here; see Scope & limitations.
Development
bun install
bun run typecheck # tsc --noEmit
bun run build # emit dist/
bun test # fixture-driven unit tests, no real network calls
For local/integration testing, override ~/.claude with the CVH_CLAUDE_HOME environment variable so you never touch your real Claude Code configuration:
export CVH_CLAUDE_HOME=/tmp/some-isolated-dir/.claude
node dist/cli.js install
When wiring this up against a real Claude Code session, set CVH_CLAUDE_HOME to $HOME/.claude (not $HOME itself), and also set HOME=<isolated dir> so the claude process reads the same settings.json.
Contributing
Issues and PRs are welcome. Please run bun run ci (typecheck + test + build) before submitting.
Contributions that add or change behavior should include a changeset:
bun run changeset
Releasing
Releases are published to npm via Trusted Publishing (OIDC, no long-lived tokens) whenever a v* tag is pushed. See docs/releasing.md for the full process and docs/release-checklist.md for the pre-flight checklist.
License
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found