EthoClaw typetex
Compile Typst (.typ) and LaTeX (.tex) documents to PDF via the TypeTex compilation API, including multi-file projects and images. Use for generating PDFs, testing templates, and automated figure-heavy layouts.
git clone https://github.com/penciler-star/EthoClaw
T=$(mktemp -d) && git clone --depth=1 https://github.com/penciler-star/EthoClaw "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/typetex" ~/.claude/skills/penciler-star-ethoclaw-typetex && rm -rf "$T"
skills/typetex/SKILL.mdTypst & LaTeX Compiler
Compile Typst (.typ) and LaTeX (.tex) documents to PDF using the TypeTex compilation API.
API Endpoint
Base URL:
https://studio-intrinsic--typetex-compile-app.modal.run
Endpoints
Compile Typst
POST /public/compile/typst Content-Type: application/json
Request Body:
{ "content": "#set page(paper: \"a4\")\n\n= Hello World\n\nThis is a Typst document.", "main_filename": "main.typ", "auxiliary_files": {} }
Response (Success):
{ "success": true, "pdf_base64": "JVBERi0xLjQK..." }
Response (Failure):
{ "success": false, "error": "error: file not found: missing.typ" }
Compile LaTeX
POST /public/compile/latex Content-Type: application/json
Request Body:
{ "content": "\\documentclass{article}\n\\begin{document}\nHello World\n\\end{document}", "main_filename": "main.tex", "auxiliary_files": {} }
Response (Success):
{ "success": true, "pdf_base64": "JVBERi0xLjQK..." }
Response (Failure):
{ "success": false, "error": "! LaTeX Error: Missing \\begin{document}.", "log_output": "This is pdfTeX..." }
Health Check
GET /public/compile/health
Returns
{"status": "ok", "service": "public-compile"} if the service is running.
Usage Examples
Simple Typst Document
import requests import base64 response = requests.post( "https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/typst", json={ "content": """ #set page(paper: "a4", margin: 2cm) #set text(font: "New Computer Modern", size: 11pt) = My Document This is a paragraph with *bold* and _italic_ text. == Section 1 - Item 1 - Item 2 - Item 3 """, "main_filename": "main.typ" } ) result = response.json() if result["success"]: pdf_bytes = base64.b64decode(result["pdf_base64"]) with open("output.pdf", "wb") as f: f.write(pdf_bytes) print("PDF saved to output.pdf") else: print(f"Compilation failed: {result['error']}")
Simple LaTeX Document
import requests import base64 response = requests.post( "https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/latex", json={ "content": r""" \documentclass[11pt]{article} \usepackage[margin=1in]{geometry} \usepackage{amsmath} \title{My Document} \author{Author Name} \begin{document} \maketitle \section{Introduction} This is a LaTeX document with math: $E = mc^2$ \end{document} """, "main_filename": "main.tex" } ) result = response.json() if result["success"]: pdf_bytes = base64.b64decode(result["pdf_base64"]) with open("output.pdf", "wb") as f: f.write(pdf_bytes) else: print(f"Compilation failed: {result['error']}") if result.get("log_output"): print(f"Log: {result['log_output']}")
Multi-File Project (Typst)
import requests import base64 response = requests.post( "https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/typst", json={ "content": """ #import "template.typ": * #show: project.with(title: "My Report") = Introduction #include "chapter1.typ" """, "main_filename": "main.typ", "auxiliary_files": { "template.typ": """ #let project(title: none, body) = { set page(paper: "a4") set text(font: "New Computer Modern") align(center)[ #text(size: 24pt, weight: "bold")[#title] ] body } """, "chapter1.typ": """ == Chapter 1 This is the first chapter. """ } } ) result = response.json() if result["success"]: pdf_bytes = base64.b64decode(result["pdf_base64"]) with open("report.pdf", "wb") as f: f.write(pdf_bytes)
Including Images
For binary files like images, base64-encode them:
import requests import base64 # Read and encode an image with open("figure.png", "rb") as f: image_base64 = base64.b64encode(f.read()).decode("utf-8") response = requests.post( "https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/typst", json={ "content": """ #set page(paper: "a4") = Document with Image #figure( image("figure.png", width: 80%), caption: [A sample figure] ) """, "main_filename": "main.typ", "auxiliary_files": { "figure.png": image_base64 } } )
Using curl
# Typst compilation curl -X POST https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/typst \ -H "Content-Type: application/json" \ -d '{ "content": "#set page(paper: \"a4\")\n\n= Hello World\n\nThis is Typst.", "main_filename": "main.typ" }' | jq -r '.pdf_base64' | base64 -d > output.pdf # LaTeX compilation curl -X POST https://studio-intrinsic--typetex-compile-app.modal.run/public/compile/latex \ -H "Content-Type: application/json" \ -d '{ "content": "\\documentclass{article}\n\\begin{document}\nHello World\n\\end{document}", "main_filename": "main.tex" }' | jq -r '.pdf_base64' | base64 -d > output.pdf
Supported Features
Typst
- Full Typst language support
- Multi-file projects with imports
- Images (PNG, JPG, SVG)
- Custom fonts (New Computer Modern, etc.)
- Math equations
- Tables and figures
- Bibliography (using Hayagriva format)
LaTeX
- Full TeX Live distribution via Tectonic
- Multi-file projects (\input, \include)
- BibTeX/BibLaTeX bibliography
- Custom style files (.sty, .cls)
- All standard packages (amsmath, graphicx, etc.)
- TikZ/PGFPlots graphics
- Images (PNG, JPG, PDF, EPS)
Error Handling
When compilation fails, the response includes:
success: false
: Human-readable error messageerror
(LaTeX only): Full compilation log for debugginglog_output
Common errors:
- Syntax errors: Check your source code for typos
- Missing files: Ensure all imported/included files are in
auxiliary_files - Package not found: Most common packages are available; contact support for additions
- Timeout: Complex documents may timeout after 60 seconds
Rate Limits
- No authentication required
- Please be respectful of shared resources
- For high-volume usage, contact support
Default Template (Nature Communications-style figures)
This OpenClaw workspace includes a default figure-heavy Typst template based on the layout conventions in:
(Nature Communications | (2021)12:2784 | doi:10.1038/s41467-021-22970-y)/home/max/下载/demo.pdf
Template file:
skills/typetex/templates/naturecomm_figures.typ
What it sets up:
- A4 page + margins
- Running header line (journal/doi/url + page number)
- Figure styling (centered figure body, small left-aligned caption, compact spacing)
- Helpers:
,naturecomm_doc
,fig
,panel_gridwidefig
How to use it in a compile request
Pass the template in
auxiliary_files and import it from main.typ:
#import "naturecomm_figures.typ": naturecomm_setup, naturecomm_doc, fig, panel_grid, widefig #naturecomm_setup() #show: naturecomm_doc = Results #fig( "fig1.png", caption: [Caption text...], )
Notes:
- The Typst build behind this API does not support setting column gutter directly on
. The 2-column layout is applied viapage(..)
(which uses#show: naturecomm_doc
).columns(2, gutter: ..)[..] - Cross-column floating figures are fragile;
renders a wide figure on its own 1-column page for stability.widefig
Auto Layout Tool (folder-grouped)
If you have many images and want an automatic paper-like PDF, grouped by folders and captioned from filenames, use:
- Script:
skills/typetex/tools/layout_results_foldered.py - Example:
python3 skills/typetex/tools/layout_results_foldered.py \ --input "/home/max/下载/results" \ --output "/home/max/.openclaw/workspace/tmp_results/results_foldered_auto.pdf" \ --title "Results"
Behavior:
- Each subfolder becomes a
.\subsection*{...} - Each image becomes a centered block with
.\captionof{figure}{<filename>} - Uses a
to force.latexmkrc
(sincepdflatex
is not available in this TypeTex environment).xelatex
Default Templates (workspace-local)
This workspace includes reusable templates (Typst + LaTeX) that mimic the figure/caption layout from:
/home/max/下载/demo.pdf (Nature Communications | (2021)12:2784).
- Typst:
skills/typetex/templates/naturecomm_figures.typ - LaTeX:
skills/typetex/templates/naturecomm_figures.tex
Typical Typst usage:
#import "naturecomm_figures.typ": naturecomm_setup, naturecomm_doc, fig, panel_grid, widefig #naturecomm_setup() #show: naturecomm_doc = Results Text... #fig( "fig1.png", caption: [Your caption...], label: <fig:one>, ) #widefig( panel_grid( cols: 2, gap: 4mm, image("a.png", width: 100%), image("b.png", width: 100%), ), caption: [Wide figure caption...], label: <fig:wide>, )
LaTeX usage: start from
naturecomm_figures.tex, then add your own \begin{document} ... content.
Notes (Typst 0.13.1 API build quirks observed via this skill):
is not supported; use#set page(columns: 2, column-gutter: ...)
(wrap with#show: naturecomm_doc
).columns(2, gutter: ...)
named argument is not supported; attach labels in markup withfigure(label: <x>)
.<label>
Tips for Agents
- Always check
before accessingsuccesspdf_base64 - Parse errors to provide helpful feedback to users
- Use minimal documents when testing - complex documents take longer
- Cache results if compiling the same content multiple times
- Include all dependencies in
for multi-file projectsauxiliary_files - Default: when the user asks for image/figure-heavy Typst output without specifying a house style, use
.skills/typetex/templates/naturecomm_figures.typ
Related Resources
- Typst Documentation
- LaTeX Wikibook
- TypeTex - Full document editor with AI assistance