Skip to content
Back to skills

Latex Engine

ASecurity

Activate when the user wants to export a completed paper draft to production-ready LaTeX (.tex) and PDF. Converts draft.md + references.bib + figures/ into a complete arxiv-style LaTeX project with properly resolved \citep/\citet citations, booktabs tables, figure environments, and compiled PDF output.

  • 18 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
data-aipythongit

Security analysis

A93/100
  • highPerforms destructive filesystem operations

Pro shows the line behind each finding and how to fix it

Scanned May 27, 2026

npx -y skills add TobiasBlask/open-paper-machine --skill latex-engine --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Latex Engine?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Latex Engine
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tobiasblask-latex-engine/badge)](https://www.skillsdirectory.com/skills/tobiasblask-latex-engine)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: latex-engine
description: >
  Activate when the user wants to export a completed paper draft to production-ready
  LaTeX (.tex) and PDF. Converts draft.md + references.bib + figures/ into a complete
  arxiv-style LaTeX project with properly resolved \citep/\citet citations, booktabs
  tables, figure environments, and compiled PDF output.
---

> **Orchestration Log**: When this skill is activated, append a log entry to `outputs/orchestration_log.md`:
> ```
> ### Skill Activation: LaTeX Engine
> **Timestamp:** [current date/time]
> **Actor:** AI Agent (latex-engine)
> **Input:** [brief description of the export request]
> **Output:** [brief description of what was produced — e.g., "Compiled paper.tex to PDF (24 pages), no errors"]
> ```

# LaTeX Engine

## Core Principle
The paper machine works in markdown throughout Phases 1-5 for speed and flexibility.
This engine is the **final production step**: it takes the completed draft.md,
references.bib, and figures/ and produces a submission-ready LaTeX project with
compiled PDF using the arxiv-style template (https://github.com/kourgeorge/arxiv-style).

## Prerequisites

**Required files in the working directory:**
- `draft.md` — complete paper draft from Phase 5
- `references.bib` — BibTeX file from literature search
- `figures/` — directory with generated PNG figures (optional but recommended)

**Required system packages for PDF compilation:**
- `texlive` or equivalent LaTeX distribution with `pdflatex` and `bibtex`
- Install if missing: `apt-get install -y texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-bibtex-extra`

**Plugin files used:**
- `templates/arxiv.sty` — the arxiv-style LaTeX style file
- `scripts/md_to_latex.py` — the markdown-to-LaTeX converter

---

## When to Activate

- User says "export to LaTeX", "generate PDF", "make it submission-ready"
- After Phase 5 (Assembly) completes in the paper machine pipeline
- User explicitly asks for `.tex` output
- User mentions arXiv submission preparation

---

## Conversion Pipeline

### Step 1: Prepare the LaTeX Project Directory

Create a `latex/` subdirectory with the proper structure:

```
latex/
├── arxiv.sty          ← copied from templates/
├── paper.tex          ← generated by md_to_latex.py
├── references.bib     ← copied from working dir
├── figures/           ← copied from working dir
│   ├── fig_method_*.png
│   ├── fig_results_*.png
│   └── ...
└── paper.pdf          ← compiled output
```

### Step 2: Run the Converter

```python
import sys, shutil
from pathlib import Path

# Paths
plugin_dir = Path(".")  # or wherever the plugin is
work_dir = Path(".")     # project working directory
latex_dir = work_dir / "latex"
latex_dir.mkdir(exist_ok=True)

# Copy arxiv.sty
shutil.copy(plugin_dir / "templates" / "arxiv.sty", latex_dir / "arxiv.sty")

# Copy references.bib
shutil.copy(work_dir / "references.bib", latex_dir / "references.bib")

# Copy figures
figures_src = work_dir / "figures"
if figures_src.exists():
    figures_dst = latex_dir / "figures"
    if figures_dst.exists():
        shutil.rmtree(figures_dst)
    shutil.copytree(figures_src, figures_dst)

# Run converter
sys.path.insert(0, str(plugin_dir / "scripts"))
from md_to_latex import md_to_latex, compile_pdf

tex_content = md_to_latex(
    md_path=str(work_dir / "draft.md"),
    bib_path=str(work_dir / "references.bib"),
    title=None,       # auto-detect from draft.md
    authors=None,      # user provides or TODO marker
    header_right="A Preprint",
)

tex_path = latex_dir / "paper.tex"
tex_path.write_text(tex_content, encoding="utf-8")
print(f"LaTeX written: {tex_path}")
```

### Step 3: Compile to PDF

```python
# Compile: pdflatex → bibtex → pdflatex → pdflatex
pdf_path = compile_pdf(str(tex_path))
if pdf_path:
    print(f"PDF ready: {pdf_path}")
else:
    print("Compilation had issues — check paper.log")
```

### Step 4: Validate Output

After compilation, verify:
1. **Citation resolution**: Check for undefined references in the `.log` file
2. **Figure inclusion**: Verify all `\includegraphics` paths resolve
3. **BibTeX entries**: Check that all `\citep`/`\citet` keys exist in `.bib`
4. **Page count**: Report total pages
5. **TODO markers**: List any remaining `% TODO:` comments

```python
import re

log_path = latex_dir / "paper.log"
if log_path.exists():
    log_text = log_path.read_text(encoding="utf-8", errors="ignore")

    # Undefined references
    undef = re.findall(r"Citation `([^']+)' undefined", log_text)
    if undef:
        print(f"⚠️  Undefined citations: {undef}")

    # Missing figures
    missing_figs = re.findall(r"File `([^']+)' not found", log_text)
    if missing_figs:
        print(f"⚠️  Missing figures: {missing_figs}")

    # Page count
    pages = re.findall(r"Output written on .+ \((\d+) page", log_text)
    if pages:
        print(f"📄 PDF: {pages[0]} pages")

# TODO markers in .tex
tex_text = tex_path.read_text(encoding="utf-8")
todos = re.findall(r"% TODO: (.+)", tex_text)
if todos:
    print(f"📝 Remaining TODOs ({len(todos)}):")
    for t in todos:
        print(f"   - {t}")
```

---

## Citation Conversion Details

The converter handles these citation patterns:

| Markdown Pattern | LaTeX Output |
|---|---|
| `(Smith, 2023)` | `\citep{smith2023}` |
| `(Smith & Jones, 2023)` | `\citep{smithjones2023}` |
| `(Smith et al., 2023)` | `\citep{smithetal2023}` |
| `Smith (2023)` | `\citet{smith2023}` |
| `Smith et al. (2023)` | `\citet{smithetal2023}` |
| `(Smith, 2023; Jones, 2024)` | `\citep{smith2023, jones2024}` |

**Resolution process:**
1. Parse all BibTeX entries → extract (LastName, Year) pairs
2. For each citation in markdown, match against the BibTeX index
3. Exact match → use BibTeX key directly
4. Fuzzy match → try without accents, partial first name
5. No match → generate fallback key, leave `% TODO` comment

---

## Author Block

Authors can be provided in three ways:

**Option A: Via command arguments**
```
--author "Tobias Blask;;University of Applied Sciences;;blask@university.de"
--author "Co-Author Name;;Other University;;coauthor@uni.de"
```

**Option B: Via the converter function**
```python
tex = md_to_latex(
    md_path="draft.md",
    bib_path="references.bib",
    authors=[
        "Tobias Blask;;HTW Berlin;;tobias.blask@htw-berlin.de",
        "Co-Author;;Institution;;email@inst.de",
    ],
)
```

**Option C: Edit the .tex file directly**
The generated .tex has a clear author block section to edit manually.

---

## Table Conversion

Markdown tables are converted to LaTeX `booktabs` tables:

```markdown
| Column A | Column B | Column C |
|----------|----------|----------|
| Data 1   | Data 2   | Data 3   |
```

Becomes:

```latex
\begin{table}[htbp]
\centering
\begin{tabular}{lll}
\toprule
\textbf{Column A} & \textbf{Column B} & \textbf{Column C} \\
\midrule
Data 1 & Data 2 & Data 3 \\
\bottomrule
\end{tabular}
\end{table}
```

For concept matrix tables (which can be wide), the converter wraps in `\adjustbox{max width=\textwidth}`.

---

## Figure Handling

**From figure-engine (LaTeX already in draft.md):**
If the draft already contains `\begin{figure}...\end{figure}` blocks (from the figure-engine),
they are passed through as-is.

**From markdown images:**
`![Caption](figures/filename.png)` is converted to:
```latex
\begin{figure}[htbp]
\centering
\includegraphics[width=\linewidth]{figures/filename.png}
\caption{Caption}
\label{fig:auto_label}
\end{figure}
```

---

## Troubleshooting

| Problem | Solution |
|---|---|
| `arxiv.sty not found` | Ensure arxiv.sty is copied to the same directory as paper.tex |
| `Citation undefined` | BibTeX key mismatch — check references.bib has the expected keys |
| `Missing figure` | Check figures/ directory is in the latex/ folder |
| `Font not found` | Install texlive-fonts-recommended |
| `natbib errors` | Ensure natbib package is installed (texlive-latex-extra) |
| `Compilation hangs` | Check for infinite loops in .tex — usually malformed tables |

---

## arXiv Submission Preparation

For arXiv upload, the user needs:
1. `paper.tex` — the generated .tex file
2. `arxiv.sty` — the style file
3. `references.bib` — OR the `.bbl` file (generated during compilation)
4. `figures/` — all PNG figures

**Important:** arXiv doesn't always process `.bib` files correctly. To be safe:
1. Copy the contents of `paper.bbl` (generated during compilation)
2. Paste into `paper.tex` replacing the `\bibliography{references}` line
3. Comment out the `\bibliographystyle` and `\bibliography` lines

The converter can prepare this automatically with `--arxiv-bundle` (copies .bbl inline).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.