Skill: seitzbg/skeet-pdf-report (version 1.0.2)

--- name: pdf-report description: | Generate a polished PDF report or summary from findings, data, or tables gathered earlier in the conversation. Use when the user asks to "make a PDF", "generate a report", "export findings", "summarize as a PDF", or similar. Produces Typst source, compiles it with `typst`, and reports the output path. metadata: {"openclaw":{"emoji":"📄","requires":{"bins":["typst"]}}} --- # pdf-report Turn gathered conversation content (findings, data, tables) into a clean PDF via Typst. Two templates ship with this skill — pick one, fill it in, compile. ## When to invoke Trigger on any of: - "make a PDF" / "create a PDF" / "export to PDF" - "generate a report" / "write up a report" - "summarize this as a PDF" / "PDF summary" - "export these findings/results" If the user says "export" or "deliverable" without specifying format and the context has tabular data or distinct findings, ask once whether they want PDF before invoking. ## Inputs to gather Before writing any Typst, confirm or infer: 1. **Title** — ask if not obvious. Keep short (≤ 60 chars). 2. **Subtitle / author** — optional; leave blank or omit if unknown. 3. **Content scope** — exactly which findings/tables/sections from the conversation belong in the document. Do not invent data the user did not provide. 4. **Output path** — default `./report-YYYY-MM-DD.pdf` in cwd. If a file with that name exists, append `-2`, `-3`, etc. ## Pick a template | Template | Use when | |----------|----------| | `templates/summary.typ` | 1–3 sections, executive summary, ≤ ~3 pages. **Default.** | | `templates/report.typ` | 3+ distinct sections, title page + TOC desired, or user said "report". | Both live next to this `SKILL.md`. Read the chosen one, then write a new `.typ` file at `<output>.typ` (next to the target PDF) with placeholders replaced and example tables swapped for real data. ## Authoring rules - **Tables**: always use `#table()` with `table.header(...)`. Right-align numeric columns. Preserve the precision the user gave you — do not round. - **Long tables**: `table.header(repeat: true, ...)` repeats headers on page breaks automatically (Typst 0.12+). - **Special characters in cell text**: wrap in `[...]` content blocks; escape `#`, `$`, `@`, `\` if they appear literally. - **Adapt freely**: add or drop sections to match the content. Keep the page setup, font sizing, and heading shows from the template — those define the look. - **No watermarks**. Do not add "Generated by AI", "Claude", "Qwen", or similar. The user does not want it. ## Compile ```bash typst compile <output>.typ <output>.pdf ``` `typst` is at `/home/linuxbrew/.linuxbrew/bin/typst` (linuxbrew). If it's not on PATH in the current shell, use the full path. ## Error handling If compile fails: 1. Read the error — Typst errors include file, line, and a usually-clear hint. 2. Fix the `.typ` source and retry **once**. 3. If it still fails, stop. Show the user: - the error output, - the path to the `.typ` source so they can edit directly. Do not loop indefinitely on errors. ## Reporting back On success, tell the user: - output PDF path (absolute), - page count (from `pdftotext -l 1` or just `typst query` — or simply state "compiled successfully" if neither is convenient), - that the `.typ` source is kept alongside for future tweaks. Offer to open it (`xdg-open <path>`) but do not open without confirmation. ## Quick reference: minimal Typst patterns ```typst // Two-column table with numeric right-align #table( columns: (auto, auto), align: (left, right), stroke: 0.5pt + gray, inset: 7pt, table.header([*Name*], [*Count*]), [alpha], [42], [beta], [108], ) // Bullet list - one - two - three // Inline emphasis This is *bold* and this is _italic_ and this is `mono`. // Math (inline and block) The energy is $E = m c^2$. $ integral_0^infinity e^(-x^2) dif x = sqrt(pi) / 2 $ // Image #figure(image("plot.png", width: 80%), caption: [A plot.]) ```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)