Save the web page you are viewing as a clean PDF or DOCX, locally, using your own Vision LLM API key.
clipcv is an open-source Chrome extension (Manifest V3) that converts a single web page you are currently viewing into a structured PDF or DOCX file. Extraction is performed by a Vision LLM endpoint you configure yourself — bring your own key (BYOK). Everything runs in your browser. The clipcv project operates no server.
- Highlights
- How it works
- Install
- BYOK setup
- Privacy
- Use responsibly
- Tech stack
- Project status
- Build from source
- Contributing
- Releasing
- License
| One-click capture | A small floating button on the active page triggers a single-page, user-initiated capture. No bulk runs, no scripted automation. |
| Vision LLM extraction | A downsampled viewport screenshot and the visible DOM are sent to the endpoint you configured. The model returns structured profile data as JSON, validated by zod. |
| PDF or DOCX output | Renders the structured data to a clean PDF (via pdf-lib) or DOCX (via docx). Pick PDF, DOCX, or both in settings. |
| BYOK, any OpenAI-compatible endpoint | Supply your own provider, base URL, model, and API key. Works with OpenAI, OpenRouter, qwen-vl on a compatibility shim, vLLM, llama.cpp, and any endpoint implementing /chat/completions with image_url content. |
| At-rest encryption | API keys are encrypted with WebCrypto AES-GCM and stored in chrome.storage.local. Plaintext keys are never persisted. The encryption key never leaves your browser. |
| No telemetry | No analytics SDK, no error reporting, no update beacons. The only outbound HTTP request is the one to the LLM endpoint you configured. |
| MIT licensed | No closed-source server component, no proxy, no bundled API key. |
┌──────────────┐ 1. click ┌──────────────────┐
│ Active tab │ ───────────────▶ │ Floating button │
└──────────────┘ │ (content script) │
└────────┬─────────┘
│ 2. capture-request
▼
┌────────────────────────────────────────────────────┐
│ Service worker (MV3, ephemeral) │
│ • chrome.tabs.captureVisibleTab → PNG (≤1280px) │
│ • DOM serialized, scripts/styles stripped │
│ • payload capped at 1 MB │
└────────────────────────────────────────────────────┘
│ 3. POST /chat/completions
▼
┌──────────────────────────┐
│ Your Vision LLM endpoint │
│ (the one you configured) │
└──────────────┬───────────┘
│ 4. JSON
▼
┌──────────────────────────────┐
│ zod validates → render PDF │
│ or DOCX via pdf-lib / docx │
└──────────────┬───────────────┘
│ 5. browser download
▼
Local file on your disk
What you do with the downloaded file is up to you. clipcv does not specify a destination or any downstream use for the file.
Listing pending review. Once published, the link will appear here.
No tagged release yet. Once the first v* tag is pushed, the release workflow will attach a signed .crx and a .zip to the Releases page automatically — drag the .crx onto chrome://extensions (Developer mode enabled) to install. Until then, use the unpacked path below.
See Build from source.
On first launch the extension shows a one-time disclaimer modal. You must accept the disclaimer before any capture works. Acceptance is scoped to the current extension version; re-accept on upgrade.
clipcv does not bundle a default API key, free tier, or proxy. You configure your own LLM provider before the extension will run a capture.
- Open the options page: right-click the toolbar icon → Options, or
chrome://extensions→ clipcv → Details → Extension options. - Pick a provider:
- OpenAI — the OpenAI API.
- OpenRouter — OpenRouter as a unified gateway to many vision models.
- OpenAI-compatible custom — any endpoint implementing the OpenAI
/chat/completionsshape with visionimage_urlcontent (qwen-vl on a compatibility shim, vLLM, local llama.cpp servers, etc.).
- Fill in base URL (e.g.
https://api.openai.com/v1), model (a vision-capable model id offered by your provider), and your API key. - Pick a default output format: PDF, DOCX, or both.
- Click Test connection to issue a 1-token request and verify credentials. Errors are surfaced as typed codes —
auth_failed,timeout,model_not_found,bad_request,rate_limited,unknown— and any string matchingsk-…orBearer …is scrubbed before display. - Click Save. Your API key is encrypted at rest with WebCrypto AES-GCM and stored in
chrome.storage.local.
You can revoke disclaimer acceptance from the same options page; the disclaimer modal will reappear on next popup open.
See PRIVACY.md. In summary:
- No clipcv server. No analytics, no telemetry, no error reporting.
- Your captures travel directly from your browser to the LLM endpoint you configured. The contractual terms with that provider govern how it may use the data you send.
- All extension state lives in your browser. Nothing is mirrored off-device by clipcv.
- API keys are encrypted at rest. WebCrypto AES-GCM, per-install random 256-bit key. Plaintext is never persisted; secret-shaped strings are scrubbed from any error surfaced to the UI.
You are responsible for complying with the terms of service of every website you use clipcv on. clipcv is a single-page, single-click, user-initiated tool. Do not use it for bulk extraction, scripted runs, or to access content you are not authorized to access. See DISCLAIMER.md.
| Layer | Choice |
|---|---|
| Build | Vite + @crxjs/vite-plugin (MV3) |
| UI | React 18 + TypeScript (strict mode) |
| Styling | Tailwind CSS, scoped via shadow DOM in content scripts |
| Schema | zod — single source of truth for the LLM response contract |
| pdf-lib | |
| DOCX | docx |
| Storage | chrome.storage.local + WebCrypto AES-GCM |
| Tests | vitest — 74 unit tests, 8 suites |
| CI | GitHub Actions — tag → build → signed .crx + .zip draft Release |
No backend. No analytics SDK. No npm-based LLM SDKs — calls go through fetch directly so the wire format is auditable from the source tree.
| Source version | 0.1.0 (15-story MVP, untagged) |
| Releases | No tag pushed yet — install via npm run build + unpacked load |
| Manifest | V3 |
| Minimum Chrome | 116 |
| Tests | 74 / 74 passing |
| Lines of code | ~2.8K production, ~1.2K test |
| Web Store | Listing in preparation |
git clone https://github.com/JamesbbBriz/clipcv.git
cd clipcv
npm install
npm run buildThen in Chrome:
- Open
chrome://extensions. - Enable Developer mode.
- Click Load unpacked and select the generated
dist/folder.
npm run typecheck # tsc --noEmit, strict mode
npm run test # vitest run, 74 tests
npm run build # vite build → dist/
npm run package # produce release/clipcv-v<version>.{zip,crx}clipcv is MIT-licensed and welcomes contributions. Before opening a PR:
- Fork the repository and create a feature branch from
main. - Run
npm install, thennpm run buildto confirm the extension builds cleanly. - Pass all quality gates (
typecheck,test,build). - Keep the change small and scoped to one logical concern. Use a Conventional Commits prefix (
feat:/fix:/chore:/docs:/refactor:/test:/ci:).
- Inline scripts,
eval, theFunction(...)constructor, or any form of remote code execution. Manifest V3 forbids them and so does this project. - A clipcv-operated server, proxy, or any non-LLM outbound HTTP request.
- Hardcoded URLs, CSS selectors, or DOM probes for any specific website. Extraction must remain a pure prompt-driven Vision LLM call — the same code path runs on every page.
- Analytics, error reporting, or telemetry of any kind.
- User-facing copy (README, popup UI, options page, generated file metadata, store listing, demo video, …) that directs the user toward a specific destination service. The tool produces a file; downstream use is the user's responsibility.
- AI attribution lines in commits, PR descriptions, or code comments.
For larger changes (new dependency, architectural shift), open an issue first to discuss the design.
Releases are produced by GitHub Actions on every v* tag push.
- Bump
versioninsrc/manifest.jsonand commit. - Tag the commit:
git tag v<version>(e.g.git tag v0.2.0). - Push the tag:
git push origin v<version>. - The
release.ymlworkflow checks out the tag, runsnpm ci,npm run build, andnpm run package, then creates a draft GitHub Release withrelease/clipcv-v<version>.zipandrelease/clipcv-v<version>.crxattached. The release stays in draft so a maintainer can review the artifacts and write user-facing notes before publishing. - The CRX signing key is consumed from the
CRX_PRIVATE_KEYrepository secret — a PEM-encoded RSA-2048 private key. Generate it once withopenssl genrsa -out clipcv.pem 2048and paste the contents into the secret. The same key must be used for every subsequent release so the extension's.crxretains a stable id. The PEM must never be committed (*.pemis gitignored).
To smoke-test the workflow without a public release, push a prerelease tag such as v0.0.1-test. The workflow attaches artifacts to a draft release, which a maintainer can delete afterward.
MIT © clipcv contributors.