{"id":"9450ab57-2a5c-4ffc-b60b-28913a189594","shortId":"92f4Jp","kind":"skill","title":"pdf-manipulation","tagline":"Manipulate PDF files including merge, split, extract, redact, convert, and secure workflows.","description":"# PDF Manipulation Skill\n\nMerge, split, extract, redact, and transform PDF files using free command-line tools and libraries. Covers common PDF operations for document automation workflows.\n\n## When to use\n- Merge multiple PDFs into one document\n- Split large PDFs into separate files or page ranges\n- Extract text, images, or specific pages\n- Redact sensitive information\n- Add watermarks, passwords, or metadata\n- Convert PDFs to images or other formats\n\n## Required tools\n- **pdftk** — Swiss Army knife for PDF manipulation (merge, split, rotate, encrypt)\n- **qpdf** — PDF transformation and encryption (linearize, decrypt, repair)\n- **pdftotext / pdfimages** — Part of poppler-utils (extract text and images)\n- **ghostscript (gs)** — Advanced PDF processing, compression, and conversion\n\n### Installation\n```bash\n# Ubuntu/Debian\nsudo apt-get install pdftk qpdf poppler-utils ghostscript\n\n# macOS (Homebrew)\nbrew install pdftk-java qpdf poppler ghostscript\n\n# For Node.js: npm i pdf-lib (pure JS, no system deps)\n# For Python: pip install PyPDF2 pypdf\n```\n\n## Skills\n\n### Merge PDFs\n```bash\n# Using pdftk (preserves bookmarks, forms)\npdftk file1.pdf file2.pdf file3.pdf cat output merged.pdf\n\n# Using ghostscript (better compression)\ngs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=merged.pdf file1.pdf file2.pdf file3.pdf\n\n# Using qpdf (preserves structure)\nqpdf --empty --pages file1.pdf file2.pdf file3.pdf -- merged.pdf\n```\n\n**Node.js (pdf-lib):**\n```javascript\nconst { PDFDocument } = require('pdf-lib');\nconst fs = require('fs');\n\nasync function mergePDFs(files, output) {\n  const mergedPdf = await PDFDocument.create();\n  \n  for (const file of files) {\n    const pdfBytes = fs.readFileSync(file);\n    const pdf = await PDFDocument.load(pdfBytes);\n    const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());\n    pages.forEach(page => mergedPdf.addPage(page));\n  }\n  \n  const mergedBytes = await mergedPdf.save();\n  fs.writeFileSync(output, mergedBytes);\n}\n\n// mergePDFs(['file1.pdf', 'file2.pdf'], 'merged.pdf');\n```\n\n### Split PDF (by page or range)\n```bash\n# Split every page into separate files\npdftk input.pdf burst output page_%02d.pdf\n\n# Extract specific pages (e.g., pages 1-5 and 10)\npdftk input.pdf cat 1-5 10 output subset.pdf\n\n# Extract page ranges with qpdf\nqpdf input.pdf --pages . 1-5 -- output.pdf\n\n# Split every N pages (e.g., every 2 pages)\npdftk input.pdf burst\n# then manually combine or script it\n```\n\n**Node.js (pdf-lib):**\n```javascript\nconst { PDFDocument } = require('pdf-lib');\nconst fs = require('fs');\n\nasync function extractPages(inputPath, pages, outputPath) {\n  const pdfBytes = fs.readFileSync(inputPath);\n  const pdfDoc = await PDFDocument.load(pdfBytes);\n  const newPdf = await PDFDocument.create();\n  \n  for (const pageNum of pages) {\n    const [page] = await newPdf.copyPages(pdfDoc, [pageNum - 1]);\n    newPdf.addPage(page);\n  }\n  \n  const newBytes = await newPdf.save();\n  fs.writeFileSync(outputPath, newBytes);\n}\n\n// extractPages('input.pdf', [1, 3, 5], 'output.pdf');\n```\n\n### Extract text\n```bash\n# Extract all text (preserves layout)\npdftotext input.pdf output.txt\n\n# Extract text as raw (no layout)\npdftotext -raw input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt\n\n# Using qpdf + pdftotext\npdftotext -layout input.pdf -\n```\n\n**Node.js (pdf-parse):**\n```javascript\nconst fs = require('fs');\nconst pdf = require('pdf-parse');\n\nasync function extractText(filePath) {\n  const dataBuffer = fs.readFileSync(filePath);\n  const data = await pdf(dataBuffer);\n  return data.text;\n}\n\n// extractText('input.pdf').then(console.log);\n```\n\n### Extract images\n```bash\n# Extract all images from PDF\npdfimages -all input.pdf output_prefix\n\n# Output: output_prefix-000.png, output_prefix-001.jpg, etc.\n\n# Extract only JPEGs\npdfimages -j input.pdf output_prefix\n```\n\n### Redact / Remove pages\n```bash\n# Remove specific pages (e.g., remove pages 2-4)\npdftk input.pdf cat 1 5-end output redacted.pdf\n\n# Keep only specific pages\npdftk input.pdf cat 1-10 20-30 output selected.pdf\n```\n\n### Add password protection\n```bash\n# Encrypt PDF with password\npdftk input.pdf output secured.pdf user_pw mypassword\n\n# Remove password\npdftk secured.pdf input_pw mypassword output unlocked.pdf\n\n# Using qpdf (AES-256)\nqpdf --encrypt userpass ownerpass 256 -- input.pdf output.pdf\n```\n\n**Node.js (pdf-lib):**\n```javascript\nconst { PDFDocument } = require('pdf-lib');\nconst fs = require('fs');\n\nasync function encryptPDF(inputPath, password, outputPath) {\n  const pdfBytes = fs.readFileSync(inputPath);\n  const pdfDoc = await PDFDocument.load(pdfBytes);\n  \n  const encryptedBytes = await pdfDoc.save({\n    userPassword: password,\n    ownerPassword: password\n  });\n  \n  fs.writeFileSync(outputPath, encryptedBytes);\n}\n```\n\n### Rotate pages\n```bash\n# Rotate all pages 90 degrees clockwise\npdftk input.pdf cat 1-endright output rotated.pdf\n\n# Rotate specific pages\npdftk input.pdf cat 1-5 6right 7-end output rotated.pdf\n\n# Options: right (90°), left (270°), down (180°)\n```\n\n### Compress / Reduce file size\n```bash\n# Using ghostscript (adjust quality)\ngs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook \\\n   -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdf\n\n# Quality settings:\n#   /screen   - low quality (72 dpi)\n#   /ebook    - medium (150 dpi)\n#   /printer  - high (300 dpi)\n#   /prepress - highest (300 dpi, preserves color)\n\n# Using qpdf (lossless compression)\nqpdf --linearize --object-streams=generate input.pdf compressed.pdf\n```\n\n### Convert PDF to images\n```bash\n# Convert each page to PNG (300 DPI)\npdftoppm -png -r 300 input.pdf output_prefix\n\n# Output: output_prefix-1.png, output_prefix-2.png, etc.\n\n# Convert to JPEG\npdftoppm -jpeg -r 150 input.pdf output_prefix\n\n# Using ImageMagick (alternative)\nconvert -density 300 input.pdf output_%03d.png\n```\n\n### Add watermark\n```bash\n# Overlay watermark.pdf on every page\npdftk input.pdf stamp watermark.pdf output watermarked.pdf\n\n# Background watermark (behind content)\npdftk input.pdf background watermark.pdf output watermarked.pdf\n\n# Watermark specific pages only\npdftk input.pdf multistamp watermark.pdf output watermarked.pdf\n```\n\n### Get PDF metadata\n```bash\n# Using pdftk\npdftk input.pdf dump_data\n\n# Using qpdf\nqpdf --show-object=1 input.pdf\n\n# Using pdfinfo (poppler-utils)\npdfinfo input.pdf\n```\n\n### Multi-operation script (Node.js)\n```javascript\nconst { PDFDocument } = require('pdf-lib');\nconst fs = require('fs');\n\nclass PDFHelper {\n  static async merge(files, output) {\n    const merged = await PDFDocument.create();\n    for (const file of files) {\n      const pdf = await PDFDocument.load(fs.readFileSync(file));\n      const pages = await merged.copyPages(pdf, pdf.getPageIndices());\n      pages.forEach(p => merged.addPage(p));\n    }\n    fs.writeFileSync(output, await merged.save());\n  }\n\n  static async split(input, ranges, output) {\n    const pdf = await PDFDocument.load(fs.readFileSync(input));\n    const newPdf = await PDFDocument.create();\n    const pages = await newPdf.copyPages(pdf, ranges);\n    pages.forEach(p => newPdf.addPage(p));\n    fs.writeFileSync(output, await newPdf.save());\n  }\n\n  static async info(input) {\n    const pdf = await PDFDocument.load(fs.readFileSync(input));\n    return {\n      pages: pdf.getPageCount(),\n      title: pdf.getTitle(),\n      author: pdf.getAuthor(),\n      creator: pdf.getCreator()\n    };\n  }\n}\n\nmodule.exports = PDFHelper;\n```\n\n## Agent prompt\n```text\nYou have PDF manipulation skills. When a user requests PDF operations:\n\n1. Detect the operation: merge, split, extract (text/images/pages), redact, compress, encrypt, rotate, watermark, or get info.\n2. Use appropriate tools:\n   - pdftk for merge, split, rotate, encrypt, watermark\n   - pdftotext/pdfimages for extraction\n   - ghostscript for compression\n   - qpdf for repair and advanced operations\n3. Always validate input files exist before processing.\n4. For scripting, prefer pdf-lib (Node.js) or PyPDF2 (Python) for portability.\n5. Return structured output (file paths, metadata, text) in JSON format.\n```\n\n## Best practices\n- **Validate PDFs** before processing (use `qpdf --check input.pdf`).\n- **Preserve metadata** when possible (use pdftk or pdf-lib, avoid ghostscript for simple operations).\n- **Use appropriate compression** — ghostscript `/ebook` is a good balance for most cases.\n- **Security** — Always remove passwords before processing if user provides them; never log passwords.\n- **Large files** — For 100+ page PDFs, process in chunks or use streaming APIs.\n\n## Common workflows\n\n### Invoice processing\n```bash\n# 1. Extract text for parsing\npdftotext invoice.pdf invoice.txt\n\n# 2. Extract first page only (summary)\npdftk invoice.pdf cat 1 output summary.pdf\n\n# 3. Compress for archival\ngs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dBATCH -dNOPAUSE -q \\\n   -sOutputFile=invoice_compressed.pdf invoice.pdf\n```\n\n### Batch processing\n```bash\n# Merge all PDFs in a directory\npdftk *.pdf cat output combined.pdf\n\n# Split each PDF in directory into individual pages\nfor f in *.pdf; do\n  pdftk \"$f\" burst output \"${f%.pdf}_page_%02d.pdf\"\ndone\n\n# Extract text from all PDFs\nfor f in *.pdf; do\n  pdftotext \"$f\" \"${f%.pdf}.txt\"\ndone\n```\n\n## Troubleshooting\n- **Corrupted PDF**: Use `qpdf --check` then `qpdf input.pdf --replace-input` to repair.\n- **Encrypted PDF**: Remove password first with `qpdf --decrypt --password=PASS input.pdf output.pdf`.\n- **Large file size**: Use ghostscript compression or remove embedded fonts/images if not needed.\n- **Missing fonts**: Install `fonts-liberation` or `msttcorefonts` packages.\n\n## See also\n- [anonymous-file-upload.md](anonymous-file-upload.md) — Upload processed PDFs anonymously.\n- [using-web-scraping.md](using-web-scraping.md) — Scrape web pages and convert to PDF.","tags":["pdf","manipulation","open","skills","besoeasy","agent-skills","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server"],"capabilities":["skill","source-besoeasy","skill-pdf-manipulation","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-clawdbot","topic-clawdbot-skill","topic-llm-tools","topic-mcp-server","topic-openai","topic-openclaw","topic-vibe-coding","topic-vibecoding"],"categories":["open-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/besoeasy/open-skills/pdf-manipulation","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add besoeasy/open-skills","source_repo":"https://github.com/besoeasy/open-skills","install_from":"skills.sh"}},"qualityScore":"0.505","qualityRationale":"deterministic score 0.51 from registry signals: · indexed on github topic:agent-skills · 111 github stars · SKILL.md body (9,801 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:04.295Z","embedding":null,"createdAt":"2026-04-18T22:10:50.344Z","updatedAt":"2026-05-02T12:55:04.295Z","lastSeenAt":"2026-05-02T12:55:04.295Z","tsv":"'-10':514 '-256':546 '-30':516 '-4':497 '-5':290,297,310,618 '/ebook':646,660,1004,1071 '/prepress':668 '/printer':664 '/screen':655 '02d.pdf':283,1112 '03d.png':727 '1':289,296,309,374,386,416,501,513,607,617,778,904,1043,1060 '1.4':644 '10':292,298 '100':1028 '150':662,715 '180':630 '2':318,496,920,1051 '20':515 '256':551 '270':628 '3':387,943,1063 '300':666,670,696,701,724 '4':951 '5':388,418,502,964 '6right':619 '7':620 '72':658 '90':601,626 'add':70,519,728 'adjust':638 'advanc':116,941 'ae':545 'agent':890 'also':1179 'altern':721 'alway':944,1013 'anonym':1185 'anonymous-file-upload.md':1180,1181 'api':1037 'appropri':922,1001 'apt':127 'apt-get':126 'archiv':1066 'armi':86 'async':221,344,442,569,806,840,870 'author':884 'autom':41 'avoid':995 'await':228,241,246,256,356,361,370,379,452,581,586,812,821,827,837,847,853,857,867,875 'background':742,748 'balanc':1008 'bash':123,167,271,392,463,489,522,597,635,690,730,765,1042,1080 'batch':1078 'behind':744 'best':975 'better':182 'bookmark':171 'brew':138 'burst':280,322,1107 'case':1011 'cat':177,295,500,512,606,616,1059,1089 'check':983,1135 'chunk':1033 'class':803 'clockwis':603 'color':673 'combin':325 'combined.pdf':1091 'command':30 'command-lin':29 'common':36,1038 'compress':119,183,631,677,913,936,1002,1064,1161 'compressed.pdf':651,685 'console.log':460 'const':211,217,226,231,235,239,244,254,334,340,350,354,359,364,368,377,432,436,446,450,559,565,575,579,584,793,799,810,815,819,825,845,851,855,873 'content':745 'convers':121 'convert':12,75,686,691,709,722,1192 'corrupt':1131 'cover':35 'creator':886 'data':451,771 'data.text':456 'databuff':447,454 'dbatch':185,649,1072 'dcompatibilitylevel':643 'decrypt':101,1151 'degre':602 'densiti':723 'dep':157 'detect':905 'directori':1086,1096 'dnopaus':186,647,1073 'document':40,51 'done':1113,1129 'dpdfset':645,1070 'dpi':659,663,667,671,697 'dquiet':648 'dump':770 'e.g':287,316,493 'embed':1164 'empti':200 'encrypt':94,99,523,548,914,929,1144 'encryptedbyt':585,594 'encryptpdf':571 'end':503,621 'endright':608 'etc':477,708 'everi':273,313,317,734 'exist':948 'extract':10,21,61,110,284,301,390,393,401,411,461,464,478,910,933,1044,1052,1114 'extractpag':346,384 'extracttext':444,457 'f':415,1101,1106,1109,1120,1125,1126 'file':6,26,57,224,232,234,238,277,633,808,816,818,824,947,968,1026,1157 'file1.pdf':174,192,202,262 'file2.pdf':175,193,203,263 'file3.pdf':176,194,204 'filepath':445,449 'first':1053,1148 'font':1170,1173 'fonts-liber':1172 'fonts/images':1165 'form':172 'format':81,974 'free':28 'fs':218,220,341,343,433,435,566,568,800,802 'fs.readfilesync':237,352,448,577,823,849,877 'fs.writefilesync':258,381,592,835,865 'function':222,345,443,570 'generat':683 'get':128,762,918 'ghostscript':114,135,145,181,637,934,996,1003,1160 'good':1007 'gs':115,184,640,1067 'high':665 'highest':669 'homebrew':137 'imag':63,78,113,462,466,689 'imagemagick':720 'includ':7 'individu':1098 'info':871,919 'inform':69 'input':538,842,850,872,878,946,1141 'input.pdf':279,294,307,321,385,399,409,419,426,458,471,483,499,511,528,552,605,615,652,684,702,716,725,737,747,757,769,779,786,984,1138,1154 'inputpath':347,353,572,578 'instal':122,129,139,161,1171 'invoic':1040 'invoice.pdf':1049,1058,1077 'invoice.txt':1050 'invoice_compressed.pdf':1076 'j':482 'java':142 'javascript':210,333,431,558,792 'jpeg':480,711,713 'js':154 'json':973 'keep':506 'knife':87 'l':417 'larg':53,1025,1156 'layout':397,406,425 'left':627 'lib':152,209,216,332,339,557,564,798,957,994 'liber':1174 'librari':34 'line':31 'linear':100,679 'log':1023 'lossless':676 'low':656 'maco':136 'manipul':3,4,17,90,896 'manual':324 'medium':661 'merg':8,19,46,91,165,807,811,908,926,1081 'merged.addpage':833 'merged.copypages':828 'merged.pdf':179,191,205,264 'merged.save':838 'mergedbyt':255,260 'mergedpdf':227 'mergedpdf.addpage':252 'mergedpdf.copypages':247 'mergedpdf.save':257 'mergepdf':223,261 'metadata':74,764,970,986 'miss':1169 'module.exports':888 'msttcorefont':1176 'multi':788 'multi-oper':787 'multipl':47 'multistamp':758 'mypassword':533,540 'n':314 'need':1168 'never':1022 'newbyt':378,383 'newpdf':360,852 'newpdf.addpage':375,863 'newpdf.copypages':371,858 'newpdf.save':380,868 'node.js':147,206,329,427,554,791,958 'npm':148 'object':681,777 'object-stream':680 'one':50 'oper':38,789,903,907,942,999 'option':624 'output':178,225,259,281,299,472,474,484,504,517,529,541,609,622,703,705,717,726,740,750,760,809,836,844,866,967,1061,1090,1108 'output.pdf':311,389,553,1155 'output.txt':400,410,420 'output_prefix-000.png':475 'output_prefix-001.jpg':476 'output_prefix-1.png':706 'output_prefix-2.png':707 'outputpath':349,382,574,593 'overlay':731 'ownerpass':550 'ownerpassword':590 'p':832,834,862,864 'packag':1177 'page':59,66,201,245,251,253,268,274,282,286,288,302,308,315,319,348,367,369,376,413,488,492,495,509,596,600,613,693,735,754,826,856,880,1029,1054,1099,1111,1190 'pagenum':365,373 'pages.foreach':250,831,861 'pars':430,441,1047 'part':105 'pass':1153 'password':72,520,526,535,573,589,591,1015,1024,1147,1152 'path':969 'pdf':2,5,16,25,37,89,96,117,151,208,215,240,248,266,331,338,429,437,440,453,468,524,556,563,687,763,797,820,829,846,859,874,895,902,956,993,1088,1094,1103,1110,1122,1127,1132,1145,1194 'pdf-lib':150,207,214,330,337,555,562,796,955,992 'pdf-manipul':1 'pdf-pars':428,439 'pdf.getauthor':885 'pdf.getcreator':887 'pdf.getpagecount':881 'pdf.getpageindices':249,830 'pdf.gettitle':883 'pdfbyte':236,243,351,358,576,583 'pdfdoc':355,372,580 'pdfdoc.save':587 'pdfdocument':212,335,560,794 'pdfdocument.create':229,362,813,854 'pdfdocument.load':242,357,582,822,848,876 'pdfhelper':804,889 'pdfimag':104,469,481 'pdfinfo':781,785 'pdfs':48,54,76,166,978,1030,1083,1118,1184 'pdftk':84,130,141,169,173,278,293,320,498,510,527,536,604,614,736,746,756,767,768,924,990,1057,1087,1105 'pdftk-java':140 'pdftoppm':698,712 'pdftotext':103,398,407,414,423,424,1048,1124 'pdftotext/pdfimages':931 'pdfwrite':189,642,1069 'pip':160 'png':695,699 'poppler':108,133,144,783 'poppler-util':107,132,782 'portabl':963 'possibl':988 'practic':976 'prefer':954 'prefix':473,485,704,718 'preserv':170,197,396,672,985 'process':118,950,980,1017,1031,1041,1079,1183 'prompt':891 'protect':521 'provid':1020 'pure':153 'pw':532,539 'pypdf':163 'pypdf2':162,960 'python':159,961 'q':187,1074 'qpdf':95,131,143,196,199,305,306,422,544,547,675,678,773,774,937,982,1134,1137,1150 'qualiti':639,653,657 'r':700,714 'rang':60,270,303,843,860 'raw':404,408 'redact':11,22,67,486,912 'redacted.pdf':505 'reduc':632 'remov':487,490,494,534,1014,1146,1163 'repair':102,939,1143 'replac':1140 'replace-input':1139 'request':901 'requir':82,213,219,336,342,434,438,561,567,795,801 'return':455,879,965 'right':625 'rotat':93,595,598,611,915,928 'rotated.pdf':610,623 'scrape':1188 'script':327,790,953 'sdevic':188,641,1068 'secur':14,1012 'secured.pdf':530,537 'see':1178 'selected.pdf':518 'sensit':68 'separ':56,276 'set':654 'show':776 'show-object':775 'simpl':998 'size':634,1158 'skill':18,164,897 'skill-pdf-manipulation' 'source-besoeasy' 'soutputfil':190,650,1075 'specif':65,285,412,491,508,612,753 'split':9,20,52,92,265,272,312,841,909,927,1092 'stamp':738 'static':805,839,869 'stream':682,1036 'structur':198,966 'subset.pdf':300 'sudo':125 'summari':1056 'summary.pdf':1062 'swiss':85 'system':156 'text':62,111,391,395,402,892,971,1045,1115 'text/images/pages':911 'titl':882 'tool':32,83,923 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-clawdbot' 'topic-clawdbot-skill' 'topic-llm-tools' 'topic-mcp-server' 'topic-openai' 'topic-openclaw' 'topic-vibe-coding' 'topic-vibecoding' 'transform':24,97 'troubleshoot':1130 'txt':1128 'ubuntu/debian':124 'unlocked.pdf':542 'upload':1182 'use':27,45,168,180,195,421,543,636,674,719,766,772,780,921,981,989,1000,1035,1133,1159 'user':531,900,1019 'userpass':549 'userpassword':588 'using-web-scraping.md':1186,1187 'util':109,134,784 'valid':945,977 'watermark':71,729,743,752,916,930 'watermark.pdf':732,739,749,759 'watermarked.pdf':741,751,761 'web':1189 'workflow':15,42,1039","prices":[{"id":"eb34bee1-2095-4554-bf8c-352fbe790853","listingId":"9450ab57-2a5c-4ffc-b60b-28913a189594","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"besoeasy","category":"open-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:10:50.344Z"}],"sources":[{"listingId":"9450ab57-2a5c-4ffc-b60b-28913a189594","source":"github","sourceId":"besoeasy/open-skills/pdf-manipulation","sourceUrl":"https://github.com/besoeasy/open-skills/tree/main/skills/pdf-manipulation","isPrimary":false,"firstSeenAt":"2026-04-18T22:10:50.344Z","lastSeenAt":"2026-05-02T12:55:04.295Z"}],"details":{"listingId":"9450ab57-2a5c-4ffc-b60b-28913a189594","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"besoeasy","slug":"pdf-manipulation","github":{"repo":"besoeasy/open-skills","stars":111,"topics":["agent-skills","ai","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server","openai","openclaw","vibe-coding","vibecoding"],"license":null,"html_url":"https://github.com/besoeasy/open-skills","pushed_at":"2026-03-31T13:05:30Z","description":"Battle-tested skill library for AI agents. Save 98% of API costs with ready-to-use code for crypto, PDFs, search, web scraping & more. No trial-and-error, no expensive APIs.","skill_md_sha":"153b2237abcf64a1618bcc472377db74a41b18aa","skill_md_path":"skills/pdf-manipulation/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/besoeasy/open-skills/tree/main/skills/pdf-manipulation"},"layout":"multi","source":"github","category":"open-skills","frontmatter":{"name":"pdf-manipulation","description":"Manipulate PDF files including merge, split, extract, redact, convert, and secure workflows."},"skills_sh_url":"https://skills.sh/besoeasy/open-skills/pdf-manipulation"},"updatedAt":"2026-05-02T12:55:04.295Z"}}