Skip to main content

Zero-config CLI that transforms Markdown into professional PDF documents using Typst.

Reason this release was yanked:

Broken on Python < 3.14, fixed in 1.1.1

Project description

doc-engine-cli

Zero-config Markdown → PDF documentation engine

License: MIT Python 3.10+ PyPI PyPI Downloads Typst Code style: black

Transform any README.md into a premium, print-ready PDF report — no configuration, no templates, no LaTeX.


doc-engine-cli Generation Demo
pipx install doc-engine-cli

Overview

doc-engine-cli is a developer-first CLI tool that converts Markdown files into professionally styled PDF documents using Typst as its rendering backend. It is designed for teams and individual developers who need high-quality documentation artifacts without the complexity of LaTeX or manual typesetting.

The tool auto-detects your README.md, extracts metadata from Git, and produces an IEEE-inspired technical document — complete with cover page, table of contents, and premium typography — in a single command.

doc-engine build

That's it. Zero configuration required.


Features

Feature Description
Zero-Config Auto-detects README.md, Git author, and document title. No setup files needed.
Five Templates Academic, modern, minimal, technical, and book layouts, each with a configurable accent color. Point --template at your own .typ file to go further.
Front Matter An optional --- metadata block sets the title, subtitle, author, template, and accent right inside the file.
Watch Mode --watch rebuilds the PDF every time you save the source.
Rich Markdown Embeds local images, renders GitHub task lists as real checkboxes, and turns [^1] footnotes into native Typst footnotes.
Error Checking Reports source problems with line and column before compiling. A --dry-run mode runs the check on its own.
Non-Destructive Never overwrites an existing PDF — writes report (1).pdf, report (2).pdf, … unless you pass --force.
Premium Typography Inter font family with fallback chain, justified text, and optimized line spacing.
Pure Python No external binaries required (no Pandoc, no LaTeX). Ships as a single pip install.
Cross-Platform Works on Windows, macOS, and Linux with Python 3.10+.

🎓 Academic Features (v0.1.2+)

doc-engine-cli ships with a premium scientific layout (using Linux Libertine and Inter font-families) and Zero-Config Bibliography handling.

To add an IEEE-styled bibliography to your PDF:

  1. Create a refs.bib, references.bib, or bibliography.bib file in your repository.
  2. In your README.md, cite using standard syntax: [@citation-key].

When you run doc-engine build, the CLI will automatically detect your .bib file, securely bind it to the sandbox, and inject a formatted References page at the end of the document.


Quick Start

Installation

pipx install doc-engine-cli

