Skip to content

Converter skills

The skills in the converters pack, their inputs, outputs, flags, and prerequisites. Each skill is a thin wrapper: the agent invokes a script and reports the result.

Skill Direction Engine
file-to-markdown documents/images → Markdown Docling / vision pipeline
mermaid-renderer Markdown → Markdown + images Mermaid CLI (mmdc)
markdown-to-html Markdown → HTML marked + highlight.js
markdown-to-docx Markdown → branded Word (template-fill) docxtpl
markdown-to-pptx Markdown → branded PowerPoint (template-fill) python-pptx
markdown-to-xlsx Markdown → branded Excel (template-fill) openpyxl
msg-to-markdown Outlook .msg → Markdown @nicecode/msg-reader / msgreader

file-to-markdown

Convert documents and images to Markdown. Two branches, selected by input type.

Source: packs/converters/.apm/skills/file-to-markdown/

Inputs

Branch Extensions Path
Document PDF, DOCX, PPTX, XLSX, XLS scripts/convert.py (Docling)
Image PNG, JPG, JPEG, TIFF, BMP, WEBP, GIF scripts/split_image.py + agent vision + scripts/reconcile.py

Prerequisites

Branch Needs Install
Document Docling, Pillow python -m pip install docling Pillow
Image Pillow python -m pip install Pillow

The first Docling run downloads ML models (~1–2 min); later runs are fast. Confirm Docling is importable with python -c "import docling" (exit 0 → proceed; non-zero → not installed).

Document branch

python scripts/convert.py "<input-file>"

Writes <basename>.md next to the input. One file per call — loop for a batch. Stdout markers:

Marker Meaning
OUTPUT: <path> Path to the written Markdown file
LINES: <n> / WORDS: <n> Counts
WARNING: <msg> Non-fatal (e.g. sparse text); surfaced to the user

Image branch

A two-pass sliding-window pipeline:

Step Command Output
Recommend split_image.py recommend --input <image> JSON: source dims, single-pass flag, recommended viewport/stride
Overview split_image.py overview --input <image> --output-dir <dir>/ --max-dim 1200 <dir>/overview.png (agent reads it for a structural map)
Detail split_image.py detail --input <image> --output-dir <dir>/ --viewport 1200 --stride 800 tile_W0_R<row>_C<col>.png + detail_manifest.json
Reconcile reconcile.py --manifest … --extractions … --strategy <name> --title "…" --output-json <dir>/merged.json --output-md <output>.md merged JSON + final Markdown

The agent reads each detail tile and writes <dir>/extractions.json, choosing one extraction strategy: architecture, event-storm, process, domain, or conceptual. reconcile.py then translates tile coordinates to global ones, collapses duplicates by (type, normalized_name) and by IoU ≥ 0.5, picks canonical records by confidence then tile-centrality, sorts by the structural map's layout, and emits Markdown with YAML frontmatter. Reconcile stdout: OUTPUT_JSON, OUTPUT_MD, ELEMENTS, AMBIGUITIES.

Edge cases

Situation Behavior
Image ≤ 1200 px on both dims Skip overview; run a single detail tile (--viewport/--stride = max dim)
Source > 8000 px on a side Script auto-prescales before tiling, records the factor in the manifest
Scanned PDF Docling applies OCR automatically; surfaces any WARNING:
Password-protected file Document branch fails fast; remove the password first
Detail pass > 100 tiles split_image.py warns; raise --stride or lower --viewport
Tile read fails Skipped; reconciler reports the gap in ambiguities

mermaid-renderer

