CLI
epresso ships a single epresso command with subcommands. Most commands take an
optional project directory (root), defaulting to the current directory.
| Command | Description |
|---|---|
epresso init [root] |
Scaffold a blank project |
epresso new [template] [dest] |
Scaffold a project (interactive, or pass a template/theme/git URL/directory) |
epresso dev [root] |
Development server with live reload |
epresso build [root] |
Deterministic + incremental production build |
epresso preview [root] |
Build then serve dist/ (production preview) |
epresso docs [root] |
Build + serve docs (port 4321) or write them with --out; no root = epresso's own docs, . = this project |
epresso import mkdocs |
Write a docs.toml from an MkDocs mkdocs.yml |
epresso serve [root] |
Serve an already-built dist/ (no build) |
epresso clean [root] |
Remove dist/ and the build cache |
epresso layers [root] |
List the component/layout layers resolved from [layers] use |
epresso check [root] |
Validate config + content, list routes |
epresso fmt [paths…] |
Format .ep files to the canonical section structure |
epresso lsp |
Run the .ep Language Server (diagnostics + formatting) over stdio |
epresso inspect [root] |
Inspect the build graph (routes + content → route edges) |
epresso deploy [root] |
Build and deploy (GitHub Pages by default) |
epresso version |
Print the version |
epresso docs
Build a directory of Markdown as a documentation site and serve it (default port
4321), or write a static build with --out.
bashepresso docs # epresso's own documentationepresso docs . # this project (site.toml / docs.toml / mkdocs.yml / zero-config)epresso docs ../my-repo # a local checkoutepresso docs github:owner/repo@v1 # clone + render a remote repoepresso docs https://github.com/owner/repo # same, by URLepresso docs ../my-repo --theme ../my-theme # with a custom themeepresso docs ../my-repo --out dist/docs # static build, no server
root is a git source or a directory:
-
git source —
github:owner/repo[@ref],git+https://…, or a plainhttps:///git@URL. It is shallow-cloned into.cache/repos/(reused on later runs; delete that directory to re-fetch a moved ref) and rendered. The clone keeps its.git, so the repository links below resolve to that repo. -
project — a directory with a
site.toml, built as-is. -
docs.toml— a directory with adocs.toml(and nosite.toml): the docs theme with theepresso_docsplugin, fed by the sources it lists (see below). -
any other directory (zero-config) — the top-level
README.mdis the homepage and every Markdown file underdocs/is a page (override the dir withEPRESSO_DOCS_DIRorREPO_DOCS). Nodocs/→ a console warning and a site with just the homepage. NoREADME.md→ a placeholder homepage explaining what to create (also in--outbuilds).README.mdwins overdocs/index.md. Other files in the directory are not read. -
mkdocs.yml— an MkDocs project (nosite.tomlordocs.toml): read live and rendered with the docs theme. See Migrate from MkDocs.
With no argument, epresso docs shows epresso's own documentation; when the
current directory holds a site.toml, docs.toml or mkdocs.yml it also prints
a hint to run epresso docs .. For a directory it checks, in order: site.toml,
docs.toml, mkdocs.yml, then zero-config. With both docs.toml and
mkdocs.yml it uses docs.toml and says so.
Several sources: docs.toml
tomltitle = "My Project" # → [site] nameextra_css = ["css/extra.css"] # copied, loaded after the theme CSSextra_javascript = ["js/extra.js"]redirects = [{ "/old/" = "/guide/install/" }][[sources]]source = "docs" # local dir, relative to docs.toml# optional, MkDocs-shaped: replaces folder grouping for this source;# unlisted pages are built but not shown in the sidebarnav = ["index.md", { "Guide" = ["guide/install.md", { "Usage" = "guide/usage.md" }] }][[sources]]source = "github:org/plugin-a@v1"dir = "docs" # dir inside the source (default "docs" for git, "." local)prefix = "/plugins/a/" # URL prefix (default "/")title = "Plugin A" # sidebar group label[site] # optional overrides for the generated site.tomlurl = "https://docs.example.com/"[theme] # optional theme options (or `theme = "path"` for another theme)logo = "logo.svg"
Every source merges into one docs collection — one sidebar, one search index,
one prev/next chain. Two sources producing the same page are a build error;
give one a prefix. docs.toml is a shorthand: epresso compiles it into a
site.toml with plugins = ["epresso_docs"] and a [plugin.epresso_docs]
table, which is exactly what a full site would write. Without sources it
reads ./docs. Relative images in every source resolve (see the plugins guide); only files a built page references are published.
Allowed top-level keys: title, theme, site, sources, base, redirects,
extra_css, extra_javascript, blog (options for epresso_blog); per source: source, dir, prefix, title,
repo_url, nav. Anything else is an error.
The link back to the repository
When the source is a git checkout, epresso also points the generated pages at
that repository. It reads the checkout's origin remote and default branch and
writes them into the generated site.toml:
toml[site]repository = "https://github.com/you/my-repo"branch = "main"
Those two fields drive the view / edit this source links on every page, so
the preview links to the real repository instead of the theme's own. The source
path itself is recorded as docs_source, and the collection it populates as
[theme] docs_base. See Preview a repository's docs
for the full workflow.
| Flag | Meaning |
|---|---|
--theme PATH |
Theme project used for bare Markdown (default: the bundled docs theme) |
--out DIR |
Write a static production build to DIR instead of serving |
--port N |
Port to serve on (default 4321; the next free port is used if busy) |
--host H |
Host to bind (default 127.0.0.1) |
--env NAME |
Environment (loads site.<env>.toml + .env.<env>; default production) |
--perf |
Print detailed build-phase timings |
epresso import mkdocs
Write a docs.toml from an MkDocs mkdocs.yml, then preview with epresso docs ..
bashepresso import mkdocs # ./mkdocs.yml → ./docs.tomlepresso import mkdocs site/mkdocs.yml --theme ../my-themeepresso import mkdocs --force # overwrite an existing docs.toml
Settings without an epresso equivalent are listed as warnings. See Migrate from MkDocs.
| Flag | Meaning |
|---|---|
--theme PATH |
Record a theme project in docs.toml |
--force |
Overwrite an existing docs.toml |
epresso serve
Serve an already-built dist/ directory — no build. Use it to check exactly
what a deploy will serve, or to preview a build produced elsewhere.
bashepresso build && epresso serveepresso serve --port 5000
| Flag | Meaning |
|---|---|
--host H |
Host to bind (default 127.0.0.1) |
--port N |
Preferred port (default 4321; the next free port is used if busy) |
Unlike epresso preview, it never loads the project or rebuilds — it fails if
dist/ does not exist.
epresso build
Build the site into dist/. Builds are deterministic and incremental; --clean
starts from scratch.
bashepresso buildepresso build --perfepresso build --profile --profile-out epresso-profile.pstats
| Flag | Meaning |
|---|---|
--clean / --no-clean |
Clean dist/ before building (default: clean) |
--env NAME |
Environment (loads site.<env>.toml + .env.<env>; default production) |
--perf |
Print detailed build-phase timings |
--profile |
Run the build under cProfile and print the hottest frames |
--profile-out PATH |
Where --profile writes its stats file (default epresso-profile.pstats) |
See Incremental builds & caching and Performance.
epresso dev
Run the Starlette development server with WebSocket live reload. It shares the production incremental engine, so an edit re-renders only what changed.
| Flag | Meaning |
|---|---|
--host H |
Host to bind (default 127.0.0.1) |
--port N |
Preferred port (default 4321; the next free port is used if busy) |
--env NAME |
Environment (default development) |
Pages served by this server show the dev toolbar.
epresso preview
Build (production environment) then serve the static dist/ — exactly what a
deploy will serve, without the dev server's live reload.
| Flag | Meaning |
|---|---|
--host H |
Host to bind (default 127.0.0.1) |
--port N |
Preferred port (default 4321; the next free port is used if busy) |
--env NAME |
Environment (default production) |
epresso check
Validate configuration and content, then list each collection and route. It exits non-zero on a config/content error, so it is useful as a CI gate before a build.
| Flag | Meaning |
|---|---|
--env NAME |
Environment (default production) |
epresso layers
List the external component/layout layers resolved from [layers] use, in
precedence order — the site's own components/ and layouts/ win, then the
layers in the order listed. See Layers.
| Flag | Meaning |
|---|---|
--env NAME |
Environment (default production) |
epresso inspect
Print the build graph — every route and its content → route edges — without writing any output. Use it to see why a page is rebuilt (incremental fan-out).
bashepresso inspect # JSONepresso inspect --format dot | dot -Tsvg -o graph.svg
| Flag | Meaning |
|---|---|
--format json|dot |
Output format (default json) |
epresso deploy
Build and deploy the site. The default (and only current) provider is GitHub
Pages: it builds into dist/, commits it to a gh-pages branch, and pushes.
bashepresso deployepresso deploy --no-push # build + commit locally, don't push
| Flag | Meaning |
|---|---|
--provider NAME |
Deploy provider (only gh-pages today) |
--remote NAME |
Git remote to push to (default origin) |
--branch NAME |
Branch to publish (default gh-pages) |
--no-push |
Build + commit but do not push |
To publish with GitHub Actions instead of a branch, see the repository's
deploy-docs.yml
workflow.
epresso new
Scaffold a project from a template, a theme name, a git URL, or a local directory. Interactive when the arguments are omitted.
bashepresso new # interactiveepresso new basic mysiteepresso new docs mysiteepresso new github:nikoshell/epresso-theme-docs mysiteepresso new github:nikoshell/epresso-theme-docs@v1 mysite # pinned to a tagepresso new -y # non-interactive: basic template, current dir
| Argument / flag | Meaning |
|---|---|
template |
A built-in template (basic, …), a theme name, a git URL, or a directory path |
dest |
Destination directory (prompted when omitted) |
--yes / -y |
Skip prompts: basic template, current directory |
epresso init
Scaffold a blank project in root (default .): a site.toml, pages/,
content/, public/ and .gitignore — no theme and no content, so you build
the layout yourself.
epresso clean
Remove dist/ and the .cache build cache. Running it twice is safe.
epresso version
Print the epresso version. The same value is shown in the footer when
[theme.footer] debug = true.
epresso fmt
Formats .ep files to the canonical structure: frontmatter → HTML body →
<script> → <style>, each section separated by a single blank line, plus
basic whitespace hygiene (strip trailing whitespace, ensure one trailing newline).
Section content (markup, CSS, JS, frontmatter Python) is preserved verbatim.
bashepresso fmt # format all .ep under the current directoryepresso fmt components/ pages/ # format specific files/dirsepresso fmt --check . # report files that would change; don't write (exit 1 if any)epresso fmt --expand . # reflow the body: one child per line (no extra deps)epresso fmt --full . # also format section contents (frontmatter/HTML/CSS/JS)epresso fmt --stdin # read one .ep source from stdin, write to stdout
--stdin is for editor integrations (the bundled VS Code extension uses it to
format the buffer without touching disk); it reads one .ep source from stdin
and writes the result to stdout. It cannot be combined with --check.
A layout — a document shell with <html>/<head>/<body> — is only
whitespace-normalised: its <style>/<script> are positional and never
reordered. --check is CI-friendly: it exits non-zero when any file needs
formatting.
epresso lsp
A dependency-free Language Server for .ep files, speaking LSP on stdin/stdout
(no extra packages). It reports the same problems the build enforces — forbidden
Jinja composition ({% extends %}, {% include %}, {% macro %}, …), the
one-root-per-branch file shape, per-kind sidecar caps, and Python syntax errors
in the frontmatter — and offers textDocument/formatting backed by
epresso fmt.
bashepresso lsp # speak LSP on stdin/stdout
Point any LSP-capable editor at it; see Editor setup. The bundled VS Code extension and a small Neovim config snippet both use it.
epresso fmt --expand
--expand reflows the HTML body: an element whose content is markup only
(no literal text) gets one child per line, Jinja blocks spread across lines, and
a lone interpolation moves onto its own line. No blank lines are added.
epresso------<div class="card"> {% if props.icon %}<Icon name={tone.icon} />{% endif %} <p>{{ props.title }}</p></div>
becomes
epresso------<div class="card"> {% if props.icon %} <Icon name={tone.icon} /> {% endif %} <p> {{ props.title }} </p></div>
Elements that contain literal text (<p>Hello <b>world</b></p>) are left
alone, so prose keeps its line wrapping, and <pre> / <script> / {% raw %}
bodies are never re-indented. Siblings that the author glued together with no
whitespace are kept glued, because that whitespace is significant.
This changes the whitespace in the rendered HTML — harmless inside block and
flex/grid containers, but visible between inline elements. It is therefore
off by default; --full implies it. The reflow is conservative: if the result
would change any non-whitespace character, the file is left untouched.
epresso fmt --full
--full additionally formats each section's content by reusing dedicated
tools, shipped as the optional [fmt] extra:
| Section | Tool |
|---|---|
| frontmatter (Python) | ruff format |
| HTML body | --expand reflow + djhtml |
CSS (<style>) |
cssbeautifier |
JS (<script>) |
jsbeautifier |
--full implies --expand.
bashpip install -e .[fmt]epresso fmt --full .
Jinja ({{ }}/{% %}/{# #}) is preserved throughout. If the [fmt] deps are
missing, --full formats whatever is available and skips the rest.
Was this page helpful?