Best for
- A research report, brief, or summary the user wants as a downloadable file.
- A subagent (e.g. the researcher) handed you a research-.md to ship as a PDF.
- Any channel message asking for "a PDF" / "the report attached" / "예쁘게 PDF로".
typeclaw/typeclaw/src/bundled-plugins/doc-render/skills/typeclaw-render-pdf/SKILL.md
The ONLY supported way to render Markdown into a polished, professional PDF (and optionally attach it to a channel). Load this whenever you need to deliver a document as a PDF rather than raw markdown — reports, summaries, briefs, meeting notes, docs, render report, export document, anything a human would want to download, print, or forward, including a researcher's report file shipped as a Slack/Discord attachment. Triggers: 'make a PDF', 'export to PDF', 'markdown to PDF', 'PDF report', 'rende
Decision brief
You can produce professional PDFs from Markdown. The bundled doc-render plugin ships two things: a themed report library (lib.typ) that does all the styling, and a render script that does the compile. The only thing installed on demand is the Typst compiler — a single npm packag…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/typeclaw/typeclaw --skill "src/bundled-plugins/doc-render/skills/typeclaw-render-pdf"Inspect the Agent Skill "typeclaw-render-pdf" from https://github.com/typeclaw/typeclaw/blob/e525119cd01aad6b88f905daa7f532bd8ca84acd/src/bundled-plugins/doc-render/skills/typeclaw-render-pdf/SKILL.md at commit e525119cd01aad6b88f905daa7f532bd8ca84acd. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
The PDF compiler is not baked into the image — install it on first use. It is a single version-pinned npm package (npm pulls only this platform's prebuilt binary — Linux x64/arm64, glibc or musl). Install it in the session's writable /tmp runtime; the agent-root dependency tree…
Use an existing markdown file (yours or a subagent's), or write your content to a markdown file. Standard CommonMark plus tables and footnotes all work. Put the .md, the copied lib.typ, and the .typ wrapper (Step 2) in the same directory so the wrapper's relative read("...") and…
First, copy the bundled theme library next to your markdown (Typst's workspace sandbox only resolves imports under the render's working directory, so the library must sit beside the wrapper — an absolute import from outside won't resolve):
The render script is bundled with the plugin — you do not write it. It lives at /agent/nodemodules/typeclaw/src/bundled-plugins/doc-render/render.ts.
Use a human-friendly filename and an absolute path. Slack, Discord, Telegram, and KakaoTalk upload the file; LINE and the GitHub adapter have no attachment support, so there post a link or paste the markdown.
Permission review
The documentation asks the agent to run terminal commands or scripts.
4-line wrapper that picks a **theme**, **(4)** run the render script. If a channelThe documentation asks the agent to run terminal commands or scripts.
bun add @myriaddreamin/[email protected]The documentation asks the agent to create, modify, or delete local files.
Only after the user agrees: edit `typeclaw.json` to set `docker.file.cjkFonts:Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 93/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 57 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
You can produce professional PDFs from Markdown. The bundled doc-render plugin
ships two things: a themed report library (lib.typ) that does all the
styling, and a render script that does the compile. The only thing installed
on demand is the Typst compiler — a single npm package the
agent bun adds into writable session scratch the first time you need a PDF,
then reuses for that session. No Pandoc, no LaTeX, no headless browser, no PDF toolchain baked
into the image.
The flow is: (1) install the compiler once (bun add), (2) have your
Markdown ready, (3) copy the theme library next to it and write a tiny
4-line wrapper that picks a theme, (4) run the render script. If a channel
asked for the PDF, attach the result with channel_send.
You do not write Typst markup or hand-style anything. The library's
report template styles every Markdown element — headings, lists, tables, code,
quotes, links, figures — and adds a cover, running header, and page footer. The
cmarker package converts your
CommonMark to Typst; the theme makes it look designed. Your only real choice is
which theme fits the document.
This is the only supported way to make a PDF from Markdown in TypeClaw. Do not reach for
jsPDF,pdfkit, a<canvas>text dump, a headless-browser "print raw text" path, or PythonReportLab. Those skip Markdown rendering (you get literal##and**in the output) and ship no CJK font, so Korean/Japanese/Chinese come out as mojibake. The Typst path below renders the Markdown properly. If you catch yourself about tobun adda PDF library other than the Typst compiler named here, stop.
researcher) handed you a research-<slug>.md to ship as a PDF.When plain markdown in chat is fine, don't make a PDF. This is for when a file is the deliverable.
The PDF compiler is not baked into the image — install it on first use. It is a
single version-pinned npm package (npm pulls only this platform's prebuilt
binary — Linux x64/arm64, glibc or musl). Install it in the session's writable
/tmp runtime; the agent-root dependency tree is protected read-only:
mkdir -p /tmp/typeclaw-doc-render-runtime && cd /tmp/typeclaw-doc-render-runtime
bun add @myriaddreamin/[email protected]
The @0.7.0 pin embeds Typst 0.14.2 and keeps the toolchain reproducible. If you
forget this step, the render script in Step 3 stops with the exact bun add line
to run, so you can also just try the render and follow its guidance.
Where it goes:
/tmp/typeclaw-doc-render-runtime, backed by TypeClaw's per-session scratch directory. It is writable to model-driven bash and reused across calls in the same session, but not promised across container restarts. Do not modify/agent/node_modulesor create a dependency tree underworkspace/.
Use an existing markdown file (yours or a subagent's), or write your content to
a markdown file. Standard CommonMark plus tables and footnotes all work. Put the
.md, the copied lib.typ, and the .typ wrapper (Step 2) in the same
directory so the wrapper's relative read("...") and #import "lib.typ" both
resolve. Any agent-writable directory works (workspace/, public/, mounts/,
or wherever the source .md already lives, e.g. a researcher's report under
public/). There is no required directory; keep the three files together and run
the render from there.
First, copy the bundled theme library next to your markdown (Typst's workspace sandbox only resolves imports under the render's working directory, so the library must sit beside the wrapper — an absolute import from outside won't resolve):
cd /agent/workspace # or wherever your .md lives (public/, mounts/, …)
cp /agent/node_modules/typeclaw/src/bundled-plugins/doc-render/templates/lib.typ .
Then write a tiny .typ wrapper next to the markdown. This is the entire
wrapper — you do not style anything yourself; the theme does it:
#import "lib.typ": report, callout, kpi, kpi-row, pullquote
#show: report.with(
theme: "editorial", // editorial | modern | report | minimal
title: "Edge-AI Quarterly Brief",
subtitle: "Q2 2026 · Internal Distribution",
date: "2026-06-17",
author: "Research",
)
#import "@preview/cmarker:0.1.8"
#cmarker.render(
read("report.md"),
h1-level: 1,
blockquote: quote.with(block: true),
// makes the helpers available to <!--raw-typst …--> snippets in the markdown
scope: (callout: callout, kpi: kpi, kpi-row: kpi-row, pullquote: pullquote),
)
Pick the one that fits the document's purpose. All four are built on the fonts that ship in the container, so they render identically everywhere.
editorial — magazine look: a dedicated cover page, smallcaps tracked
headings, booktabs tables, wine accent. The elegant default for prose: reports,
briefs, memos, articles.modern — startup look: a bold bleed-bar masthead, accent-bar headings,
airy ragged-right, indigo accent, accent-header tables. Product/launch briefs,
updates, anything that should feel current.report — data / consulting look: a cover page with a full accent band,
accent-ruled section heads, strong navy zebra tables, plus kpi() and
pullquote() helpers. Boardroom-ready analyses and data reports.minimal — Apple-clean: a spacious title block, large light headings, no
running header, generous margins, ultra-light tables. Short notes, letters,
one-pagers.When unsure, use editorial. If a user said the last PDF looked plain, try
modern or report (the most visibly "designed") and apply the tips below.
accent: rgb("#0f766e") — override the theme's accent color (links, rules,
headings, cover, table headers). Omit or pass accent: auto for the theme
default.cover: "page" | "masthead" | "title" | none — override the cover treatment
(page = dedicated cover page, masthead = bold top block, title = compact
title block), or none to drop it (e.g. a short memo). Omit for the theme
default.title entirely and no cover is drawn — useful when the markdown already
opens with its own H1.The render script is bundled with the plugin — you do not write it. It lives
at /agent/node_modules/typeclaw/src/bundled-plugins/doc-render/render.ts.
You should already be cd'd into the directory holding your .typ, .md, and
the copied lib.typ (from Step 2). The wrapper's read("report.md") and
#import "lib.typ" both resolve relative to the render's working directory, so
you must run it from there:
cd /agent/workspace # or wherever your .typ + .md + lib.typ live
bun run /agent/node_modules/typeclaw/src/bundled-plugins/doc-render/render.ts report.typ report.pdf
On success it prints wrote report.pdf (<N> bytes) and report.pdf exists in
that directory.
If it stops with @myriaddreamin/typst-ts-node-compiler is not installed
(exit 3), run the Step 0 bun add and re-run. If it stops with a NotDir /
ENOTDIR error, that is the sandbox /proc degraded mode, not your markup and
not a font — retry once; if it persists, report it as a sandbox/environment
issue and do not switch to another PDF library (it won't help). Any other
error is a real Typst compile error (usually raw HTML or an unsupported markdown
extension) and names the offending line — simplify that part and re-run.
A theme gets you 90% of the way. The rest is content discipline — the same things that separate a designed document from a markdown dump:
Front-load structure. A short lead paragraph under the title, then clear
## sections. Don't open with a wall of text.
Tables over repeated bullet stanzas. If you're repeating the same fields per item (name, value, status…), a table reads far better than N bullet lists. The theme styles tables with clean rules and a header row.
Caption your images so they read as figures, not floating screenshots:
<!--raw-typst
#figure(image("chart.png", width: 80%), caption: [Revenue trend, Q1–Q2 2026.])
-->
Images default to a sensible max width; keep them to one strong figure per idea rather than many raw dumps at random sizes.
Use callouts for what matters — a risk, a key result, a caveat — instead of
bolding a whole paragraph. callout is exported by the library (pass it via
scope: as shown above), then used inside the markdown:
<!--raw-typst
#callout(kind: "warning", title: "Risk")[A single supplier covers 40% of NPUs.]
#callout(kind: "success")[Revenue grew 31% YoY, ahead of plan.]
-->
Kinds: note, tip, success, warning, danger. Keep them rare — two or
three in a document read as deliberate; a wall of colored boxes reads as noise.
Lead with the numbers (data reports). For a metrics-heavy document, open a
section with a row of KPI cards instead of burying figures in prose. kpi and
kpi-row are exported by the library (pass them via scope: as shown above):
<!--raw-typst
#kpi-row(
kpi("$5.5M", "Revenue", sub: "+31% YoY"),
kpi("124%", "Net retention", sub: "+6pt"),
kpi("63.4%", "Gross margin", sub: "+240bp"),
)
-->
Use pullquote("…", by: "…") for a centered featured quote between sections.
Let whitespace breathe, but don't pad. Trust the theme's rhythm; don't add
manual #v(...) spacers around everything.
CJK fonts are opt-in (the docker.file.cjkFonts toggle). The themes already
list Noto Serif CJK / Noto Sans Mono CJK as fallbacks, so Korean/Japanese/
Chinese resolve automatically when those fonts are present. When the toggle
is off, Typst still renders — it just substitutes .notdef tofu (□) boxes for
every CJK glyph. Do not download, vendor, or curl a font to work around
this, and do not silently deliver a tofu PDF.
You don't need a pre-render gate: render first, then verify. If the source markdown contains CJK and the resulting PDF shows tofu boxes (or you know CJK fonts aren't enabled on this container), tell the user honestly and offer the fix:
This report has Korean/Japanese/Chinese text but the container has no CJK font — they're opt-in, so the PDF comes out as tofu boxes. Want me to set
docker.file.cjkFonts: trueintypeclaw.json? It's a boot setting, so after I edit it you'll runtypeclaw restartfrom the host project directory, and then I'll regenerate the PDF.
Only after the user agrees: edit typeclaw.json to set docker.file.cjkFonts: true (use the typeclaw-config skill), ask them to typeclaw restart, and
regenerate the PDF after the restarted container comes back. If the markdown has
no CJK, this section doesn't apply.
This skill renders markdown you author. To capture an existing web page or
a live URL as a PDF — something Typst cannot do — use the already-installed
agent-browser (Chrome): agent-browser --allow-file-access open file:///agent/workspace/page.html (or a URL), then agent-browser pdf /agent/workspace/out.pdf. Its output is fixed US-Letter with default margins, so
it's the right tool for archiving web content, not for authoring styled
reports. For authored documents, stay on the Typst path above.
Channel asked for the PDF — attach it:
channel_send(text: "Here's the report.", attachments: [{ path: "/agent/workspace/report.pdf", filename: "Edge-AI-Brief.pdf" }])
Use a human-friendly filename and an absolute path. Slack, Discord, Telegram,
and KakaoTalk upload the file; LINE and the GitHub adapter have no attachment
support, so there post a link or paste the markdown.
Replying in a thread — use channel_reply with the same attachments shape.
No channel (TUI session) — just report the path: report.pdf.
The researcher subagent writes its report to research-<slug>.md and returns a
<report> block naming the file. Copy lib.typ into that file's directory, point
the wrapper's read(...) at the report, render there, and attach. You do the PDF
step — the researcher's bash is read-only and it only emits markdown by design.
This is a bundled default. Want a fifth theme, a cover page with a logo, or a
house style? Two options: (a) copy lib.typ into the document directory and edit
your local copy before rendering (one-off), or (b) for a durable change, copy this
file to .agents/skills/<your-name>/SKILL.md (use a different name; bundled
skills win name collisions) and point it at your own theme library.
cmarker covers CommonMark well, but a few markdown features don't render as you
might expect:
- [ ] / - [x]) render as literal [ ] text, not
checkboxes. Use a plain bullet list or a status column in a table instead.**로컬 우선(local-first)**) may not be recognized as emphasis — CommonMark's
flanking rules treat that boundary as non-emphasis. Put a space inside, or bold a
pure run of text.#show: report.with(theme: …) from
the bundled library; only reach for raw Typst (via <!--raw-typst … -->) for
the occasional figure or callout.lib.typ by absolute path — copy it next to the markdown
first (Typst's workspace sandbox won't resolve an import from outside the
render's working directory).package.json / node_modules / a render script under
workspace/ or modify the protected agent-root dependencies. The compiler
installs in /tmp/typeclaw-doc-render-runtime; the render script and theme library are bundled with the plugin (under
/agent/node_modules/typeclaw/src/bundled-plugins/doc-render/).Frequently asked questions
You can produce professional PDFs from Markdown. The bundled doc-render plugin ships two things: a themed report library (lib.typ) that does all the styling, and a render script that does the compile. The only thing installed on demand is the Typst compiler — a single npm packag…
The source record exposes this install command: npx skills add https://github.com/typeclaw/typeclaw --skill "src/bundled-plugins/doc-render/skills/typeclaw-render-pdf". Inspect the command and pinned source before running it.
Static rules flagged exec-script, write-files in the source; the page lists the matching lines and excerpts.
Alternatives
NintendaDev/unikit-ai
Generate and maintain the project's TECHNICAL documentation from its codebase — scans the project structure, tech stack, and module boundaries, then writes a lean README landing page plus detailed topic pages (architecture, modules, setup, build, APIs), only the docs that are relevant. Use whenever the user wants to create, update, or validate documentation of the CODE or the project itself, e.g. "generate documentation", "create docs", "write the README", "update the project docs", "document th
eugenelim/agent-ready-repo
Use when implementing or resuming a non-trivial repository change: a feature, behavior-changing fix, refactor, migration, framework or dependency upgrade, schema or API change, performance work, infrastructure or build-system change, reversion, or an existing build spec under `docs/specs/`. Also use for bare continuation commands ('resume', 'continue', 'keep going', 'pick up where I left off', 'let's get going') when conversation or workspace context identifies active build work. Do not use for
objectstack-ai/objectstack
Author ObjectStack UI metadata — Views (list/form/kanban/calendar/gantt), Apps (navigation), Pages (structured plus the HTML and React source-authoring tiers, ADR-0080/0081), Dashboards, Reports, Charts, Actions, and package Docs (`src/docs/*.md`). Use when the user is adding `*.view.ts` / `*.app.ts` / `*.dashboard.ts` / `*.action.ts` / `src/docs/*.md` files or designing a Studio-rendered UI surface, including dataset-bound dashboard/report widgets. Do not use for: data schema (see objectstack-d
mgiovani/cc-arsenal
Multi-agent review team: architecture, security, performance, testing, style, docs/UX, plus an adversary that cross-examines the other 6, for security-sensitive, architectural, or large PRs (15+ files) where a single-agent pass risks missing cross-cutting issues. Use for auth/payments/PII changes, schema/pattern changes, compliance sign-off, or when asked to 'get the review team on this' / 'multi-agent review' / 'thorough review before merge'. For a standard PR or a quick pre-merge check, use /r