Extract ```mermaid fenced blocks from a Markdown file, render each to an image, and write a rewritten Markdown file with each fence replaced by an image reference. The original input is not modified.

Source: packs/converters/.apm/skills/mermaid-renderer/

Prerequisites

The Mermaid CLI (mmdc), installed via npm install -g @mermaid-js/mermaid-cli (or a project-local node_modules/ on PATH). No Python deps beyond the standard library. Verify with python scripts/render_mermaid.py --check (exit 0 → ready; exit 2 → not installed).

Command

python scripts/render_mermaid.py --input report.md --output-dir ./rendered [flags]
Flag Meaning
--input PATH Source Markdown file. Required.
--output-dir DIR Directory for images and the rewritten Markdown. Default: ./mermaid-out.
--format png\|svg Output format. Default: png.
--theme default\|forest\|dark\|neutral Mermaid theme. Default: default.
--background white\|transparent\|#hex Background color. Default: white.
--prefix NAME Output filename prefix. Default: mermaid.
--width N Output width in px (passes to mmdc -w).
--height N Output height in px (passes to mmdc -H).
--check Verify mmdc is on PATH; exit 0 or 2.
--verbose Debug logging.

Outputs

  • <output-dir>/<prefix>-1.<ext>, <prefix>-2.<ext>, … — one image per block, numbered in document order.
  • <output-dir>/<input-basename>.md — rewritten copy with each fence replaced by a Markdown image reference.

Stdout: OUTPUT_DIR, REWRITTEN, DIAGRAMS.

Edge cases

Situation Behavior
No Mermaid blocks DIAGRAMS: 0, input copied through unchanged, exit 0
A block fails to render Writes mermaid-N.error.txt, leaves the fence intact, keeps going, exits non-zero with a failure count
Unknown theme mmdc exits with the valid choices; surfaced
mmdc not on PATH --check exits 2 with the install command

markdown-to-html

Convert a Markdown file to a self-contained, styled HTML page (sticky header, sidebar nav, syntax-highlighted code, callout boxes, Mermaid diagrams, print-ready). For documents, not slides.

Source: packs/converters/.apm/skills/markdown-to-html/

Prerequisites

Node.js with marked and highlight.js (pinned in the skill's package.json). Verify from the skill directory with node -e "require.resolve('marked'); require.resolve('highlight.js')" (exit 0 → ready; non-zero → run npm install once). Add the skill's node_modules/ to .gitignore if the skill lives in a tracked directory.

Command

node scripts/render.js <input.md> [flags]
Flag Meaning
--output FILE Output path. Default: input with .html extension.
--title TEXT Page title. Default: first H1, then filename.
--subtitle TEXT Header subtitle (small grey text).
--theme navy\|green\|teal\|amber\|rose Accent color. Default: navy.
--no-mermaid Skip the Mermaid CDN script.

Outputs

Writes the HTML file and prints three stdout lines:

Marker Meaning
OUTPUT: <path> Path to the written HTML file
SECTIONS: <n> Number of h2/h3 anchors built
MERMAID: yes\|no Whether Mermaid handling was emitted

Handled automatically

  • Headings get stable id attributes for sidebar links and the print TOC.
  • Code blocks are syntax-highlighted; ```mermaid fences pass through as <div class="mermaid"> for the runtime CDN renderer.
  • Tables are wrapped in <div class="table-wrap"> for horizontal scroll.
  • Paragraphs beginning with **Note:**, **Tip:**, **Warning:**, **Important:**, or **Stop:** become styled callout boxes.
  • Every output includes an @media print block; Ctrl+P → Save as PDF works out of the box.

Edge cases

Situation Behavior
Missing dependencies render.js exits 1 with an install hint
No headings Sidebar shows (no sections); output still works
Unknown theme Exits with the list of valid choices
Offline output wanted with Mermaid present Pass --no-mermaid; the block falls back to a plain <pre>

markdown-to-docx

Fill a branded Word template from a Markdown artifact. Template-fill via docxtpl — the designer's cover page, styles, headers, and logo survive; the skill never converts Markdown into a fresh document.

Source: packs/converters/.apm/skills/markdown-to-docx/

Prerequisites

Tier-1 on docxtpl (exact canonical PyPI package). Install with python -m pip install 'docxtpl>=0.16.0' (the floor clears a version where get_undeclared_template_variables() was broken). The library installs into your environment, outside the repo's SCA. Verify with python scripts/render.py --check (exit 0 → ready; exit 2 → not installed).

Commands

python scripts/render.py --check
python scripts/render.py inspect <template.docx>
python scripts/render.py render <markdown> --template <template.docx> [--output <path>]
Verb Purpose
--check Import-probe docxtpl; exit 0/2.
inspect <template> List the template's declared Jinja variables.
render <markdown> --template <tpl> Fill the template and write a .docx. Default output: <basename>.docx in CWD.

Fill-points and mapping

A .docx has no fill-points until you add Jinja tags: {{ var }} (scalar), {%p for it in items %}…{%p endfor %} (paragraph loop), {%tr for r in rows %}…{%tr endfor %} (table-row loop). Mapping: front-matter key: value{{ key }}; the first list → items; the first Markdown table → rows (list of {column: value} dicts). Author each tag in one uniform run or Word's run-splitting will hide it.

Outputs and edge cases

Stdout: OUTPUT:, FILLED:, WARNING:, and GUIDANCE: (emitted instead of OUTPUT: when the template has no tags). Renders with autoescape=True, so user content with </&/{{ is XML-escaped, not interpolated. A user-supplied template is trusted-author input — a malicious template author could embed SSTI; that (and XXE / zip-bomb) is an accepted, out-of-scope risk. The output write is confined under the working directory. Omit --template only on the user's explicit opt-out — the skill then writes an unbranded .docx via python-docx (with a WARNING:).


markdown-to-pptx

Fill a branded PowerPoint template from a Markdown artifact. Template-fill via python-pptx — the slide master, theme, fonts, and placed logo survive.

Source: packs/converters/.apm/skills/markdown-to-pptx/

Prerequisites

Tier-1 on python-pptx. Install with python -m pip install 'python-pptx>=1.0.0'. Installs outside the repo's SCA. Verify with python scripts/render.py --check.

Commands

python scripts/render.py --check
python scripts/render.py inspect <template.pptx>
python scripts/render.py render <markdown> --template <template.pptx> [--output <path>]
Verb Purpose
--check Import-probe python-pptx; exit 0/2.
inspect <template> List the layout placeholders (layout/idx/type/name).
render <markdown> --template <tpl> Fill the deck and write a .pptx. Default output: <basename>.pptx in CWD.

Fill-points and mapping

PowerPoint layouts already carry placeholders, keyed by their stable idx — so every .pptx is fillable (no "untagged template" case). Mapping: front-matter title/subtitle → the title slide; each #/## heading → one slide; list items → bullet rows; a Markdown table → a TABLE placeholder if the layout has one, else a table added to the slide.

Outputs and edge cases

Stdout: OUTPUT:, FILLED:, WARNING:. python-pptx evaluates no template content as code, so there is no SSTI surface; XXE / zip-bomb on a crafted archive is an accepted, out-of-scope risk. The output write is confined under the working directory. Omit --template only on the user's explicit opt-out (renders with the python-pptx default master; unbranded).


markdown-to-xlsx

Fill a branded Excel template from a Markdown artifact. Template-fill via openpyxl — writes into named ranges and Excel Tables only, so formatting, formulas, and charts survive.

Source: packs/converters/.apm/skills/markdown-to-xlsx/

Prerequisites

Tier-1 on openpyxl. Install with python -m pip install 'openpyxl>=3.1.0'. Installs outside the repo's SCA. Verify with python scripts/render.py --check.

Commands

python scripts/render.py --check
python scripts/render.py inspect <template.xlsx>
python scripts/render.py render <markdown> --template <template.xlsx> [--output <path>]
Verb Purpose
--check Import-probe openpyxl; exit 0/2.
inspect <template> List named ranges + Excel Tables (kind/name/ref).
render <markdown> --template <tpl> Fill the data ranges and write a .xlsx. Default output: <basename>.xlsx in CWD.

Fill-points and mapping

A workbook needs named ranges (for scalars) and/or Excel Tables (for tabular data) defined beforehand. Mapping: front-matter key: value → the single-cell named range called key; the first Markdown table → the first Excel Table's data region (columns aligned by header, else by position).

Outputs and edge cases

Stdout: OUTPUT:, FILLED:, WARNING:, and GUIDANCE: (when the workbook has no fill-points). The script writes only into data cells and never resizes a range, so a chart reading it keeps working; a Markdown table longer than the Excel Table is truncated with a WARNING:, never expanded. openpyxl preserves charts/images it can parse on round-trip, but its tutorial warns shapes it cannot read are lost — re-open and verify for complex templates. The output write is confined under the working directory. Omit --template only on the user's explicit opt-out — the skill then writes an unbranded .xlsx via a bare openpyxl workbook (with a WARNING:).


msg-to-markdown

Convert Outlook .msg email files to Markdown, preserving headers (From, To, CC, Date), body content, and attachment metadata.

Source: packs/converters/.apm/skills/msg-to-markdown/

Prerequisites

Node.js with one of @nicecode/msg-reader (preferred) or msgreader; scripts/convert.js uses whichever is installed. Install with npm install @nicecode/msg-reader. Verify from the skill directory:

node -e "try{require.resolve('@nicecode/msg-reader')}catch{require.resolve('msgreader')}"

Commands

Command Purpose
node scripts/convert.js "<file>.msg" Convert one .msg to Markdown
node scripts/extract-attachments.js "<file>.msg" Extract attachments to a folder

For a glob like emails/*.msg, loop over each file individually.

Output

Structured Markdown with a header table (From/To/CC/Date), the body, and attachment metadata. HTML bodies are converted (complex CSS or conditional Outlook markup may be simplified).

Edge cases

Situation Behavior
RTF-only body Flagged; re-save as HTML in Outlook or install an RTF parser
Winmail.dat / TNEF May not parse; node-tnef suggested
Inline images (cid:) Stored as attachments; broken refs until extracted
Reply chains Quoted replies preserved as nested blockquotes
Unusual encoding Re-read as UTF-8 / UTF-16LE / Windows-1252
Calendar .ics attachment Offered for parsing into a structured section
Sensitivity labels Included in the metadata table when present

For task recipes, see the how-to guides. Installing and upgrading the pack live in ../../_shared/.