Turn technical books into Claude Code plugins using an Opus-advises, Sonnet-executes pipeline
Project description
Franklin
Turn technical books into Claude Code plugins.
Franklin reads an EPUB or PDF and produces a full Claude Code plugin — SKILL, reference tree, slash commands, subagents, and plugin packaging — by extracting the book's concepts, principles, and workflows into structured intermediate data, then generating one artifact at a time. Every stage is a separate CLI command so you can iterate cheaply, and every stage writes to disk so crashes resume where they stopped.
Install
The easiest install is via uv or pipx:
uv tool install franklin-book
# or
pipx install franklin-book
On macOS / Linux you can also install via Homebrew:
brew tap mcrundo/franklin
brew install franklin-book
All three drop a franklin command onto your PATH. (The distribution is called franklin-book on PyPI and Homebrew because franklin was already taken; the CLI you actually type is still franklin. See docs/homebrew.md for tap maintenance details.)
For development from a clone:
uv sync
uv run franklin doctor
Franklin is a Python 3.12+ package managed with uv.
First-run checklist
uv run franklin doctor
franklin doctor is a preflight: it verifies your Python version, uv and claude binaries, Anthropic API key resolution, license state, network reachability to api.anthropic.com, and available disk space. Run it once after install to catch setup issues before your first paid run. --skip-network for air-gapped environments, --json for support tooling.
Anthropic API key
Franklin looks up ANTHROPIC_API_KEY in the environment first, then falls back to the OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) under service name franklin:
# Option 1: environment variable (CI, direnv, 1Password op run)
export ANTHROPIC_API_KEY=sk-ant-...
# Option 2: OS keychain (local dev — stored encrypted at rest)
keyring set franklin ANTHROPIC_API_KEY
Use whichever fits your workflow. You do not need to configure anything in Franklin itself.
The happy path
# Pick a book interactively (scans ~/Books, ~/Media, ~/Downloads, ~/Documents
# by default; override with --dir or FRANKLIN_BOOKS_DIR). Truncates long
# titles, shows author + year, and marks anything you've already processed.
uv run franklin pick
# Or point directly at a file
uv run franklin run path/to/book.epub
# Curious what it'll cost first? Dry-run the estimator.
uv run franklin run path/to/book.epub --estimate
# Want a pause between plan and reduce to prune artifacts?
uv run franklin run path/to/book.epub --review
franklin pick runs ingest, then shows a pre-map cost gate: a per-stage cost table with a low-high range, then a Proceed / Edit chapter selection / Cancel prompt. "Edit" opens a multi-select where every content chapter is pre-checked — spacebar to skip the chapters you don't want to spend tokens on, Enter to commit. The selection persists across resumes via map_selection.json.
franklin run chains the five pipeline stages end-to-end (ingest → map → plan → reduce → assemble) and ends with a grade card plus a tailored "next steps" block. It's resume-safe: re-running over an existing run directory detects which stages are done and prompts to continue from the first incomplete one. Use --force to restart from scratch, --yes to auto-confirm prompts in scripts.
Pipeline stages
Every stage can be run on its own, reads from disk, and writes to disk — so you can replay just one stage when you change a prompt or want to inspect intermediate state.
- ingest (
franklin ingest <book>) — parse EPUB/PDF into normalized chapter JSON. Deterministic, no LLM calls. PDFs get an optional Tier 4 LLM cleanup pass via--cleanthat fixes extraction artifacts concurrently with a live progress bar. - map (
franklin map <run-dir>) — per-chapter structured extraction. One LLM call per chapter produces a sidecar with concepts, rules, anti-patterns, and workflows. - plan (
franklin plan <run-dir>) — design the plugin architecture from the distilled sidecars (one call). - reduce (
franklin reduce <run-dir>) — generate each artifact file from the plan. This is the most expensive stage. - assemble (
franklin assemble <run-dir>) — writeplugin.json, run link/frontmatter/template validators, and compute the grade card.
Iteration tools
franklin runs list— table of every run directory under./runs/with slug, title, date, last completed stage, artifact count, and grade.franklin grade <run-dir>— detailed per-artifact grade report with structural rubric scores, lowest-grade artifacts, and suggested regeneration commands.--jsonfor machine output.franklin review <run-dir>— interactive pruning of the planned artifact list. Show the plan, omit artifacts you don't want to pay to generate, save a reducedplan.json. Supports index ranges like1,3-5.franklin inspect <run-dir>— preview the ingest output (chapters, code blocks, anomalies) before committing to the paid stages.franklin reduce <run-dir> --artifact <id> --force— regenerate one artifact after editing a prompt or fixing a sidecar.
Publishing and installing
Once a run is assembled and you're happy with the grade:
# Try it locally before publishing (ephemeral, per-session)
uv run franklin install <run-dir> --scope local
# Or persist it to your user scope (every Claude Code session)
uv run franklin install <run-dir> --scope user
# Or scope it to the current project (committed to .claude/settings.json)
uv run franklin install <run-dir> --scope project
# When ready to share, push to a GitHub repo
uv run franklin push <run-dir> --repo owner/name
# Other users (and you, after publishing) install from GitHub
claude plugin install owner/name
v0.1 ships fully free: every command above is available without a license, and you don't need to run franklin license login before franklin push or franklin install. The license module stays in place for a future paid tier; franklin license status continues to work if you want to inspect state, but no command calls it as a gate today.
Advisor strategy (Opus advises, Sonnet executes)
Franklin uses the advisor pattern to get Opus-quality output at roughly Sonnet prices: a single expensive Opus call produces a high-leverage plan, and many cheap Sonnet calls execute that plan one artifact at a time.
Concretely:
plan(Opus) runs once per run and outputsplan.json— the full plugin architecture, artifact list, and per-filefeeds_fromwiring. This is the advisory call; it thinks holistically about the book and the plugin shape.reduce(Sonnet) runs N times — once per artifact — and generates each file using the brief Opus wrote. Sonnet never has to reason about the architecture; it just fills in a well-scoped plan.
For a typical 28-artifact run that translates to 1× Opus + 28× Sonnet instead of 29× Opus. In dollar terms that's roughly $0.30 + 28 × $0.20 ≈ $5.90 vs 29 × $1.00 ≈ $29.00 — the same output quality for about 20% of the cost. map and cleanup similarly use Sonnet since they're per-chapter executions of a well-defined extraction prompt, not architectural decisions.
The tradeoff is that Opus's advisory call is a single point of failure: if the plan is wrong, all 28 reduces inherit the mistake. franklin review <run-dir> pauses between plan and reduce so you can prune or redirect the plan before paying for execution — that's the human-in-the-loop half of the pattern.
Cost and performance
franklin run --estimatepredicts per-stage token counts and dollar cost from a parsedBookManifestbefore any paid calls. Displayed as a$low - $highrange: the high end is the pessimistic worst case (~1.3 tokens/word x chapter text + per-stage overhead), the low end discounts for prompt caching and realistic output lengths. Real runs almost always land inside the band.franklin pickshows the same estimate as a pre-map gate so you can deselect expensive chapters before paying for them — see "happy path" above.- Tier 4 cleanup uses
AsyncAnthropicwith a bounded semaphore (--clean-concurrency=8default). A 29-chapter book drops from ~50 minutes sequential to ~6 minutes. - Resume-on-disk means a flaky network or a burned credit card never costs you more than the stage that was in flight. Re-run the same command; Franklin picks up from
book.json,chapters/,plan.json, oroutput/depending on what already exists. - Per-chapter failures are non-fatal during cleanup and map; the original Tier 2 output is kept and reported in the summary.
- LLM drift is tolerated, not fatal. If a tool-use response slips a stray field onto a sub-object, the validator strips it and logs a warning instead of killing the whole stage. Missing required fields and type errors still raise.
Run directory layout
runs/<slug>/
book.json # BookManifest (evolves across stages)
raw/chNN.json # NormalizedChapter — one per chapter from ingest
chapters/chNN.json # ChapterSidecar — one per chapter from map
plan.json # PlanManifest — from plan
output/<plugin>/ # Generated plugin tree — from reduce/assemble
.claude-plugin/plugin.json
skills/<name>/SKILL.md
references/.../*.md
commands/*.md
agents/*.md
metrics.json # Grade card output from assemble
Configuration
- Runs directory: defaults to
./runs/relative to cwd; override with--outputon any stage command. - License directory: defaults to
~/.config/franklin/; override withFRANKLIN_LICENSE_DIR. - Models:
claude-sonnet-4-6is the default formap,reduce, andcleanup;claude-opus-4-6is the default forplan. Override per-command with--model.
Development
uv run pytest # run the test suite
uv run ruff check . # lint
uv run ruff format . # format
uv run mypy # type check (strict)
Prompts live as markdown under src/franklin/llm/prompts/ and are loaded by the prompt renderer — add new ones there rather than inlining strings.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file franklin_book-0.2.0.tar.gz.
File metadata
- Download URL: franklin_book-0.2.0.tar.gz
- Upload date:
- Size: 235.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c58a2c5f3cfc2d082de8407effb357f429a897b138eb50c30f5cb4e2e6f1c23f
|
|
| MD5 |
b257377dca839ccb8924b93a1a45c1ba
|
|
| BLAKE2b-256 |
410bfc92a83a7a3c6521cf850973207c8be6d9947255c8f0b57a0d1b5d901590
|
Provenance
The following attestation bundles were made for franklin_book-0.2.0.tar.gz:
Publisher:
publish.yml on mcrundo/franklin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
franklin_book-0.2.0.tar.gz -
Subject digest:
c58a2c5f3cfc2d082de8407effb357f429a897b138eb50c30f5cb4e2e6f1c23f - Sigstore transparency entry: 1280226759
- Sigstore integration time:
-
Permalink:
mcrundo/franklin@848108f4097ee49ee5e0d2f96b31b625a4c159ee -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/mcrundo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@848108f4097ee49ee5e0d2f96b31b625a4c159ee -
Trigger Event:
release
-
Statement type:
File details
Details for the file franklin_book-0.2.0-py3-none-any.whl.
File metadata
- Download URL: franklin_book-0.2.0-py3-none-any.whl
- Upload date:
- Size: 126.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8143436e68fdb65a93d9f84031249bb0a7d452fc0f7ec7c5d7aee90ebed3e2a4
|
|
| MD5 |
a9c228ffb4fe00c4e5d450f667458381
|
|
| BLAKE2b-256 |
970ccae6cefc11ff529d5f371156001962c0d0444cbf4e047ac9186c7c599289
|
Provenance
The following attestation bundles were made for franklin_book-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on mcrundo/franklin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
franklin_book-0.2.0-py3-none-any.whl -
Subject digest:
8143436e68fdb65a93d9f84031249bb0a7d452fc0f7ec7c5d7aee90ebed3e2a4 - Sigstore transparency entry: 1280226760
- Sigstore integration time:
-
Permalink:
mcrundo/franklin@848108f4097ee49ee5e0d2f96b31b625a4c159ee -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/mcrundo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@848108f4097ee49ee5e0d2f96b31b625a4c159ee -
Trigger Event:
release
-
Statement type: