pdf-manipulation
Manipulate PDF files including merge, split, extract, redact, convert, and secure workflows.
What this skill does
# PDF Manipulation Skill
Merge, split, extract, redact, and transform PDF files using free command-line tools and libraries. Covers common PDF operations for document automation workflows.
## When to use
- Merge multiple PDFs into one document
- Split large PDFs into separate files or page ranges
- Extract text, images, or specific pages
- Redact sensitive information
- Add watermarks, passwords, or metadata
- Convert PDFs to images or other formats
## Required tools
- **pdftk** — Swiss Army knife for PDF manipulation (merge, split, rotate, encrypt)
- **qpdf** — PDF transformation and encryption (linearize, decrypt, repair)
- **pdftotext / pdfimages** — Part of poppler-utils (extract text and images)
- **ghostscript (gs)** — Advanced PDF processing, compression, and conversion
### Installation
```bash
# Ubuntu/Debian
sudo apt-get install pdftk qpdf poppler-utils ghostscript
# macOS (Homebrew)
brew install pdftk-java qpdf poppler ghostscript
# For Node.js: npm i pdf-lib (pure JS, no system deps)
# For Python: pip install PyPDF2 pypdf
```
## Skills
### Merge PDFs
```bash
# Using pdftk (preserves bookmarks, forms)
pdftk file1.pdf file2.pdf file3.pdf cat output merged.pdf
# Using ghostscript (better compression)
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=merged.pdf file1.pdf file2.pdf file3.pdf
# Using qpdf (preserves structure)
qpdf --empty --pages file1.pdf file2.pdf file3.pdf -- merged.pdf
```
**Node.js (pdf-lib):**
```javascript
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
async function mergePDFs(files, output) {
const mergedPdf = await PDFDocument.create();
for (const file of files) {
const pdfBytes = fs.readFileSync(file);
const pdf = await PDFDocument.load(pdfBytes);
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
pages.forEach(page => mergedPdf.addPage(page));
}
const mergedBytes = await mergedPdf.save();
fs.writeFileSync(output, mergedBytes);
}
// mergePDFs(['file1.pdf', 'file2.pdf'], 'merged.pdf');
```
### Split PDF (by page or range)
```bash
# Split every page into separate files
pdftk input.pdf burst output page_%02d.pdf
# Extract specific pages (e.g., pages 1-5 and 10)
pdftk input.pdf cat 1-5 10 output subset.pdf
# Extract page ranges with qpdf
qpdf input.pdf --pages . 1-5 -- output.pdf
# Split every N pages (e.g., every 2 pages)
pdftk input.pdf burst
# then manually combine or script it
```
**Node.js (pdf-lib):**
```javascript
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
async function extractPages(inputPath, pages, outputPath) {
const pdfBytes = fs.readFileSync(inputPath);
const pdfDoc = await PDFDocument.load(pdfBytes);
const newPdf = await PDFDocument.create();
for (const pageNum of pages) {
const [page] = await newPdf.copyPages(pdfDoc, [pageNum - 1]);
newPdf.addPage(page);
}
const newBytes = await newPdf.save();
fs.writeFileSync(outputPath, newBytes);
}
// extractPages('input.pdf', [1, 3, 5], 'output.pdf');
```
### Extract text
```bash
# Extract all text (preserves layout)
pdftotext input.pdf output.txt
# Extract text as raw (no layout)
pdftotext -raw input.pdf output.txt
# Extract specific pages
pdftotext -f 1 -l 5 input.pdf output.txt
# Using qpdf + pdftotext
pdftotext -layout input.pdf -
```
**Node.js (pdf-parse):**
```javascript
const fs = require('fs');
const pdf = require('pdf-parse');
async function extractText(filePath) {
const dataBuffer = fs.readFileSync(filePath);
const data = await pdf(dataBuffer);
return data.text;
}
// extractText('input.pdf').then(console.log);
```
### Extract images
```bash
# Extract all images from PDF
pdfimages -all input.pdf output_prefix
# Output: output_prefix-000.png, output_prefix-001.jpg, etc.
# Extract only JPEGs
pdfimages -j input.pdf output_prefix
```
### Redact / Remove pages
```bash
# Remove specific pages (e.g., remove pages 2-4)
pdftk input.pdf cat 1 5-end output redacted.pdf
# Keep only specific pages
pdftk input.pdf cat 1-10 20-30 output selected.pdf
```
### Add password protection
```bash
# Encrypt PDF with password
pdftk input.pdf output secured.pdf user_pw mypassword
# Remove password
pdftk secured.pdf input_pw mypassword output unlocked.pdf
# Using qpdf (AES-256)
qpdf --encrypt userpass ownerpass 256 -- input.pdf output.pdf
```
**Node.js (pdf-lib):**
```javascript
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
async function encryptPDF(inputPath, password, outputPath) {
const pdfBytes = fs.readFileSync(inputPath);
const pdfDoc = await PDFDocument.load(pdfBytes);
const encryptedBytes = await pdfDoc.save({
userPassword: password,
ownerPassword: password
});
fs.writeFileSync(outputPath, encryptedBytes);
}
```
### Rotate pages
```bash
# Rotate all pages 90 degrees clockwise
pdftk input.pdf cat 1-endright output rotated.pdf
# Rotate specific pages
pdftk input.pdf cat 1-5 6right 7-end output rotated.pdf
# Options: right (90°), left (270°), down (180°)
```
### Compress / Reduce file size
```bash
# Using ghostscript (adjust quality)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook \
-dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdf
# Quality settings:
# /screen - low quality (72 dpi)
# /ebook - medium (150 dpi)
# /printer - high (300 dpi)
# /prepress - highest (300 dpi, preserves color)
# Using qpdf (lossless compression)
qpdf --linearize --object-streams=generate input.pdf compressed.pdf
```
### Convert PDF to images
```bash
# Convert each page to PNG (300 DPI)
pdftoppm -png -r 300 input.pdf output_prefix
# Output: output_prefix-1.png, output_prefix-2.png, etc.
# Convert to JPEG
pdftoppm -jpeg -r 150 input.pdf output_prefix
# Using ImageMagick (alternative)
convert -density 300 input.pdf output_%03d.png
```
### Add watermark
```bash
# Overlay watermark.pdf on every page
pdftk input.pdf stamp watermark.pdf output watermarked.pdf
# Background watermark (behind content)
pdftk input.pdf background watermark.pdf output watermarked.pdf
# Watermark specific pages only
pdftk input.pdf multistamp watermark.pdf output watermarked.pdf
```
### Get PDF metadata
```bash
# Using pdftk
pdftk input.pdf dump_data
# Using qpdf
qpdf --show-object=1 input.pdf
# Using pdfinfo (poppler-utils)
pdfinfo input.pdf
```
### Multi-operation script (Node.js)
```javascript
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
class PDFHelper {
static async merge(files, output) {
const merged = await PDFDocument.create();
for (const file of files) {
const pdf = await PDFDocument.load(fs.readFileSync(file));
const pages = await merged.copyPages(pdf, pdf.getPageIndices());
pages.forEach(p => merged.addPage(p));
}
fs.writeFileSync(output, await merged.save());
}
static async split(input, ranges, output) {
const pdf = await PDFDocument.load(fs.readFileSync(input));
const newPdf = await PDFDocument.create();
const pages = await newPdf.copyPages(pdf, ranges);
pages.forEach(p => newPdf.addPage(p));
fs.writeFileSync(output, await newPdf.save());
}
static async info(input) {
const pdf = await PDFDocument.load(fs.readFileSync(input));
return {
pages: pdf.getPageCount(),
title: pdf.getTitle(),
author: pdf.getAuthor(),
creator: pdf.getCreator()
};
}
}
module.exports = PDFHelper;
```
## Agent prompt
```text
You have PDF manipulation skills. When a user requests PDF operations:
1. Detect the operation: merge, split, extract (text/images/pages), redact, compress, encrypt, rotate, watermark, or get info.
2. Use appropriate tools:
- pdftk for merge, split, rotate, encrypt, watermark
- pdftotext/pdfimages for extraction
- ghostscript for compression
- qpdf for repair and advanced operations
3. Always validate input files exist before processing.
4. For scripting, prefer pdf-lib (Node.js) or PyPDF2 (Python) for Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.