AI makes PDF.
Teach any LLM to generate professional, PDF/A + PDF/UA compliant documents from natural language. Drop one skill file into your agent, point it at a fast REST API, and ship.
Add it to your agent in 30 seconds
The fastest path: paste the prompt below into your agent and it'll fetch the skill file itself. Want to install it locally? Two coding-agent-friendly options below.
Use this skill to author PDFs: https://makespdf.com/skills/pdf-template-author.md
Any coding agent
Download the file, then register it as a skill, rule, or instruction set in your agent of choice — Claude Code, Codex, OpenCode, Cursor, Windsurf, Copilot, etc.
curl -o pdf-template-author.md \
https://makespdf.com/skills/pdf-template-author.mdThe makesPDF CLI
Prints the skill to stdout — redirect to wherever your agent looks. Also gives the agent validate and preview commands.
npx @makespdf/cli skill > pdf-template-author.md
# or
npm i -g @makespdf/cli && makespdf loginHow it works
The agent writes a tiny JavaScript snippet using a high-level builder DSL — things like doc(), page(), table(), totals(). Our API renders it to a compliant PDF in about a second wall-clock. No layout knowledge required from the model: the DSL encodes professional document patterns (invoices, receipts, CVs, reports) as composable functions.
curl -X POST https://makespdf.com/api/v1/preview \
-H "Authorization: Bearer $MAKESPDF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dsl": "const template = doc({ size: \"A4\" }, page(col(s(\"Hello {{name}}\")))); const sampleData = { name: \"World\" };",
"data": { "name": "Ada" }
}' -o hello.pdfHeadless agents auth in one click
Agents that can't ship a baked-in API key use the OAuth 2.0 device authorization flow (RFC 8628). The agent prints a short code, the user opens a URL, approves once, and the agent receives a persistent key. Same flow as gh auth login — no secrets to manage, no loopback listener required. Full details in the API reference →
Which models can author a PDF?
Internal benchmark — each model gets the skill file as its system prompt, then runs the five test cases below. Up to 5 cycles per test, with structured catalog feedback fed back to the model between cycles.
Build a template from scratch
Given only the data, produce a working DSL template. The data uses non-generic field names (gstRate, gstAmount, NZD currency) the model must respect.
Show instructions + data
The invoice is for a New Zealand company (Solaris Energy) that installs solar panels. Include the GST number and use NZD currency. The data has a `gstRate` and `gstAmount` instead of generic "tax" fields — use those exact field names. The company has an `email` and `gst` field.
{
"invoiceNumber": "INV-7742",
"date": "31 March 2026",
"dueDate": "30 April 2026",
"company": {
"name": "Solaris Energy Ltd",
"address": "12 Harbour View, Level 3",
"city": "Auckland 1010, New Zealand",
"email": "billing@solaris.nz",
"gst": "GST 123-456-789"
},
"customer": {
"name": "Pacific Fresh Exports",
"address": "88 Wharf Road",
"city": "Tauranga 3110, New Zealand",
"email": "accounts@pacificfresh.co.nz"
},
"items": [
{
"description": "Solar panel installation (20kW system)",
"qty": 1,
"unitPrice": "18,500.00",
"amount": "18,500.00"
},
{
"description": "Inverter — SolarEdge SE7600H",
"qty": 3,
"unitPrice": "2,100.00",
"amount": "6,300.00"
},
{
"description": "Mounting hardware and cabling",
"qty": 1,
"unitPrice": "3,200.00",
"amount": "3,200.00"
},
{
"description": "Electrical certification",
"qty": 1,
"unitPrice": "450.00",
"amount": "450.00"
},
{
"description": "Project management",
"qty": 20,
"unitPrice": "95.00",
"amount": "1,900.00"
}
],
"subtotal": "30,350.00",
"gstRate": "15%",
"gstAmount": "4,552.50",
"total": "34,902.50",
"currency": "NZD",
"paymentTerms": "Net 30. Direct credit to Solaris Energy Ltd, ANZ Bank, Account 06-0123-0456789-00. Please reference INV-7742."
}Rewire an existing template
Given the working assets/samples/invoices/invoice-clean-dsl.js template plus data with a different schema (French TVA, EUR, renamed fields), update the template to fit.
Show schema diff
| Kind | Before | After |
|---|---|---|
| renamed | customer | client |
| renamed | customer.country | (merged into client.city) |
| renamed | taxRate | tvaRate |
| renamed | tax | tvaAmount |
| renamed | item.rate | item.unitPrice |
| added | — | currency (was hardcoded $, now EUR) |
| added | — | company.siret, company.tva |
| added | — | client.ustId |
| added | — | legalNotice (must render at bottom) |
| removed | notes | — |
Show instructions + data
The data structure has changed — the customer field is now called `client`, tax is now French TVA (`tvaRate`, `tvaAmount`), currency is EUR, and the company has SIRET and TVA identifiers. There is also a `legalNotice` field that should appear at the bottom.
{
"invoiceNumber": "FAC-2026-031",
"date": "31 March 2026",
"dueDate": "15 April 2026",
"company": {
"name": "Lumière Digital",
"address": "5 Place de la Bourse",
"city": "33000 Bordeaux, France",
"siret": "SIRET 123 456 789 00012",
"tva": "FR 32 123456789"
},
"client": {
"name": "Weinkeller Schmidt GmbH",
"address": "Römerberg 15",
"city": "60311 Frankfurt, Germany",
"ustId": "DE 987654321"
},
"items": [
{
"description": "Refonte site web e-commerce",
"qty": 1,
"unitPrice": "8,500.00",
"amount": "8,500.00"
},
{
"description": "Intégration passerelle de paiement",
"qty": 1,
"unitPrice": "2,200.00",
"amount": "2,200.00"
},
{
"description": "SEO — audit et optimisation",
"qty": 1,
"unitPrice": "1,500.00",
"amount": "1,500.00"
},
{
"description": "Formation CMS (2 sessions)",
"qty": 2,
"unitPrice": "400.00",
"amount": "800.00"
}
],
"subtotal": "13,000.00",
"tvaRate": "20%",
"tvaAmount": "2,600.00",
"total": "15,600.00",
"currency": "EUR",
"paymentTerms": "Virement bancaire sous 15 jours. IBAN: FR76 3000 6000 0112 3456 7890 189. BIC: AGRIFRPP. Mention: FAC-2026-031.",
"legalNotice": "TVA intracommunautaire FR 32 123456789. Pénalités de retard: 3x le taux d'intérêt légal."
}Multi-page invoice with footer
50 line items that span 3+ pages. Tests template:each, repeating page header, and a footer with thisPage() / totalPages() — totals must appear only on the final page.
Show instructions + data
This invoice has 50 line items, so the table will span multiple pages. Use a repeating page header (with the company name) and a footer that shows "Page X of Y" using `thisPage()` and `totalPages()`. Make sure the totals block appears only on the last page (after the table), not after every page.
{
"invoiceNumber": "INV-9001",
"date": "31 March 2026",
"dueDate": "30 April 2026",
"company": {
"name": "Northwind Consulting",
"address": "200 King St W, Suite 1500",
"city": "Toronto, ON M5H 3T4, Canada",
"email": "ar@northwind.example"
},
"customer": {
"name": "Globex Manufacturing",
"address": "1 Industrial Pkwy",
"city": "Hamilton, ON L8E 5K2, Canada"
},
"items": [
{
"description": "Consulting hours — Sprint 1, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 1, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 1, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 1, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 1, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 2, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 2, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 2, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 2, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 2, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 3, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 3, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 3, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 3, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 3, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 4, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 4, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 4, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 4, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 4, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 5, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 5, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 5, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 5, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 5, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 6, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 6, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 6, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 6, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 6, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 7, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 7, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 7, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 7, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 7, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 8, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 8, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 8, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 8, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 8, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 9, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 9, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 9, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 9, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 9, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 10, day 1",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 10, day 2",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 10, day 3",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 10, day 4",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
},
{
"description": "Consulting hours — Sprint 10, day 5",
"qty": 8,
"unitPrice": "175.00",
"amount": "1,400.00"
}
],
"subtotal": "70,000.00",
"taxRate": "13%",
"tax": "9,100.00",
"total": "79,100.00",
"currency": "CAD",
"paymentTerms": "Net 30. Wire transfer to RBC, Account 12345-678901."
}Generate a resume / CV
Distinguishes models that learned the DSL from ones that pattern-matched on invoices. Different structure: name + summary, then iterated experience with nested bullets, skills, education.
Show instructions + data
Generate a clean single-column resume (CV) — name + title at the top, contact line, summary paragraph, then sections for Experience, Skills, and Education. Use `template:each` to iterate experience entries and bullets. Section headings should be visually distinct (bold, slight underline or top border).
{
"name": "Avery Chen",
"title": "Senior Software Engineer",
"contact": {
"email": "avery.chen@example.com",
"phone": "+1 415 555 0148",
"location": "San Francisco, CA",
"linkedin": "linkedin.com/in/averychen"
},
"summary": "Backend engineer with 9 years building distributed systems. Led migration of a 4-region payments platform from monolith to event-driven services with zero downtime.",
"experience": [
{
"role": "Staff Engineer",
"company": "Lumen Payments",
"period": "2022 – Present",
"bullets": [
"Designed event-driven settlement pipeline processing $2B/month",
"Mentored team of 6 engineers, ran biweekly architecture reviews",
"Cut p99 latency 4x via per-shard read replicas"
]
},
{
"role": "Senior Engineer",
"company": "Helix Robotics",
"period": "2018 – 2022",
"bullets": [
"Built fleet telemetry ingest handling 50k events/sec",
"Owned on-call rotation and SLO instrumentation"
]
},
{
"role": "Software Engineer",
"company": "Pixelforge",
"period": "2015 – 2018",
"bullets": [
"Shipped real-time collaboration features for vector editor"
]
}
],
"skills": [
"Go",
"Rust",
"PostgreSQL",
"Kafka",
"Kubernetes",
"Terraform"
],
"education": [
{
"degree": "B.S. Computer Science",
"school": "University of Waterloo",
"period": "2011 – 2015"
}
]
}Repair a broken template
Three deliberate errors: a plain-string child in col(...), a style object passed as a second argument to s(...) (lands in the span's kids instead of applying styles), and a template:each loop variable that doesn't match the {{...}} references. Tests debugging — the most common real-world skill use.
Show instructions + broken DSL
This template fails validation. There are three problems: 1. `col` cannot contain a plain-string child — `"Summary"` must be wrapped in a span: `s({ "font-size": 14, "font-weight": "bold" }, "Summary")`. 2. `s("{{row.value}}", { align: "right" })` passes a style object as a second argument, which lands inside the span's children. Right-align via the cell tuple instead: `[s("{{row.value}}"), "auto", "right"]` (or put align on the column). 3. The loop is declared `"r in metrics"` but the cells reference `{{row.name}}` / `{{row.value}}` — the loop variable must match the references. Use `"row in metrics"`. Fix all three problems and output the corrected DSL. Output ONLY the corrected JavaScript.
// This template is broken. Fix it.
const template = doc({ size: "A4" },
page(
hdr(s("Quarterly Report — {{quarter}}")),
col(
"Summary",
s("{{summary}}"),
gap(12),
s({ "font-weight": "bold" }, "Metrics"),
table([["Metric", "1fr"], ["Value", "auto", "right"]], "r in metrics", [
[s("{{row.name}}")],
[s("{{row.value}}", { align: "right" })],
]),
),
),
ftrPages(),
);
const sampleData = {
quarter: "Q1 2026",
summary: "Revenue up 18% YoY. Churn flat at 2.1%.",
metrics: [
{ name: "Revenue", value: "$4.2M" },
{ name: "Churn", value: "2.1%" },
],
};
Four-turn conversational edit chain
Closest test to the real /ai/chat use case: starts from a working invoice, fires four scripted plain-English edit requests, and verifies every prior intent still holds on the final template. Each turn gets up to five catalog-feedback cycles before moving on — same two-layer loop the chat applies via commit_dsl.
Show the four turns
- Make the totals row bold.
- Change the document font to NotoSans, size 10.
- Add a centered "Thank you for your business." line below the totals (small, italic).
- Add a 1pt bottom border under the table header row so it visually separates from the line items.
Columns
- Total time — sum of wall-clock time across every attempt in every test. The most direct measure of "how long would this model take on real work?". A self-correcting model that takes 5 cycles to pass shows 5× the cost of a model that converges on the first try; per-call latency can be inferred as Total ÷ (Cycles × 6).
- Out tokens — sum of output tokens across all attempts in the run.
- DSL — final-attempt count of tests where the model's DSL parsed and validated against the catalog without errors. This says nothing about whether the PDF actually rendered.
- Rendered — count of tests that produced a PDF end-to-end (valid DSL and the render pipeline succeeded). The real success metric: a 5/5 here is a model you can ship.
- Skill — first-attempt compliance score (0–1), mean of the static-check modules that apply to each generated template. Scoring only the first attempt isolates raw skill comprehension from self-correction (later cycles get structured catalog feedback). See the two modules below.
- Run cost — sum of input + output token cost across all attempts at published OpenRouter prices.
Column widths follow the skill's guidance
Numeric columns use auto instead of a fixed % width (so wide values don't wrap and drop), and at least one column uses 1fr / auto / auto-stretch to absorb surplus width when a description column is present.
Every variable reference resolves
Each {{...}} reference in the generated DSL points at a path that exists in the model's own sampleData — no broken bindings, typos, or made-up fields.
| Cycles | ||||||||
|---|---|---|---|---|---|---|---|---|
| claude-opus-4.7 | 27,709 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 0.99 | 3m 55s | $2.85 | |
| gpt-5-mini | 30,126 | 6/6 | ⌀ 1.7 cyc · 100% clean | 6/6 | 0.93 | 4m 14s | $0.12 | |
| gpt-5.4-nano | 33,241 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 0.99 | 4m 17s | $0.10 | |
| qwen3.5-122b-a10b | 30,604 | 6/6 | ⌀ 2.5 cyc · 100% clean | 6/6 | 0.99 | 5m 39s | $0.24 | |
| gpt-5.5 | 21,076 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 0.99 | 5m 45s | $2.04 | |
| minimax-m2.7 | 19,945 | 6/6 | ⌀ 1.5 cyc · 83% clean | 6/6 | 1.00 | 6m 5s | $0.09 | |
| grok-4-fast | 47,018 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 0.98 | 7m 58s | $0.08 | |
| deepseek-v4-flash · OpenRouter | 27,682 | 6/6 | ⌀ 2.0 cyc · 100% clean | 6/6 | 0.99 | 8m 46s | $0.05 | |
| gpt-5.4 | 32,122 | 6/6 | ⌀ 1.7 cyc · 100% clean | 6/6 | 0.99 | 9m 28s | $1.13 | |
| claude-haiku-4.5 | 99,966 | 6/6 | ⌀ 2.0 cyc · 100% clean | 6/6 | 0.99 | 10m 30s | $0.85 | |
| deepseek-v4-flash · OpenCode Go | 88,666 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 1.00 | 10m 37s | $0.07 | |
| claude-sonnet-4.6 | 49,237 | 6/6 | ⌀ 1.7 cyc · 100% clean | 6/6 | 1.00 | 10m 40s | $1.66 | |
| gpt-5 | 36,121 | 6/6 | ⌀ 1.8 cyc · 100% clean | 6/6 | 1.00 | 12m 28s | $0.71 | |
| gemini-2.5-pro | 119,230 | 6/6 | ⌀ 2.8 cyc · 100% clean | 6/6 | 0.99 | 18m 1s | $1.79 | |
| deepseek-v4-flash-0731 | 58,299 | 6/6 | ⌀ 1.5 cyc · 100% clean | 6/6 | 0.99 | 23m 25s | $0.03 | |
| glm-4.6 | 28,540 | 6/6 | ⌀ 2.5 cyc · 100% clean | 6/6 | 0.99 | 28m 42s | $0.20 | |
| grok-4 | 72,744 | 6/6 | ⌀ 3.0 cyc · 100% clean | 6/6 | 1.00 | 42m 46s | $2.42 | |
| kimi-k2.6 | 126,422 | 6/6 | ⌀ 2.0 cyc · 100% clean | 6/6 | 1.00 | 85m 33s | $0.66 | |
| gpt-5.1-codex-mini | 76,441 | 5/6 | ⌀ 2.5 cyc · 83% clean | 6/6 | 1.00 | 8m 50s | $0.25 | |
| deepseek-v4-pro | 40,512 | 5/6 | ⌀ 2.5 cyc · 83% clean | 6/6 | 0.99 | 26m 36s | $0.20 | |
| glm-4.7 | 81,134 | 5/6 | ⌀ 2.5 cyc · 83% clean | 6/6 | 1.00 | 58m 57s | $0.30 | |
| grok-4.20 | 91,564 | 4/6 | ⌀ 2.8 cyc · 67% clean | 6/6 | 0.99 | 18m 14s | $0.75 | |
| qwen3.6-max-preview | 82,797 | 4/6 | ⌀ 2.8 cyc · 67% clean | 6/6 | 0.99 | 57m 34s | $0.98 | |
| mistral-medium-3-5 | 18,954 | 5/6 | ⌀ 2.5 cyc · 83% clean | 5/6 | 1.00 | 2m 15s | $0.73 | |
| gpt-5.4-mini | 45,728 | 5/6 | ⌀ 2.0 cyc · 83% clean | 5/6 | 0.99 | 6m 11s | $0.43 | |
| llama-4-maverick | 14,375 | 5/6 | ⌀ 2.0 cyc · 83% clean | 5/6 | 0.99 | 7m | $0.05 | |
| qwen3-32b | 38,096 | 5/6 | ⌀ 2.0 cyc · 67% clean | 5/6 | 0.94 | 17m 49s | $0.04 | |
| gemma-3-12b-it | 13,194 | 5/6 | ⌀ 1.5 cyc · 83% clean | 4/6 | 0.90 | 9m 27s | $0.01 | |
| minimax-m3 | 52,043 | 4/6 | ⌀ 2.2 cyc · 67% clean | 4/6 | 1.00 | 44m 10s | $0.16 | |
| kimi-k2 | 14,289 | 3/6 | ⌀ 2.7 cyc · 50% clean | 3/6 | 1.00 | 6m 37s | $0.25 |
Refreshed periodically. Click a column header to sort, or a model row to see per-test status, errors, and download the rendered PDF / generated DSL. All models are routed through OpenRouter. Download as Markdown or JSON — leaderboard + per-model narrative + failing-DSL snippets (markdown only), sized to drop straight into an AI assistant.
Next steps
- Full agent setup walkthrough — per-tool instructions, validation, error handling
- API reference — every endpoint, every option
- Read the raw skill file — single source of truth for the DSL
- llms-full.txt — LLM-crawler manifest with the skill inlined