This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
vp install # Install dependencies (auto-detects pnpm)
vp run build # Build extension to ./dist
vp lint # Lint (type-aware, config in vite.config.ts)
vp fmt # Format
vp check # Run fmt + lint + typecheck in one command
vp test # Run unit tests (via Vitest)
vp test src/shared/pdf.test.ts # Run a single test file
vp run test:e2e # Run e2e tests with Playwright
vp run package # Package extensionChrome extension (Manifest V3) for PDF signing in Outlook Web. Downloads PDF attachments, signs them, creates reply drafts. Built with Vite+, uses pdf-lib for PDF manipulation.
#shared/*→src/shared/*#mocks/*→e2e/mocks/*#helpers/*→e2e/helpers/*
src/
├── content/ # Content scripts (injected into Outlook)
│ ├── content.ts # Entry point, message handling
│ ├── outlook-dom.ts # PDF collection workflow orchestrator
│ ├── outlook-actions.ts # Outlook DOM operations (messages, attachments, replies)
│ ├── outlook-automation.ts # DOM interaction helpers (click, type, wait)
│ ├── outlook-compose.ts # Create draft replies
│ ├── outlook-compose-actions.ts # Draft reply DOM operations
│ ├── outlook-download.ts # PDF download via blob interception
│ ├── blob-protocol.ts # Window message types for blob transfer
│ └── main-world.ts # MAIN world script (blob URL interception)
├── background/ # Service worker
│ └── service-worker.ts # PDF signing, message routing
├── popup/ # Extension popup UI
├── options/ # Settings page
└── shared/ # Shared types and utilities
├── dom.ts # DOM utility (getElement)
├── encoding.ts # Base64 encoding/decoding
├── errors.ts # Error message extraction
├── messages.ts # Message types
├── origins.ts # Outlook origin constants
├── pdf.ts # PDF signing, name extraction, attachment naming
├── sender.ts # Email/lastname extraction from sender strings
└── storage.ts # Chrome storage API wrappers
The extension uses two content scripts injected into Outlook pages:
- MAIN world (
main-world.ts): Runs in the page's JS context to interceptblob:URLs viaXMLHttpRequestmonkey-patching. Communicates PDF data to the content script viawindow.postMessage. - ISOLATED world (
content.ts): Standard content script that orchestrates the workflow, manipulates DOM, and communicates with the service worker viachrome.runtime.
The blob protocol (blob-protocol.ts) defines the message types exchanged between worlds.
- User selects conversation in Outlook Web
- Clicks extension popup → "Sign PDFs & Create Drafts"
- Content script finds PDF attachments from the last message sent by others
- Downloads PDF, sends to service worker for signing
- Creates reply draft with signed PDF attached
setTimeout: In Node scripts, useimport { setTimeout } from "node:timers/promises"notnew Promise(r => setTimeout(r, ms)). In browser code (src/), use thesleephelper fromoutlook-automation.ts- Encoding:
utf8notutf-8(unicorn/text-encoding-identifier-case) - Array destructuring:
const [, second] = arrnotarr[1](prefer-destructuring) - Strict booleans:
!== undefined && !== ""not truthy checks (strict-boolean-expressions) - Catch params:
errornoterr(unicorn/catch-error-name) - Catch handlers: Must use braces
(error) => { console.error(error); }(no-confusing-void-expression) - No empty catch: Always handle or log errors