Use Claude Code or Codex as your reviewer
If you are an HBS student, read Stay compliant with HBS AI policies before sending HBS course materials to either provider.
Two independent ways to bring AI into a review, both optional and off by default. By default the summary is built from your highlighted excerpts, your notes and the document's extracted text; a setting narrows that to notes only (see choosing the context scope below), and the PDF file itself is never sent. The report sets AI text apart in grey italics with a legend.
A. The built-in executive summary
- Install a CLI and sign in once (Install a command-line AI assistant walks through it):
npm i -g @anthropic-ai/claude-codethen runclaude, ornpm i -g @openai/codexthen runcodex. - Open your case and run PDF Case Review: Summarize with AI. That one command is the front door: with no provider configured it opens the provider picker first, which probes both CLIs and shows, per option, the signed-in account or a one-line install fix, plus a Manual entry for the clipboard flow below. (Choose AI Provider... opens the same picker on its own whenever you want to switch.)
Before anything is sent you answer one direct question: may this document be fed into AI context on this account? The dialog names the signed-in email (read from the CLI's own saved login, never from asking a model), shows the document's authorization line when page 1 has one ("authorized for use only by..."), and counts what will be sent. Answering yes records the attestation in the sidecar; the report's AI section is stamped with provider, model, account and dates. Cancel and nothing is sent; the report still renders without a summary.
Review the prompt before it is sent
After you answer yes, the assembled prompt opens in an editor tab (a Markdown file under the extension's global storage, ai/summary-<timestamp>.prompt.md) and a notification reports its size: "review the prompt (N words, about M tokens), edit it if you like, then send", with a Send to Claude Code (or Send to Codex) button and Cancel. Read it to see where your tokens go, trim or reword it if you like, then press Send: the provider receives exactly what the tab contains at that moment, unsaved edits included. Cancel, or dismiss the notification, and nothing is sent. When the run finishes the reply opens beside the prompt as summary-<timestamp>.output.md, and it is cached in the sidecar as usual. The folder keeps the newest 20 files. To send straight away without the tab, set "pdfCaseReview.ai.reviewPrompt": false. The clipboard flow below never opens a tab; the clipboard is its review surface.
The summary's word budget is pdfCaseReview.ai.maxWords (500 by default). Configure ($(gear) in the tab's title bar) > Summary Length... changes it in place, at whichever settings scope defines it.
The summary is cached in the sidecar (aiSummary), so re-rendering the report never re-calls the model; every run of Summarize with AI generates a fresh one and replaces it. To read the cached summary without regenerating it, run PDF Case Review: Show AI Summary: it opens in a tab headed Generated with <provider> on <date> (plus model and account when recorded), and says so when nothing is cached yet. The prompt template is at version 3 as of this release (it now asks the model to avoid em-dashes), so a summary cached by an earlier release is reported as possibly out of date once, until you regenerate it.
When there is nothing to send, Summarize with AI and Copy Summary Prompt stop with "nothing to summarize yet" instead of sending an empty prompt. Under the default document-text scope (below) the document text alone is enough, so this mainly bites under the notes scope, or on a scanned or image-only PDF with no extractable text, until you highlight a passage or add a note.
Choose how much context is sent
By default the prompt carries your highlights and notes plus the document text, so a summary works on a freshly opened case before any highlights exist. Summarize with AI and Copy Summary Prompt append the document text after your notes: extracted per page through the viewer, each page chunked under a citation marker, so the model can cite pages. It is document text, not the PDF: the file itself is never sent, and pages with nothing to extract (image-only exhibits, scans) are simply absent. Very long documents are cut off at a size budget and the prompt says where.
To keep the PDF's text on this machine and send only your highlights and notes, narrow the scope:
"pdfCaseReview.ai.contextScope": "notes"Widening the scope always re-asks the consent question (a wider consent covers narrower runs, so switching back never nags), and the dialog states exactly what the run will send: under document text it adds a coverage line ("text extracted from N of M page(s), about W words") so you can judge how much of the document is actually going out before you answer. Add AI Page Context is unaffected: it always sends only the picked pages' highlights and notes.
A summary generated under document text is stamped in the report ("using document text"), and its cache is tied to the PDF's content hash, so a changed file marks it as possibly out of date.
Context for a busy page
PDF Case Review: Add AI Page Context... finds pages with a dense cluster of highlights where most carry no note (threshold: pdfCaseReview.ai.pageContext.minHighlights), lets you pick which of them to cover, and asks the same provider for 2 to 4 sentences per page: what the highlighted passages are about and why they hang together. One consent dialog covers the batch. The contexts are cached in the sidecar (aiPageContexts) and render above those pages' highlights in the report, in the same grey italics with per-block provenance; editing a page's highlights marks only that page's context as possibly out of date.
No CLI? Use the clipboard
Pick Manual in the provider picker (or run PDF Case Review: Copy Summary Prompt directly). It passes the same eligibility question, then puts the prompt and your notes on the clipboard. Paste into claude.ai, chatgpt.com or any chat, copy the answer, and run Paste AI Summary. It is saved and reported like any other provider's output, labeled manual.
Enforce the right account
If some documents must only be processed under a specific login (a school account, say), add a rule:
// settings.json
"pdfCaseReview.ai.requiredAccount": [
{ "when": { "protected": true }, "email": "you@school.edu" }
]When a rule matches and the signed-in email differs, the AI step is refused with no override; sign out of the CLI (/logout in claude), sign in with the right account, and retry. Rules can also match on authorizationLineMatches (a regex against the document's own authorization line) or pathGlob.
Two accounts without logging out
If you switch accounts often, keep a second CLI login in its own directory and register it. An id is unique per provider, not globally, so register the same id once for each CLI you use:
"pdfCaseReview.ai.accounts": [
{ "id": "school", "provider": "claude-cli", "configDir": "~/.claude-school" },
{ "id": "school", "provider": "codex-cli", "configDir": "~/.codex-school" }
],
"pdfCaseReview.ai.requiredAccount": [
{ "when": { "protected": true }, "use": "school" }
]A rule's use picks the entry for the active provider: with pdfCaseReview.ai.provider set to claude-cli a protected document runs under ~/.claude-school, and switching the provider to codex-cli moves it to ~/.codex-school without touching the rule. When a matched rule names an id that has no entry for the active provider, the run is refused with an error naming the fix, and its Add an AI Account... button opens the guided flow with the provider and id already filled in. Listing the same id twice for one provider is reported as a warning and the first entry wins. Leave email off a rule that has use when the two logins have different addresses: email is checked against whichever login runs, so one address cannot fit both.
The Configure button in the viewer's title bar ($(gear)) has an Add an AI Account flow that writes both settings for you, creates the login directory and opens a sign-in terminal with the directory already on the environment. When the id is already registered for the other provider and rules select it, the flow skips the "when should this account be used?" question and tells you those rules now cover the new provider as well. By hand instead: run the CLI with the directory set, for example in PowerShell: $env:CLAUDE_CONFIG_DIR = "$HOME\.claude-school"; claude and sign in. From then on the extension sets CLAUDE_CONFIG_DIR (or CODEX_HOME) on the spawned CLI itself and verifies the email it finds there; you never export environment variables for VS Code. To switch the account your terminal and the Claude Code chat panel use as well, see Use personal and school Claude accounts.
While a PDF is open, the status bar shows the provider and the account the document would run under ($(sparkle) Claude Code · school), with the signed-in email and login directory in its tooltip. A warning background means the run would be refused as configured, for example $(warning) Codex · no "school" login. Clicking the item opens the provider picker.
When a plan hits its monthly limit
Click the AI status bar item or run PDF Case Review: Choose AI Provider..., pick the other CLI, and answer the consent question once more on the next run (the consent is recorded per provider, so a switch re-asks it). The same rules apply: a protected document still runs under the school entry, now the one for the provider you picked. Each CLI in the picker is probed under the login this document's rules select, so the email shown is the one the gate will verify; if the other CLI has no login registered under that id, the picker says so and offers Add an AI Account... after you pick it. When a run fails, the error notification carries a Switch AI Provider... button that reruns the command under the provider you pick there. A failure that reads like a usage limit is reported as "Claude Code reports a usage limit; switch to the other provider for now" (or Codex), with the raw error in the output channel.
B. The agent reads your notes directly
Because the sidecar is plain JSON, a terminal agent can work with your notes without any integration. In Claude Code or Codex, from the folder with your case:
Read
ferrari-2025.pdf.review.json. It follows the schema at https://raw.githubusercontent.com/realslimslaney/pdf-case-review/main/schemas/review.schema.json: highlights with categories, quotes and notes, plus page and document notes. Summarize my notes by category, flag contradictions between highlights, and draft three discussion questions for class.
Reusable version for a repo: drop the same instructions into AGENTS.md, or as a Claude Code skill in .claude/skills/pdf-case-review/SKILL.md:
---
name: pdf-case-review
description: Work with PDF Case Review sidecars (<file>.pdf.review.json) when the user asks about their reading notes or highlights.
---
Sidecars follow schemas/review.schema.json from realslimslaney/pdf-case-review:
`highlights[]` carry categoryId, page, text (the quote) and note; `pageNotes[]` and
`documentNotes[]` carry page and document level notes; `categories[]` maps ids to names.
Cite quotes with their page. Never invent content that is not in the file; say so when
the notes do not cover a question.This "ask questions about my notes" path sends whatever your agent reads to your agent's provider under your own CLI login, so the same eligibility judgment applies: it is your responsibility to use it on content your account may process.