Turn a Technical Book Into an Agent Skill
Convert a PDF, EPUB or folder of internal docs into an agent skill your coding agent loads on demand: install, token budget, headless runs, licensing.
Turn a technical book into an agent skill: what you get
To turn a technical book into an agent skill you point a converter at a PDF, an EPUB, a DOCX export, or a folder of internal documents you already own. It writes a skill directory: one entry file holding the named frameworks plus an index of the chapters, and one file per chapter that the agent reads only when your question calls for it. The book never enters the context window. The index does.
This is the opposite job from writing an agent skill from scratch, where you encode a procedure you already know. Here the knowledge exists and nobody can reach it: an 800-page vendor PDF, or a handbook that has not been opened since the person who wrote it left. The work is compression and indexing. If the word skill is new to you, read what an agent skill actually is first.
The converter used here is book-to-skill, an MIT-licensed skill that runs on your own machine. The current tag as of August 2026 is v1.4.0. The structure it produces matters more than the tool itself, and the last section before the FAQ shows how to build the same structure by hand.
Why the token budget is the whole design
A book pasted into a context window costs its full size on every conversation that needs it. A skill costs its entry file once, plus whatever chapters the question actually touches. The project documents a budget for each file it generates.
The data behind this chart
[
{
"label": "SKILL.md entry file",
"tokens": "4,000"
},
{
"label": "One chapter file",
"tokens": "1,000"
},
{
"label": "glossary.md",
"tokens": "1,500"
},
{
"label": "patterns.md",
"tokens": "2,000"
},
{
"label": "cheatsheet.md",
"tokens": "1,000"
}
]The entry file, SKILL.md, is held to 4,000 tokens and carries the named frameworks and the chapter index. Each chapter file is about 1,000 tokens and sits on disk until something asks for it. The supporting files are similar: 1,500 tokens for glossary.md, 2,000 for patterns.md, 1,000 for cheatsheet.md.
Those budgets line up with how Claude Code actually spends context. A skill's description sits in the skill listing so the model knows the skill exists. The body loads when the skill is invoked, and once loaded it stays in context for the rest of the session, so every line in the entry file is a recurring cost. Supporting files load only when the agent reads them, which is what makes per-chapter files cheap.
There is a harder limit behind that entry-file number. When auto-compaction summarises a long conversation, Claude Code re-attaches the most recent invocation of each skill after the summary and keeps the first 5,000 tokens of each, inside a combined budget of 25,000 tokens across every re-attached skill. An entry file that fits inside 5,000 tokens survives compaction whole. A 20,000-token entry file comes back as its first quarter, and nothing tells you which three quarters went missing.
That is progressive disclosure: a small index that is always worth its cost, and the bulk of the material behind a door the agent opens on purpose. How Claude Code manages its context window covers the rest of that accounting.
Install the converter on your VPS, pinned to a release
The skill is a git repository. Clone it into the skills directory of the agent you use. The directory name becomes the slash command, so the clone path is not a matter of taste.
git clone --depth 1 --branch v1.4.0 \
https://github.com/virgiliojr94/book-to-skill.git \
~/.claude/skills/book-to-skill--branch accepts a tag, so this checks out v1.4.0 and nothing later. Pin it, because a skill is a set of instructions your agent follows, and an unreviewed change to those instructions is a change to what runs on your server. GitHub Copilot CLI reads ~/.copilot/skills/ instead, and Amp reads ~/.agents/skills/.
There is also a one-line install, npx skills add virgiliojr94/book-to-skill, which fetches whatever is current. Use it to try the tool. Use the pinned clone for anything you re-run.
Now confirm which extractors the box has:
cd ~/.claude/skills/book-to-skill
python3 scripts/extract.py --check--check reports which extractors are installed and prints the install command for each one that is missing. The package needs Python 3.9 or newer.
If /book-to-skill does not appear in autocomplete after cloning, restart your agent. Claude Code watches the skill directories that existed when the session started, so a ~/.claude/skills/ you created two minutes ago is not being watched yet.
Which extractors do you actually need?
Nothing is required beyond Python, because every format has a standard-library fallback. The fallbacks are worse, and on a small server the wasted time is in installing extractors you had no use for.
pdftotext, from thepoppler-utilspackage, handles text-heavy PDFs and is close to instant. Install it withsudo apt install poppler-utils.pypdfandpdfminer.sixare the Python fallbacks for PDF.doclingis for technical PDFs whose value is in their tables and code listings. The project measures it at roughly 1.5 seconds per page.ebooklibwithbeautifulsoup4reads EPUB properly. Without them the tool falls back to the stdlibzipfilereader.python-docxreads DOCX andstriprtfreads RTF.- Calibre's
ebook-convertis required for MOBI and AZW files. ocrmypdfruns OCR (optical character recognition) over a scanned book, which carries no text layer at all.
On Ubuntu 24.04 a plain pip3 install pypdf stops with this:
error: externally-managed-environmentThat is not a broken pip. Ubuntu and Debian mark the system Python as managed by apt, so pip refuses to write into it. Two answers work. sudo apt install poppler-utils installs a binary and needs no pip at all, and pdftotext covers most prose PDFs on its own. For the Python extractors, build a virtual environment and start your agent from inside it, so the python3 the skill calls is the interpreter that has the packages.
python3 -m venv ~/.venvs/book-to-skill
source ~/.venvs/book-to-skill/bin/activate
pip install "$HOME/.claude/skills/book-to-skill[pdf,epub,docx]"
claudeThe repository declares the extras pdf, epub, docx, rtf, technical and all, where technical is docling. The project's install page also shows pip install "book-to-skill[pdf,epub,docx]", but that name is not published on PyPI as of August 2026, so install from your own checkout as above.
Leave docling out until a book needs it. It pulls in a machine learning stack, so check free disk on a small plan before you install it.
Run it over a folder of documents, including headless
The command takes a file, a folder, a quoted glob, or several paths at once, followed by an optional skill name. Anything you can put in one directory works, including an RFC set (request for comments, the documents that define internet protocols).
/book-to-skill ~/library/platform-docs/ platform-handbook
/book-to-skill "~/books/*.epub" my-library
/book-to-skill ~/papers/paper1.pdf ~/notes/export.txt unified-researchQuote the glob so your shell does not expand it before the skill sees it. Pointing the command at an existing skill directory folds the new sources into that skill instead of creating a second one.
An interactive run asks you questions. Is the material technical or text-heavy, which decides the extractor. Do you want reference depth or study depth, which decides the per-chapter budget. What should the skill be called, and which skills root should it go in. It also prints a token and time estimate before generation and waits for you to confirm.
A headless run has nobody to answer those questions. User-invocable skills do work in claude -p: put the slash command in the prompt string and Claude Code expands it before the run starts. So answer the questions in the same prompt.
claude -p "/book-to-skill ~/library/platform-docs/ platform-handbook
The sources are technical. Use reference depth. Write the skill to
~/.claude/skills/. Do not publish it to GitHub. Proceed without asking me." \
--allowedTools "Bash,Read,Write,Edit"--allowedTools pre-approves the tools the run needs, because a permission prompt with no terminal attached is a run that never finishes. Adding --output-format json puts total_cost_usd in the result, which is a client-side estimate rather than your bill.
Extraction consolidates every source into a temporary work directory under /tmp before any model reads it, and the last step of the run deletes that directory. A source that fails to extract is skipped so the batch survives, which means a run can report success having read fewer files than you supplied. Compare the file inventory in the final report against what is in the folder. A missing chapter is usually a missing source.
Give the run a server you are comfortable handing to an agent. Running Claude Code safely on a VPS covers the permission side of that.
Where the output goes so your coding agent finds it
The generated skill lands in a skills root. Two of them matter.
~/.claude/skills/<skill-name>/is personal, and available in every project on that machine..claude/skills/<skill-name>/lives inside a repository and travels with it.
Inside either one you get SKILL.md, a chapters/ directory with one file per chapter, and the supporting files. The directory name is the command, so ~/.claude/skills/platform-handbook/ gives you /platform-handbook, and you can follow it with a topic or a plain question.
Choose the root by licensing rather than convenience. A skill built from a book you bought belongs in your personal directory. A skill built from documentation your own team wrote belongs in the repository, which turns sharing one skill across several repositories into the next problem to solve.
One cost grows with every skill you add. Each skill's description stays in the skill listing so the model can decide to use it, the combined description text is truncated at 1,536 characters per entry, and the listing as a whole has a budget. Ten book skills means ten descriptions competing for it. For the ones you always call by name, add one line to the generated frontmatter:
---
name: platform-handbook
description: Frameworks and chapter index from the internal platform handbook.
disable-model-invocation: true
---With disable-model-invocation: true the description stays out of context entirely, and the skill still loads in full when you type /platform-handbook. You give up automatic discovery and get a quieter context window.
Licensing: MIT covers the converter, not the book
Be exact about this, because the failure here is not a technical one.
- The MIT license covers the converter's code and its skill definition. It says nothing about the document you feed it.
- Running the converter over a book you bought, on hardware you control, is you making notes from your own copy.
- Publishing the result is distribution, and the MIT license on the tool grants you no right to distribute anything derived from someone else's book.
- The output is a derivative work. Frameworks and chapter takeaways are still shaped by the source, and a derivative work is still governed by the source's copyright.
- A skill built from material you cannot redistribute stays on the machine that built it. Not a public repository. Not a shared team marketplace.
- Publish when the source is yours or openly licensed: documentation your team wrote, or a standard whose terms allow redistribution.
The tool is built around this. It ships no book content, extraction runs locally, and its publish step asks for repository visibility as a separate question that accepts only the bare word public or private rather than inferring one. Treat that prompt as the licensing decision, because that is what it is.
Internal handbooks carry a second problem. They contain credentials more often than anyone admits, and a converter turns a PDF nobody opens into a file your agent reads on demand. Read the generated files once before you commit them, and see keeping secrets out of your AI agents.
What does one conversion cost?
The numbers below are the project's own published measurements rather than ours.
The data behind this chart
[
{
"label": "Think Python 2",
"cost_usd": 0.88
},
{
"label": "Working Backwards",
"cost_usd": 0.96
},
{
"label": "Pro Git",
"cost_usd": 1.23
},
{
"label": "Moby-Dick",
"cost_usd": 1.42
}
]Across the 4 books the project measured, one conversion ran between 0.88 and 1.42 US dollars, with Pro Git at 1.23. The figures were measured on Claude Sonnet 4.5, with token counts from tiktoken using cl100k_base, and they are published in the project's docs/performance.md as of August 2026. Your own number moves with your model and your prices.
The project also documents 24 to 51 times fewer tokens to answer a single question from the skill than from the whole book pasted into context. Read that as the shape of the saving rather than a promise, because it depends on the book and the question. The structural point holds either way: conversion is paid once, and a context dump is paid again on every conversation that needs the book.
Why not paste the PDF or build a RAG index?
Pasting works, and it is the right answer for one question about one document. It stops being the right answer when the same book is needed on Tuesday and again on Friday, because you pay its full size each time.
Retrieval, or RAG (retrieval augmented generation), searches at query time and hands back the passages that match your words. That is strong when you need the exact sentence. It is weak when the useful thing is a framework spread across a chapter, because no single passage contains it. A skill does that extraction once, at conversion time, and stores the structure instead of the passages.
The honest limit: a generated skill is a lossy summary written by a model. It is a study aid, and the source is still the source. When the exact wording carries legal or protocol weight, keep the PDF and quote from it. Skills compared against MCP servers and rules files covers where each approach belongs.
Failure modes, and the strings you will see
A scanned PDF produces nothing. The extractor checks the opening pages for a text layer and stops with an explanation rather than grinding through 400 pages of images. Run ocrmypdf input.pdf output.pdf first, then feed it the output file.
pip refuses to install. error: externally-managed-environment on Ubuntu 24.04 is apt protecting the system Python. Use the virtual environment above, or install poppler-utils and skip pip entirely.
The chapters come out wrong. Chapter detection looks for explicit headings such as Chapter 7 and its language variants. A book that uses bare section titles or roman numerals gives a bad split, and the fix is to tell the run where the chapters start rather than hoping it guesses.
The command does not exist. /book-to-skill missing from autocomplete means the skills directory was created after your session started. Restart the agent.
Docling takes forever. At roughly 1.5 seconds per page it is minutes of CPU time for a long book, and on a shared server that run competes with everything else you host. Answer "text-heavy" when the run asks about content type, or pass --mode text when you drive scripts/extract.py yourself. --mode technical is the answer that selects docling.
A source vanishes quietly. A file that cannot be read is skipped so the batch can finish. The run then reports success over fewer sources than you handed it, and the only place that shows is the file inventory in the final report.
Apply the same pattern by hand
The tool is a convenience. The structure is the transferable part, and a text editor builds it for any reference material you own.
- Write one entry file and keep it near the 4,000 tokens the converter targets. Put the named concepts in it with their exact formulations, plus an index listing every detail file and the topics that file holds.
- Split the material into files of roughly 1,000 tokens, one topic each, named so the filename alone tells you what is inside.
- Describe each of those files from the entry file, in the sentence that says when to read it.
Step 3 is the one people skip, and it is the one that makes the pattern work. The agent chooses what to open by reading the index, so a file the index does not describe is a file the agent never opens. The index is the product, and the chapter files are storage.
Keep the entry file inside the compaction budget and the whole structure survives a long session. That rule holds whether a converter wrote the files or you did.
FAQ
Can I publish a skill built from a book I bought?
No, unless that book's license allows redistribution. The MIT license on the converter covers the converter's code, not the material you feed it, and the generated skill is a derivative work of the book. Keep it in ~/.claude/skills/ on your own machine. Publishing is fine for documentation you wrote yourself or for openly licensed sources, and the tool asks for repository visibility as its own question, accepting only a bare public or private, so the decision stays deliberate.
Do I need docling, or is pdftotext enough?
pdftotext from poppler-utils is enough for prose and is close to instant. Install docling when the value of the book sits in its tables and code listings, because a plain text extractor drops exactly those. The trade is speed: the project measures docling at roughly 1.5 seconds per page, so a 300-page manual is several minutes of CPU time on a VPS.
Why does pip fail with externally-managed-environment on my VPS?
Ubuntu 24.04 and current Debian mark the system Python as managed by apt, so pip refuses to install into it and prints error: externally-managed-environment. Create a virtual environment with python3 -m venv ~/.venvs/book-to-skill, activate it, install the extractors there, then start your agent from that same shell. The skill calls python3, so it uses whichever interpreter is on your PATH, which is now the one in the virtual environment.
Why does my generated skill not show up as a slash command?
Two causes. The command name comes from the directory name, so the skill has to sit at ~/.claude/skills/<name>/SKILL.md or .claude/skills/<name>/SKILL.md, with SKILL.md spelled exactly that way. If the path is right, restart the agent. Claude Code picks up edits inside skill directories it already watches, but a skills directory created after the session started is not being watched at all.