pi-heartbeat
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
Read and extract content from PDF files — text, tables, metadata, and images. Use when asked to read a PDF, extract text from a PDF, summarize a PDF, analyze a PDF document, get tables from a PDF, or check PDF metadata. Also triggers on "open this PDF", "what does this PDF say",
$ npx -y skills add espennilsen/pi --skill pdf-reader --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/pdf-readerContext preview
The summary Claude sees to decide when to auto-load this skill.
Read and extract content from PDF files — text, tables, metadata, and images. Use when asked to read a PDF, extract text from a PDF, summarize a PDF, analyze a PDF document, get tables from a PDF, or check PDF metadata. Also triggers on "open this PDF", "what does this PDF say",
name: pdf-reader description: > Read and extract content from PDF files — text, tables, metadata, and images. Use when asked to read a PDF, extract text from a PDF, summarize a PDF, analyze a PDF document, get tables from a PDF, or check PDF metadata. Also triggers on "open this PDF", "what does this PDF say", "parse PDF", "PDF to text", or when a .pdf file path or URL is provided.
Extract content from PDF files using `pdftotext` (Poppler) for text and `pdfplumber` (Python) for tables and structured extraction.
| Task | Tool | Command | |------|------|---------| | Full text | pdftotext | `pdftotext file.pdf -` | | Text with layout | pdftotext | `pdftotext -layout file.pdf -` | | Specific pages | pdftotext | `pdftotext -f 3 -l 5 file.pdf -` | | Tables | pdfplumber | `python3 scripts/extract.py tables file.pdf` | | Metadata | pdfinfo | `pdfinfo file.pdf` | | Page count | pdfinfo | `pdfinfo file.pdf \| grep Pages` | | Images | pdfimages | `pdfimages -list file.pdf` | | Fonts | pdffonts | `pdffonts file.pdf` | | OCR (scanned PDF) | tesseract | `python3 scripts/extract.py ocr file.pdf` | | Smart text + OCR | extract.py | `python3 scripts/extract.py text file.pdf` | | Quick survey | extract.py | `python3 scripts/extract.py scan file.pdf` |
If the user provides a URL, download it first:
curl -sL "URL" -o /tmp/document.pdf
Verify it's a valid PDF:
file /tmp/document.pdf # should say "PDF document" pdfinfo /tmp/document.pdf # metadata + page count
**Plain text (most cases):**
pdftotext file.pdf -
This pipes output to stdout. For large PDFs, use page ranges:
pdftotext -f 1 -l 10 file.pdf - # pages 1-10
**Layout-preserving text (columns, formatted docs):**
pdftotext -layout file.pdf -
Use `-layout` when the PDF has multi-column layouts, tables rendered as text, or precise spacing that matters.
**Tables (structured data):**
python3 scripts/extract.py tables file.pdf
Or inline with pdfplumber:
import pdfplumber
pdf = pdfplumber.open("file.pdf")
for i, page in enumerate(pdf.pages):
tables = page.extract_tables()
for table in tables:
print(f"\n--- Table on page {i+1} ---")
for row in table:
print(" | ".join(str(cell or "") for cell in row))
pdf.close()**Metadata only:**
pdfinfo file.pdf
Returns: title, author, creator, producer, page count, page size, dates.
For PDFs over ~50 pages, don't dump everything at once:
1. Get page count: `pdfinfo file.pdf | grep Pages` 2. Extract in chunks: `pdftotext -f 1 -l 20 file.pdf -` 3. Process chunk, then continue: `pdftotext -f 21 -l 40 file.pdf -`
For targeted extraction (searching for specific content):
# Extract all text, grep for relevant sections pdftotext file.pdf - | grep -n -i "keyword" # Then extract the specific page range pdftotext -f PAGE -l PAGE file.pdf -
If `pdftotext` returns empty or garbled output, the PDF is likely scanned.
**Detection:**
python3 scripts/extract.py scan file.pdf # reports scanned pages pdffonts file.pdf # empty = image-based
**Smart extraction (auto-fallback):**
`text` mode automatically detects scanned pages and OCRs them:
python3 scripts/extract.py text file.pdf
Pages with selectable text extract normally. Pages without selectable text fall back to OCR via Tesseract. No manual detection needed.
**Force OCR on all pages:**
python3 scripts/extract.py ocr file.pdf python3 scripts/extract.py ocr file.pdf --pages 1-5 python3 scripts/extract.py ocr file.pdf --dpi 400 # higher quality python3 scripts/extract.py ocr file.pdf --lang eng+nor # multi-language
**OCR options:**
**Available language packs:**
tesseract --list-langs
Install additional languages via Homebrew:
brew install tesseract-lang # all languages
**Mixed PDFs (some pages scanned, some not):**
Just use `text` mode — it handles mixed PDFs automatically:
python3 scripts/extract.py text file.pdf
Selectable pages extract instantly, scanned pages get OCR'd. The output is tagged so you know which pages used OCR.
**Password-protected PDFs:**
pdftotext -upw "password" file.pdf - # user password pdftotext -opw "password" file.pdf - # owner password
**Encoding issues (garbled output):**
pdftotext -enc UTF-8 file.pdf -
**Extract images:**
pdfimages -png file.pdf /tmp/images/img # extracts as PNG pdfimages -list file.pdf # list images without extracting
Is it a URL? → curl -sL "URL" -o /tmp/doc.pdf
↓
Run: python3 scripts/extract.py scan file.pdf
↓
All pages have selectable text?
YES → pdftotext file.pdf - (fast, simple)
NO → python3 scripts/extract.py text file.pdf (auto OCR fallback)
↓
Need tables?
YES → python3 scripts/extract.py tables file.pdfThis repository is my Pi coding agent home directory. I keep it under version control and symlink it to ~/.pi/agent so Pi loads configuration, extensions, skills, and runtime state from here.
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
Manage persistent memory across sessions. Use when asked to remember, recall, forget, or review what was stored. Covers long-term…
Track and manage projects with git status via dashboard and tool.
Delegate tasks to specialized subagents for parallel or sequential execution.
Audit, generate, update, and lint AGENTS.md files across all projects. Use when asked to check project context files, scaffold…