(If you don't have pipx, you can install it via pip install pipx)

Generate Your First PDF

Navigate to any project directory containing a README.md and run:

doc-engine build

The tool will:

  1. Auto-detect README.md in the current directory
  2. Extract the document title from the first # heading
  3. Read your Git user.name for the author field
  4. Generate a README_doc.pdf with cover page, ToC, and formatted content

Explicit Options

doc-engine build path/to/file.md -o output.pdf -t "Custom Title" -a "Author Name"

Usage

doc-engine-cli configuration demo
Switching templates, recoloring the accent, and checking a file for errors.

Commands

doc-engine build [INPUT_FILE]   Convert a Markdown file into a PDF
doc-engine info                 Show version, repository, and templates
doc-engine --version            Print the version and exit
doc-engine --help               Show all commands and flags

build flags

Flag Default Description
INPUT_FILE auto-detect README.md Path to the Markdown file to convert.
-o, --output <input>_doc.pdf Output PDF path.
-t, --title first # heading Document title override.
-s, --subtitle none Subtitle shown under the title on the cover.
-a, --author git config user.name Author name override.
--date today Date shown on the cover.
--template academic A built-in layout (academic, modern, minimal, technical, book) or a path to your own .typ file.
--accent template default Accent color as a hex value (#2563eb) or a name (blue, teal, rose, ...).
--bib auto-detect refs.bib Path to a custom .bib file for the bibliography.
--no-branding off Hide the doc-engine attribution from the PDF.
--dry-run off Check the Markdown for errors and exit without writing a PDF.
-w, --watch off Rebuild automatically whenever the source file changes.
-f, --force off Overwrite the output file instead of writing a numbered copy.
--open off Open the PDF after it is generated.

Any flag can also be set in the front matter (see below); a flag on the command line always wins.

Examples

Basic — zero-config mode:

cd my-project
doc-engine build
# → Generates README_doc.pdf

Specify input and output:

doc-engine build CONTRIBUTING.md -o contributing_guide.pdf

Override metadata:

doc-engine build -t "API Reference v2.0" -a "Engineering Team"

Pick a template and accent color:

doc-engine build --template modern --accent teal
doc-engine build --template technical --accent "#7c3aed"

Check for errors before building:

doc-engine build --dry-run

Drop the engine attribution from the PDF:

doc-engine build --no-branding

Generate and open immediately:

doc-engine build --open

Rebuild on every save:

doc-engine build --watch

Use as Python module:

python -m doc_engine build README.md

Front Matter

Any Markdown file can open with a --- block to carry its own settings, so the document renders the same way for everyone — no flags to remember:

---
title: Payments API
subtitle: Integration Guide
author: Platform Team
template: technical
accent: teal
---

# Payments API

...

Supported keys: title, subtitle, author, date, template, accent, and bib. A flag passed on the command line overrides the matching front-matter key, which in turn overrides the auto-detected value.


Watch Mode

Pass --watch to keep doc-engine running and rebuild the PDF whenever you save the source. It's the fastest way to tweak a template or accent and see the result:

doc-engine watch mode rebuilding on save
Metadata read from front matter, rebuilt live on every save.
doc-engine build --watch --template modern --accent teal

The output path is chosen once when watch starts, then rewritten in place on each change. Press Ctrl+C to stop.


Templates

doc-engine ships with five layouts. Switch with --template <name>, and recolor any of them with --accent.

Template Look
academic Serif IEEE-style report with cover page, table of contents, and running headers. The default.
modern Clean sans-serif layout with generous spacing and a left-aligned cover.
minimal No cover or table of contents — a compact title block, then straight into the content.
technical Bold layout with a filled accent banner and section markers. Good for engineering docs.
book Classic centered title page with chapter-style section breaks.
doc-engine build --template book
doc-engine build --template modern --accent rose

Accent colors take a hex value (#0ea5e9) or one of these names: blue, sky, indigo, violet, purple, red, rose, orange, amber, green, emerald, teal, slate, black.

Bring your own template

--template also accepts a path to a .typ file, so you can ship a house style without forking the project:

doc-engine build --template ./corporate.typ

The quickest way to start is to copy one of the files in doc_engine/templates/ and edit it. A template exposes a single setup_doc entry point, and the compiler passes it the document metadata:

#let setup_doc(
  title: "",
  subtitle: "",
  author: "Anonymous",
  date: datetime.today().display(),
  bibliography_file: none,
  accent: none,
  branding: true,
  version: "",
  body,
) = { ... }

Checking for Errors

Before compiling, doc-engine scans the Markdown for problems and reports them with the exact line and column, so you can jump straight to the fix:

README.md:42:8: error: link URL must not be empty
README.md:51:1: warning: image source is empty

Errors stop the build; warnings don't. Use --dry-run to run the check on its own without producing a PDF — handy in CI:

doc-engine build --dry-run

Architecture

                    ┌─────────────┐
                    │  README.md  │
                    └──────┬──────┘
                           │
                    ┌──────▼──────┐
                    │   CLI Layer  │  click + rich
                    │  (cli.py)    │  arg parsing, git detection
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │                         │
       ┌──────▼──────┐          ┌───────▼──────┐
       │  Converter   │          │   Compiler   │
       │(converter.py)│          │(compiler.py) │
       │              │          │              │
       │ Markdown AST │          │  Typst → PDF │
       │  → Typst     │          │  via typst-py│
       └──────┬──────┘          └───────┬──────┘
              │                         │
              │    ┌──────────────┐     │
              └────► templates/   ◄─────┘
                   │   *.typ      │
                   └──────┬──────┘
                          │
                   ┌──────▼──────┐
                   │  output.pdf  │
                   └─────────────┘

Pipeline

Stage Module Responsibility
1. Input Resolution cli.py Locate Markdown file, detect Git metadata
2. Source Checking linter.py Report empty links and unclosed fences with line/column
3. Markdown Parsing converter.py Parse Markdown AST via mistune, emit Typst markup
4. Template Injection compiler.py Merge converted content with the selected template
5. PDF Compilation compiler.py Compile via typst Python bindings

How It Works

Markdown → Typst Conversion

The converter module parses Markdown using mistune and generates equivalent Typst markup:

Markdown Typst Output
# Heading = Heading
**bold** *bold*
*italic* _italic_
`code` `code`
[text](url) #link("url")[text]
- item - item
1. item + item
- [x] task rendered checkbox
text[^1] #footnote[...]
![alt](local.png) #image("local.png")
> blockquote #block(...)
--- #line(...)

Special characters (#, $, @, *, _, etc.) are automatically escaped to prevent Typst interpretation.

PDF Templates

Each template lives in doc_engine/templates/ and exposes the same setup_doc entry point, so the compiler can swap between them with --template. The default academic template provides:

  • Cover page with title, author, and date
  • Table of contents with depth-3 navigation
  • Running headers with document title and author
  • Page footer with page numbers and engine attribution
  • Code blocks with rounded corners and subtle borders
  • Heading hierarchy with accent-colored H2 sections

The other templates (modern, minimal, technical, book) keep the same content but change the fonts, layout, and cover. The accent color is injected at compile time, so --accent recolors any of them.


Project Structure

doc-engine-cli/
├── doc_engine/
│   ├── __init__.py          # Package version
│   ├── __main__.py          # python -m doc_engine entrypoint
│   ├── cli.py               # Click-based CLI + Git detection
│   ├── converter.py         # Markdown → Typst transpiler
│   ├── compiler.py          # Typst → PDF compilation engine
│   ├── linter.py            # Source checks (line/column reporting)
│   └── templates/
│       ├── academic.typ     # Default IEEE-style report
│       ├── modern.typ       # Clean sans-serif layout
│       ├── minimal.typ      # Compact, no cover page
│       ├── technical.typ    # Accent banner + section markers
│       └── book.typ         # Centered title page, chapter breaks
├── tests/
│   ├── __init__.py
│   ├── test_converter.py    # Unit tests for the converter
│   ├── test_linter.py       # Unit tests for the linter
│   └── test_cli.py          # CLI and template/accent tests
├── pyproject.toml            # Package configuration + dependencies
├── LICENSE                   # MIT License
├── .gitignore
└── README.md

Dependencies

Package Purpose License
click CLI framework BSD-3
rich Terminal formatting and progress indicators MIT
mistune Markdown parser (pure Python) BSD-3
typst Typst compiler bindings Apache-2.0

All dependencies are pure Python — no external binaries (Pandoc, LaTeX, etc.) are required.


Development

Setup

git clone https://github.com/leonardosalasd/doc-engine-cli.git
cd doc-engine-cli
pip install -e ".[dev]"

Run Tests

python -m pytest tests/ -v

Project Commands

# Generate PDF from this project's README
python -m doc_engine build

# Run with verbose error output
python -m doc_engine build README.md -o docs_output.pdf

Docker

A container image is published to GitHub Container Registry on every release. Mount your project into /workspace and run build as usual:

docker run --rm -v "$PWD:/workspace" ghcr.io/leonardosalasd/doc-engine-cli build

The entrypoint is doc-engine, so you can pass any command or flag:

docker run --rm -v "$PWD:/workspace" ghcr.io/leonardosalasd/doc-engine-cli build --template modern --accent teal

Supported Markdown Elements

  • Headings (H1–H6)
  • Bold, italic, strikethrough
  • Inline code and fenced code blocks (with language hints)
  • Links
  • Ordered and unordered lists
  • Nested lists
  • Blockquotes
  • Tables
  • Horizontal rules
  • Line breaks (<br>)
  • Task lists (- [x] / - [ ])
  • Footnotes ([^1])
  • Local images (remote images still render as alt-text)
  • Math blocks

Roadmap

  • Template selection via --template flag
  • Configurable accent color via --accent
  • Source error checking with line/column and --dry-run
  • User-supplied template files (point --template at a path)
  • YAML front-matter support for metadata override
  • Local image embedding
  • Watch mode for continuous rebuilds
  • Multi-file documentation merge
  • Image downloading and embedding for remote URLs
  • PDF/A compliance for archival

Contributing

Contributions are welcome. Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/your-feature)
  3. Write tests for new functionality
  4. Ensure all tests pass (python -m pytest tests/ -v)
  5. Submit a pull request

License

This project is licensed under the MIT License.


Built with Typst · Parsed with mistune · Styled with Rich

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

doc_engine_cli-1.1.0.tar.gz (29.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

doc_engine_cli-1.1.0-py3-none-any.whl (26.4 kB view details)

Uploaded Python 3

File details

Details for the file doc_engine_cli-1.1.0.tar.gz.

File metadata

  • Download URL: doc_engine_cli-1.1.0.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for doc_engine_cli-1.1.0.tar.gz
Algorithm Hash digest
SHA256 63fe2b6685ad1598aed5dab11c8e57cec7ac328c26d89b6481106c85ea68fda9
MD5 66a6d82d83ca35a71cf8880226a0131e
BLAKE2b-256 2fcc89a3c69ea11a081ea47eb0d3339cb0492c511f9872f9c9b948a4971d680e

See more details on using hashes here.

File details

Details for the file doc_engine_cli-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: doc_engine_cli-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for doc_engine_cli-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 826bd077ffdb22c53446b76dc6ed81c920618a9afcae7c5d72342c5f727c4e68
MD5 c07ac97e00c940fd1461bd068e90a52f
BLAKE2b-256 da795f46b7bca676ea158bc3f6804ddfa8f98485ed4cf81ca80fc6a0db51c036

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page