# Toolshed — tools for agents · a Lemon field directory Tools an agent can call over HTTP with nothing installed, plus local-only references for the jobs we do not host. 5 hosted · 28 local references. 10 free conversions a day on every hosted tool. The unit is the pair — what you have, what you need. Structured fields are in catalog.json alongside this file; the full verdicts, caveats and escalate lines are in llms-full.txt. Availability check: GET https://toolshed.lemon-agent.dev/check?from=&to= Field-bound substring match, case-insensitive: from is matched against the "have" side only, to against the "need" side only. No parameters returns every hosted tool. Convert: POST https://toolshed.lemon-agent.dev/convert/ with the raw file as the body (256 KB cap). The converted file comes back as the body, with the right Content-Type. Tiers: every hosted tool is free to try — 10 conversions per caller per UTC day, no login — and priced per call past that. A caller is an IP address (rotating the user-agent does not reset it); every free-tier response carries x-free-tier-remaining: , and the count resets at midnight UTC. Payment: past the free tier a call answers HTTP 402 with an x402 envelope (USDC on Base). No accounts, no keys, per-call pricing. Pay with an x402-capable client (x402-fetch, the x402 SDK, Coinbase AgentKit) holding a wallet key with USDC on Base; it signs and retries with an X-PAYMENT header. NOT SWITCHED ON YET: with no receiving address configured, a call past the free tier answers HTTP 429 with a Retry-After instead of a 402, and nothing verifies settlement — a response that sees an X-PAYMENT header says x-payment-verified: false rather than treating it as paid. Skill: npx skills add chronick/lemon-toolshed MCP: claude mcp add toolshed -- npx -y github:chronick/lemon-toolshed Tools: toolshed_check, toolshed_convert, toolshed_catalog. Base URL via TOOLSHED_URL. Editorial stance: Post a file to a hosted tool and read the converted file back — nothing to install. Where we do not host the job, the entry names the tool worth reaching for and what bites about it. We prefer the plain deterministic tool wherever one works, and a model only where the answer is a judgment call. ## Documents & markup Saved HTML page / static HTML file -> Markdown [html-markdown]: hosted live, 10/day free, then $0.001/call · x402, at POST /convert/html-markdown; local pandoc (deterministic) — For HTML already on disk, pandoc's reader is exact and fast, and `--wrap=none` keeps the output diff-friendly. — https://pandoc.org Markdown -> HTML [md-html]: hosted live, 10/day free, then $0.001/call · x402, at POST /convert/md-html; local pandoc (deterministic) — Markdown to HTML is a solved parse, so the only real questions are which dialect and which extensions. — https://pandoc.org Markdown (with math, code blocks, citations) -> PDF [markdown-to-pdf]: local only; local pandoc (deterministic) — Pandoc plus a Typst or LaTeX engine gives the same PDF on every run, with real pagination, footnotes and cross-references. — https://pandoc.org Markdown -> DOCX styled to a house template [markdown-to-docx]: local only; local pandoc (deterministic) — `--reference-doc=template.docx` maps headings, tables and code blocks onto a real Word style sheet, so a human reviewer gets an editable document instead of a wall of Normal-styled text. — https://pandoc.org DOCX -> Markdown + extracted media [docx-to-markdown]: local only; local pandoc (deterministic) — Pandoc reads the DOCX XML directly, so headings, lists, tables and footnotes land as real Markdown structure, and `--extract-media` writes embedded images to disk instead of dropping them. — https://pandoc.org Live DOM in a browser or headless page (JS-rendered) -> Markdown [rendered-dom-to-markdown]: local only; local turndown (deterministic) — When the content only exists after JavaScript runs, the conversion belongs where the DOM is — Turndown runs in-page or in Node against a parsed DOM and takes custom rules for app-specific markup. — https://github.com/mixmark-io/turndown Markdown (multi-chapter manuscript) -> EPUB 3 [markdown-to-epub]: local only; local pandoc (deterministic) — `pandoc -o book.epub` produces a valid EPUB with a real table of contents, metadata and chapter splitting via `--split-level`; readers care about that structure far more than typography. — https://pandoc.org DOCX/XLSX/PPTX (batch) -> PDF [office-docs-to-pdf-batch]: local only; local libreoffice (deterministic) — `soffice --headless --convert-to pdf --outdir out/ *.docx` is the only free path that renders Office layout faithfully enough to hand to someone, and it batches on a server with no Office licence. — https://www.libreoffice.org HTML + CSS (invoice, report, generated page) -> Paginated PDF [html-to-paginated-pdf]: local only; local weasyprint (deterministic) — WeasyPrint implements print CSS — `@page`, running headers, page counters — so a report template paginates the same way in CI as on your laptop, with no browser in the image. — https://weasyprint.org Messy document (invoice, contract, report PDF/DOCX) -> Structured records against a schema [messy-doc-to-schema]: local only; local unstructured (hybrid) — Split the job rather than the tool: deterministic partitioning (unstructured's parsers, or pdftotext/pdfplumber) yields elements, positions and tables, and a model is asked only for the fields that are genuinely judgment — which of these three numbers is "the total", is this clause an indemnity. — https://github.com/Unstructured-IO/unstructured MOBI/AZW3/LIT and other legacy ebook formats -> EPUB [legacy-ebook-to-epub]: local only; local calibre (deterministic) — `ebook-convert in.azw3 out.epub` carries the TOC, metadata and internal links across a dozen legacy formats — a decade of accumulated format edge cases you should not re-derive. — https://calibre-ebook.com ## PDF PDF (digital-born — has a text layer) -> Plain text / layout-preserved text [pdf-digital-born-to-text]: local only; local pdftotext (deterministic) — If `pdftotext -layout` returns real text, the job is already finished — the characters are in the file and extraction is exact and instant. — https://poppler.freedesktop.org PDF (scanned — page images, no text layer) -> Searchable PDF + extractable text [pdf-scanned-to-searchable]: local only; local ocrmypdf (hybrid) — ocrmypdf adds an invisible text layer to the original pages, so the file stays a faithful scan and becomes greppable and citable; `--skip-text` and `--redo-ocr` make it safe to sweep a mixed directory. — https://ocrmypdf.readthedocs.io PDF page(s) -> PNG/JPEG page images [pdf-to-page-images]: local only; local pdftoppm (deterministic) — `pdftoppm -r 200 -png` renders pages reproducibly and is the correct pre-step whenever OCR or a vision model is the next stage, because you control DPI, page range and colour — which is exactly what downstream accuracy depends on. — https://poppler.freedesktop.org PDF with ruled or whitespace-aligned tables -> CSV / DataFrame [pdf-tables-to-csv]: local only; local camelot (deterministic) — Camelot's lattice mode reconstructs cells from the table's actual ruling lines, so on a bordered table it is exact rather than approximate; stream mode handles whitespace-aligned tables with more supervision. — https://github.com/camelot-dev/camelot ## Data & tabular JSON -> YAML [json-yaml]: hosted live, 10/day free, then $0.001/call · x402, at POST /convert/json-yaml; local yq (deterministic) — mikefarah's yq speaks both formats natively (`yq -P`) and preserves comments through YAML edits, which is the whole reason to use it on real config files. — https://github.com/mikefarah/yq YAML -> JSON [yaml-json]: hosted live, 10/day free, then $0.001/call · x402, at POST /convert/yaml-json; local yq (deterministic) — `yq -o=json` is the local answer, and the direction that bites is this one: YAML is the larger language, so anchors, multi-document streams and unquoted `no`/`yes` all have to land somewhere in JSON. — https://github.com/mikefarah/yq CSV -> JSON [csv-json]: hosted live, 10/day free, then $0.001/call · x402, at POST /convert/csv-json; local csvkit (deterministic) — `csvjson data.csv` turns a header row plus records into an array of objects, which is the shape almost everything downstream wants. — https://csvkit.readthedocs.io Nested JSON from an API -> Flat JSON / NDJSON / CSV rows [json-reshape]: local only; local jq (deterministic) — jq is a real language for this: `-r`, `@csv`, `to_entries`, `group_by` cover most reshapes in a line, and the result is an auditable program you can re-run on tomorrow's payload. — https://jqlang.github.io/jq/ Messy CSV (ragged rows, BOM, mixed quoting, duplicate headers) -> Clean, validated UTF-8 CSV [messy-csv-to-clean-csv]: local only; local qsv (deterministic) — `qsv input` normalizes quoting and line endings, and `validate`/`headers`/`dedup` tell you what is actually wrong before the data reaches anything downstream — all at streaming speed on files far past spreadsheet size. — https://github.com/dathere/qsv XLSX workbook (specific sheet) -> CSV [xlsx-to-csv]: local only; local csvkit (deterministic) — `in2csv --sheet "Sheet2" book.xlsx` gets the sheet you asked for with stable typing and scripts across a directory. — https://csvkit.readthedocs.io Large CSV -> Queryable SQLite database [csv-to-sqlite]: local only; local sqlite3 (deterministic) — `.import --csv data.csv t` buys you indexes, joins and SQL over a file too big for a spreadsheet, with no service and no ORM. — https://sqlite.org/cli.html SQLite query result -> JSON / NDJSON for an API or an agent [sqlite-to-json]: local only; local sqlite3 (deterministic) — `sqlite3 -json db.sqlite "select ..."` (or `.mode json`) emits valid JSON straight from the CLI, composes with jq in a pipe, and needs no serialization layer. — https://sqlite.org/cli.html ## Images HEIC/HEIF photos from an iPhone -> JPEG [heic-to-jpeg]: local only; local imagemagick (deterministic) — `magick mogrify -format jpg -quality 88 *.heic` converts a folder in one line and keeps EXIF, which matters when the timestamps are the reason you kept the photos. — https://imagemagick.org Large batch of source images -> Web-sized JPEG/WebP/AVIF derivatives [bulk-image-resize]: local only; local libvips (deterministic) — `vipsthumbnail` streams through a batch on a small memory footprint and gets the defaults right — shrink-on-load for JPEG, sane colour handling. — https://www.libvips.org Static SVG -> PNG at a chosen scale [svg-to-png]: local only; local resvg (deterministic) — resvg renders an SVG to PNG with no browser and no JS runtime, so it runs in CI and produces the same bytes run after run. — https://github.com/linebender/resvg Image of text (screenshot, clean scan, photo) -> Plain text [image-to-text]: local only; local tesseract (model) — Tesseract is a fixed local model — same input, same output, no API, nothing leaving the machine — and `--psm` is the knob that actually matters (6 for a block, 7 for a single line). — https://github.com/tesseract-ocr/tesseract ## Audio & video Arbitrary video (any container/codec) -> H.264 MP4 that plays everywhere [video-to-portable-mp4]: local only; local ffmpeg (deterministic) — `-c:v libx264 -crf 20 -preset slow -c:a aac -movflags +faststart` is the boring correct answer for delivery: CRF targets quality rather than a guessed bitrate, and faststart lets playback begin before the file finishes downloading. — https://ffmpeg.org Video file with an audio track -> Audio file (m4a/wav) [video-to-audio-track]: local only; local ffmpeg (deterministic) — `ffmpeg -i in.mp4 -vn -c:a copy out.m4a` lifts the existing audio stream with no re-encode and no generation loss; switch to `-c:a pcm_s16le out.wav` only when the next tool demands PCM. — https://ffmpeg.org WAV / FLAC / arbitrary audio -> MP3 or Opus at a fixed sample rate and loudness [audio-transcode-and-normalize]: local only; local ffmpeg (deterministic) — ffmpeg does the format change, the resample (`-ar`) and loudness normalization (`loudnorm`) in a single pass, which matters because chaining separate tools resamples twice and compounds artifacts. — https://ffmpeg.org Recorded speech (meeting, interview, podcast) -> Transcript (text/SRT/VTT) [speech-audio-to-transcript]: local only; local whisper.cpp (model) — This pair has no deterministic answer; speech-to-text is model work and pretending otherwise wastes a day. — https://github.com/ggml-org/whisper.cpp ## Files, encodings & metadata Photo / video / PDF file -> Structured metadata (JSON) [media-to-metadata-json]: local only; local exiftool (deterministic) — `exiftool -json -r dir/` reads (and writes) metadata across essentially every format and tag standard, which makes it the right first move before any lossy pipeline: capture the metadata, then convert. — https://exiftool.org Text/CSV in a legacy encoding (CP-1252, Latin-1, Shift-JIS) showing mojibake -> Clean UTF-8 [legacy-encoding-to-utf8]: local only; local iconv (deterministic) — `iconv -f WINDOWS-1252 -t UTF-8` fixes the entire class of "why are there  characters" bugs in one pass once you know the source encoding; pair it with `uchardet` or `file -I` to guess. — https://www.gnu.org/software/libiconv/