PDF Processing
anthropics/skills
Handles everyday PDF jobs in Python and on the command line: extract text and tables, merge, split, rotate, watermark, fill forms, encrypt and OCR.
Reads, extracts from, creates, merges, splits, watermarks, encrypts and fills PDF files with pdfplumber, pypdf and reportlab inside a Python sandbox.
$ npx skills add HKUDS/DeepTutor --skill pdf -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install HKUDS/DeepTutor pdf --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .claude/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .claude/skills/pdf && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .claude/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdfType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add HKUDS/DeepTutor --skill pdf -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install HKUDS/DeepTutor pdf --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .agents/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .agents/skills/pdf && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .agents/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add HKUDS/DeepTutor --skill pdf -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install HKUDS/DeepTutor pdf --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .cursor/skills/pdf && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .cursor/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/HKUDS/DeepTutor.git --path deeptutor/skills/builtin/pdf--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add HKUDS/DeepTutor --skill pdf -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install HKUDS/DeepTutor pdf --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .gemini/skills/pdf && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .gemini/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install HKUDS/DeepTutor pdfInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add HKUDS/DeepTutor --skill pdf -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .github/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .github/skills/pdf && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .github/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add HKUDS/DeepTutor --skill pdf -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install HKUDS/DeepTutor pdf --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/HKUDS/DeepTutor.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/deeptutor/skills/builtin/pdf .opencode/skills/pdf && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "pdf" agent skill from https://github.com/HKUDS/DeepTutor/tree/main/deeptutor/skills/builtin/pdf into .opencode/skills/pdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "pdf", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
pdfReads, extracts from, creates, merges, splits, watermarks, encrypts and fills PDF files with pdfplumber, pypdf and reportlab inside a Python sandbox.
The skill picks a Python library for each PDF job and has the agent run complete scripts in a sandbox. pdfplumber handles text, table, layout and word-coordinate extraction. pypdf covers quick text, merging, splitting, rotating, cropping, watermarking, encryption, decryption and metadata, and fills fillable AcroForm fields. reportlab creates new PDFs from scratch, and flat forms are filled with an annotation overlay.
Tables can be written to Excel with openpyxl, one worksheet per table, and messy tables can be handled by passing line strategies or cropping a region first. If you ask for a size such as 500 words, the agent counts it in the output. Scanned PDFs are treated honestly: with no OCR engine and no network, the agent says the text cannot be recovered instead of making content up or trying to install tools.
Read from SKILL.md and the folder at commit 6cf793b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pipFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use pip, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
PDF Processing with Python loads about 2.7k tokens when it runs. Until then it costs about 52 tokens; SKILL.md has 608 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from HKUDS/DeepTutor at commit 6cf793b, republished under its Apache-2.0 licence (© HKUDS). 608 words, ~2,664 tokens.
.claude/skills/pdf/SKILL.md (or your agent's skills folder).Work PDFs in the sandbox with preinstalled Python libs. Pick the library by task:
pdfplumber; quick raw text or page ops → pypdf.pypdf.pypdf (fillable AcroForm fields) or annotation overlay (flat forms).reportlab.Use exec with complete Python source (language: python). Prefer creating,
reopening, and validating the PDF in one call; later calls can revise the same
relative filename. Follow the turn's User workspace instructions for
locating inputs, output boundaries, and presenting the finished file.
Preserve an explicitly requested quantity (such as 500 words) and verify the count in the output before finishing. If execution fails or the artifact is missing, diagnose stderr/root cause and change strategy; do not retry identical code or reduce the requested scope without asking.
import pdfplumber
with pdfplumber.open("in.pdf") as pdf:
for i, page in enumerate(pdf.pages, 1):
print(f"--- page {i} ---")
print(page.extract_text() or "") # layout-aware text
for t in page.extract_tables(): # list of tables; each is list[row]
for row in t:
print(row)Tables → Excel (one worksheet per table):
import pdfplumber
from openpyxl import Workbook
workbook = Workbook()
workbook.remove(workbook.active)
table_number = 0
with pdfplumber.open("in.pdf") as pdf:
for page_number, page in enumerate(pdf.pages, 1):
for table in page.extract_tables():
if not table:
continue
table_number += 1
sheet = workbook.create_sheet(f"p{page_number}_table{table_number}"[:31])
for row in table:
sheet.append([cell or "" for cell in row])
if table_number:
workbook.save("tables.xlsx")Messy tables: pass strategies, or crop a region with page.within_bbox((x0, top, x1, bottom)) first:
ts = {
"vertical_strategy": "lines",
"horizontal_strategy": "lines",
"snap_tolerance": 3,
"intersection_tolerance": 15,
}
page.extract_tables(ts)For very large PDFs where you only need raw text, pypdf's page.extract_text() is lighter.
If extract_text() returns empty or garbage (e.g. (cid:NN) runs) the page is scanned. No OCR engine (tesseract) is installed and network is off, so you cannot recover that text. Say so plainly and stop — do not fabricate content or attempt pip install.
from pypdf import PdfReader, PdfWriter
# Merge
w = PdfWriter()
for f in ["a.pdf", "b.pdf"]:
for p in PdfReader(f).pages:
w.add_page(p)
w.write("merged.pdf")
# Split: one file per page
r = PdfReader("in.pdf")
for i, p in enumerate(r.pages, 1):
w = PdfWriter()
w.add_page(p)
w.write(f"page_{i}.pdf")
# Rotate page 0 by 90 degrees clockwise
r = PdfReader("in.pdf")
w = PdfWriter()
r.pages[0].rotate(90)
w.add_page(r.pages[0])
w.write("rotated.pdf")PdfReader("in.pdf").metadata (.title, .author, ...).page.mediabox.left/bottom/right/top (points, origin y=0 at bottom).w = PdfWriter(clone_from=PdfReader("in.pdf")); w.encrypt("userpw", "ownerpw"); w.write("enc.pdf").r = PdfReader("enc.pdf"); r.decrypt("pw") if r.is_encrypted, then read/copy pages.Watermark (stamp one page over every page):
from pypdf import PdfReader, PdfWriter
wm = PdfReader("stamp.pdf").pages[0]
r = PdfReader("in.pdf")
w = PdfWriter()
for p in r.pages:
p.merge_page(wm)
w.add_page(p)
w.write("stamped.pdf")Flowing document (preferred for text/reports/tables — handles pagination):
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
styles = getSampleStyleSheet()
story = [
Paragraph("Report Title", styles["Title"]),
Spacer(1, 12),
Paragraph("Body text. " * 20, styles["Normal"]),
]
data = [["Product", "Q1", "Q2"], ["Widgets", "120", "135"]]
tbl = Table(data)
tbl.setStyle(
TableStyle(
[
("BACKGROUND", (0, 0), (-1, 0), colors.grey),
("TEXTCOLOR", (0, 0), (-1, 0), colors.whitesmoke),
("GRID", (0, 0), (-1, -1), 0.5, colors.black),
]
)
)
story += [Spacer(1, 12), tbl]
SimpleDocTemplate("out.pdf", pagesize=letter).build(story)Absolute placement (labels at fixed coordinates): use canvas.Canvas("out.pdf", pagesize=letter), c.drawString(x, y, "...") (origin bottom-left, points), c.showPage() per page, c.save().
reportlab's built-in fonts (Helvetica/Times/Courier) carry zero CJK glyphs, so any 中文/日本語/한국어 renders as empty boxes (□) baked permanently into the PDF. reportlab never auto-discovers system fonts — you MUST register a font that has the glyphs and set it on every style. Whenever the document may contain non-Latin text, register a CJK font first (it also covers Latin, so it is safe to use as the only font):
import os
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
def register_cjk_font(name="CJK"):
# TrueType ONLY — reportlab cannot embed CFF/OpenType outlines, so a .otf
# like Noto Sans CJK fails with "postscript outlines are not supported".
for path in [
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", # Linux sandbox (fonts-wqy-zenhei)
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
"/System/Library/Fonts/STHeiti Light.ttc", # macOS
"/System/Library/Fonts/Hiragino Sans GB.ttc",
"/System/Library/Fonts/Supplemental/Songti.ttc",
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
"C:/Windows/Fonts/msyh.ttc", # Windows
]:
if os.path.exists(path):
try:
pdfmetrics.registerFont(TTFont(name, path, subfontIndex=0))
return name
except Exception:
continue
raise RuntimeError("No CJK-capable TrueType font found — do not emit tofu; say so.")
font = register_cjk_font()
styles = getSampleStyleSheet()
for s in styles.byName.values(): # make the CJK font the default everywhere
s.fontName = font
# Tables don't read the stylesheet — set the font in the TableStyle too:
# ("FONTNAME", (0, 0), (-1, -1), font)
# Canvas: c.setFont(font, size) before every drawString.If register_cjk_font raises (no font on the host), do not ship a tofu PDF — tell the user the sandbox lacks a CJK font instead of producing garbage.
Gotcha: even with a good font, reportlab still needs markup for subscripts/superscripts. In Paragraph use Paragraph("H<sub>2</sub>O", styles["Normal"]), x<super>2</super>.
Markdown/HTML → PDF needs an external converter (soffice/pandoc) that is usually absent — command -v soffice / command -v pandoc and degrade to building the PDF directly with reportlab if neither is present.
First detect whether the PDF has real fillable (AcroForm) fields:
from pypdf import PdfReader
fields = PdfReader("form.pdf").get_fields()
print("fillable" if fields else "flat (no fields)")Fillable — inspect field names/types, then fill and write:
from pypdf import PdfReader, PdfWriter
r = PdfReader("form.pdf")
for name, f in r.get_fields().items():
print(name, f.get("/FT"), f.get("/_States_")) # /Tx text, /Btn checkbox/radio, /Ch choice
w = PdfWriter(clone_from=r)
values = {"first_name": "Bart", "agree": "/Yes"} # checkbox/radio: use its on-state, NOT True/False
for page in w.pages:
w.update_page_form_field_values(page, values, auto_regenerate=False)
w.set_need_appearances_writer(True) # force viewers to render the values
w.write("filled.pdf")Checkbox/radio values are on-state strings, not booleans — read the field's /_States_ (e.g. /Yes, /On); /Off clears it.
Flat form (no fields) — overlay text with FreeText annotations at PDF coordinates. Get real coordinates from the layout with pdfplumber instead of guessing:
import pdfplumber
with pdfplumber.open("form.pdf") as pdf:
pg = pdf.pages[0]
for wd in pg.extract_words(): # each has x0, top, x1, bottom (TOP-left origin!)
print(wd["text"], wd["x0"], wd["top"])
for rc in pg.rects: # small squares are likely checkboxes
print("rect", rc["x0"], rc["top"], rc["x1"], rc["bottom"])pdfplumber top is measured from the page top; pypdf rects are bottom-left, so convert: pdf_y = page_height - top. Place text just right of the matching label:
from pypdf import PdfReader, PdfWriter
from pypdf.annotations import FreeText
r = PdfReader("form.pdf")
w = PdfWriter()
w.append(r)
h = float(r.pages[0].mediabox.height)
top = 700 # pdfplumber 'top' of the label's row
w.add_annotation(
page_number=0,
annotation=FreeText(
text="Smith",
rect=(255, h - top - 14, 720, h - top), # (x0, y0, x1, y1)
font="Helvetica",
font_size="10pt",
font_color="000000",
border_color=None,
background_color=None,
),
)
w.write("filled.pdf")Verify: re-open the output and re-read get_fields() values (fillable) or re-extract text (overlay) to confirm the values landed.
PyMuPDF (imported as fitz, preinstalled) rasterizes pages — useful to inspect a PDF visually or to hand a page to an image-capable step. No external tools needed (poppler / pdf2image are absent; don't reach for them).
import fitz # PyMuPDF
doc = fitz.open("in.pdf")
for i, page in enumerate(doc, 1):
page.get_pixmap(dpi=150).save(f"page_{i}.png") # higher dpi = sharper + largerfitz also extracts text (page.get_text()) and can render a sub-region via page.get_pixmap(clip=fitz.Rect(x0, y0, x1, y1)). It does not OCR — a rendered scanned page is still just pixels (see Scanned PDFs above).
© HKUDS, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in deeptutor/skills/builtin/pdf of HKUDS/DeepTutor.
Open the folder on GitHubat commit 6cf793b
PDF Processing with Python next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| PDF Processing with Python this skillHKUDS/DeepTutor | 41k | — | ~2.7k | Automated safety check: Pass | Apache-2.0 | |
| PDF Processinganthropics/skills | 180k | 48 repos | ~2k | Automated safety check: Pass | Proprietary | |
| PDF ToolkitTokenRhythm/opensquilla | 7.1k | — | ~1.9k | Automated safety check: Pass | Apache-2.0 | |
| PDF ToolkitXiaomiMiMo/MiMo-Code | 14k | — | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| PDF Generation, Forms and Extractionpipeshub-ai/pipeshub-ai | 3.8k | — | ~2.9k | Automated safety check: Pass | Apache-2.0 | |
| PDF Processing Guideagentscope-ai/QwenPaw | 35k | — | ~1.8k | Automated safety check: Pass | Proprietary |
anthropics/skills
Handles everyday PDF jobs in Python and on the command line: extract text and tables, merge, split, rotate, watermark, fill forms, encrypt and OCR.
TokenRhythm/opensquilla
Deterministic PDF operations through bundled scripts: extract text and tables, merge files or page ranges, split by range, fill form fields and build PDFs from data.
XiaomiMiMo/MiMo-Code
Reads, transforms, composes and fills PDFs with Python scripts for extraction, merging, watermarking, encryption, OCR and form filling.
pipeshub-ai/pipeshub-ai
Picks the right library for generating a new PDF, filling an existing PDF form, or extracting text and tables, defaulting to Node where possible.
agentscope-ai/QwenPaw
Handles PDF tasks with Python libraries and command-line tools: extract text and tables, merge, split, rotate, create, fill forms and more.
telagod/code-abyss
Picks the right Python library or CLI tool for a PDF task, text and table extraction, merging, splitting, OCR, watermarking or form filling, and points to a matching recipe.
HKUDS/DeepTutor
Teaches the agent to set up and run DeepTutor from the command line: chat and capabilities, knowledge bases, partners, memory, sessions, notebooks and the server or Web app.
HKUDS/DeepTutor
Reads, creates and edits Word .docx files with python-docx, and drops to raw OOXML for tracked changes, comments and byte-exact edits.
HKUDS/DeepTutor
Explains how to design and write DeepTutor skills: the SKILL.md anatomy, a trigger-focused description, concise content and progressive disclosure into reference files.
HKUDS/DeepTutor
Reads, creates and edits Excel workbooks with openpyxl, including formulas, styles, charts and CSV or TSV tables, with advice on formula values openpyxl cannot compute.
Categories
Reads, extracts from, creates, merges, splits, watermarks, encrypts and fills PDF files with pdfplumber, pypdf and reportlab inside a Python sandbox. The skill picks a Python library for each PDF job and has the agent run complete scripts in a sandbox. pdfplumber handles text, table, layout and word-coordinate extraction.
PDF Processing with Python fits situations like: pulling text or tables out of an uploaded PDF; merging, splitting, rotating or watermarking PDF files; filling in a fillable or flat PDF form; generating a new PDF report from scratch.
Run `npx skills add HKUDS/DeepTutor --skill pdf -a claude-code`. Or copy the skill folder (deeptutor/skills/builtin/pdf in HKUDS/DeepTutor) into .claude/skills/pdf in your project. Claude Code loads it when a task matches its description.
Run `npx skills add HKUDS/DeepTutor --skill pdf -a codex`. Or copy the skill folder (deeptutor/skills/builtin/pdf in HKUDS/DeepTutor) into .agents/skills/pdf in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add HKUDS/DeepTutor --skill pdf -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/pdf, .gemini/skills/pdf, .github/skills/pdf and .opencode/skills/pdf in your project.
Going by SKILL.md and its folder, PDF Processing with Python needs the command-line tools its instructions call (pip). Our summary lists: A Python sandbox with pdfplumber, pypdf and reportlab; openpyxl for exporting tables to Excel.
SKILL.md contains no URLs. Its commands use pip, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
PDF Processing with Python is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with PDF Processing with Python: PDF Processing (anthropics/skills, 180k stars), PDF Toolkit (TokenRhythm/opensquilla, 7.1k stars), PDF Toolkit (XiaomiMiMo/MiMo-Code, 14k stars) and PDF Generation, Forms and Extraction (pipeshub-ai/pipeshub-ai, 3.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
HKUDS (a GitHub organization) maintains it in HKUDS/DeepTutor, which has 40,905 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 8, 2026.
Source: HKUDS/DeepTutor on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.