CLI Commands
Highlight files, inspect Tree-sitter output, manage languages, and generate themes with the Lumis CLI.
Global options
These flags work with any subcommand:
| Flag | Short | Description |
|---|---|---|
--verbose | -v | Show extra output: downloads, cache hits, parser paths |
--data-dir <path> | -d | Override the data directory (also LUMIS_DATA_DIR env var) |
--config <path> | Override the config file (also LUMIS_CONFIG env var) | |
--help | -h | Print help for any command |
--version | -V | Print the version |
Commands
| Command | What it does |
|---|---|
lumis highlight | Highlight a file or stdin |
lumis dump tree | Print configurable Tree-sitter syntax trees |
lumis dump events | Print raw highlight events as JSON |
lumis formatters list | List output formatters |
lumis formatters show | List the options one formatter accepts |
lumis languages list | List supported languages and file patterns |
lumis languages show | Print what the catalog knows about one language |
lumis languages download | Download and compile parsers so later runs skip both |
lumis themes list | List built-in and local themes |
lumis themes show | Print one theme's appearance and colors |
lumis themes build-css | Generate a theme stylesheet |
lumis themes generate | Generate a theme from a Neovim colorscheme repo |
lumis highlight
lumis highlight main.rs --theme catppuccin_frappecat main.rs | lumis highlight -l rust
echo 'const x = 1' | lumis highlight \
-l javascript \
--formatter html-inline \
--theme catppuccin_frappeOptions
Most options belong to a specific formatter. Passing one the selected formatter does not accept is an error naming both, rather than being silently ignored:
lumis highlight main.rs --pre-class code
# error: `--pre-class` is not accepted by the `terminal` formatter
#
# HTML options apply to: html-inline, html-linked, html-multi-themes
# run `lumis formatters show terminal` to see what it acceptslumis highlight --help prints the same grouping, and
lumis formatters show <name> answers it for one formatter.
Accepted by every formatter:
| Flag | Short | Description |
|---|---|---|
--language <lang> | -l | Language id (e.g., rust, javascript). Auto-detects from file if omitted. |
--formatter <fmt> | -f | Output format: terminal (default), html-inline, html-linked, html-multi-themes, bbcode-scoped |
--rainbow-brackets | Render matched brackets by nesting depth | |
--word-diff | Mark the words that changed between removed and added lines. Only applies with -l diff | |
--highlight-lines <lines> | -H | Lines to highlight (e.g., 1,3-5,10) |
Accepted by html-inline and terminal:
| Flag | Short | Description |
|---|---|---|
--theme <name-or-path> | -t | Built-in name, data-directory filename stem, JSON file path (e.g., ./my-theme.json), or auto |
Accepted by every formatter except bbcode-scoped, which has nothing to render a
number into:
| Flag | Short | Description |
|---|---|---|
--line-numbers | -n | Render a line number gutter |
Accepted by terminal:
| Flag | Short | Description |
|---|---|---|
--background <bg> | -b | Fallback background: theme, a hex color, or omit to inherit |
--width <n> | -w | Render width for background padding, or auto |
--highlight-lines-background <bg> | Background for highlighted lines (defaults to the theme's highlighted background) |
Accepted by html-inline, html-linked and html-multi-themes:
| Flag | Short | Description |
|---|---|---|
--structure <structure> | block (default) writes a <pre><code> block; inline writes only the token spans, and the flags that configure the <pre>, <code>, lines and header have no effect. See Inline code | |
--pre-class <class> | CSS class appended to the wrapping <pre> tag | |
--pre-attr <name[=value]> | Attribute for the wrapping <pre> tag; a bare name writes the boolean form. Repeat for more than one | |
--no-pre-attr <name> | Attribute to leave off the wrapping <pre> tag | |
--code-attr <name[=value]> | Attribute for the nested <code> tag; a bare name writes the boolean form. Repeat for more than one | |
--no-code-attr <name> | Attribute to leave off the nested <code> tag, such as tabindex | |
--header-open <tag> | Opening tag wrapped around the output (requires --header-close) | |
--header-close <tag> | Closing tag wrapped around the output (requires --header-open) | |
--highlight-lines-class <class> | CSS class added to highlighted lines |
For an HTML background override, use --pre-attr 'style=background-color: #181818;'.
Use transparent in place of the color to let an enclosing card show through.
See Override the block background.
Accepted by html-inline and html-multi-themes:
| Flag | Short | Description |
|---|---|---|
--include-highlights | Add data-highlight attributes naming each scope | |
--highlight-lines-style <style> | theme (default), none, or raw CSS |
Accepted by html-multi-themes:
| Flag | Short | Description |
|---|---|---|
--themes <key:theme> | Theme pair; each theme accepts a name or JSON path (repeatable, e.g., --themes light:catppuccin_latte --themes dark:./my-theme.json) | |
--default-theme <id> | Which --themes entry gets inline styles | |
--css-variable-prefix <prefix> | Prefix for CSS custom properties (default: --lumis). A value starting with - needs the = form: --css-variable-prefix=--shiki |
Examples
lumis highlight main.rs -f html-inline -t catppuccin_frappelumis highlight main.rs -f html-linkedlumis highlight main.rs \
-f html-multi-themes \
--themes light:catppuccin_latte \
--themes dark:catppuccin_frappe \
--default-theme lightlumis highlight main.rs -f bbcode-scopedlumis highlight main.rs -vlumis formatters
lumis formatters listhtml-inline HTML with inline style attributes
html-linked HTML with CSS class names (pair with a theme stylesheet)
html-multi-themes HTML with CSS custom properties, one set per theme
terminal ANSI escape codes (default)
bbcode-scoped BBCode using highlight scope names as tagslumis formatters show terminalterminal: ANSI escape codes (default)
Accepted options:
--language
--formatter
--rainbow-brackets
--theme
--background
--width
Run `lumis highlight --help` for descriptions.lumis dump tree
Print named syntax nodes as branch lines with language and zero-based range
metadata. The host tree is shown by default. Options can add source text,
resolved highlights, and query-driven injected language trees. Square brackets
identify syntax nodes; @name lines identify resolved highlights.
| Flag | Short | Description |
|---|---|---|
--language <lang> | -l | Language id. Auto-detects from the path if omitted. |
--format <format> | lines (default) or canonical sexp output | |
--text[=<limit|full>] | Add JSON-escaped middle previews; defaults to 80 characters | |
--highlights | Add resolved highlight-query results in source order | |
--injections | Add injected language trees and their highlights |
lumis dump tree src/main.jslumis dump tree component.svelte --text
lumis dump tree component.svelte --text=120
lumis dump tree component.svelte --text=fullLimits from 1 to 3 show leading characters only. Larger truncated previews use
..., retaining both ends when space permits. Optional text values use = so
--text component.svelte still treats the final argument as the input path.
lumis dump tree component.svelte \
--injections --text --highlightslumis dump tree src/main.js --format sexp--format sexp cannot be combined with --text or --highlights. With
--injections, each actual parser tree is printed as a separately labeled
S-expression section.
[document] language: svelte, range: 0:0-1:0, text: "function increment() { count++; }\n"
├── [text] language: svelte, range: 0:0-0:20, text: "function increment()"
└── [expression] language: svelte, range: 0:21-0:33, text: "{ count++; }"
├── @punctuation.bracket language: svelte, range: 0:21-0:22, text: "{"
├── [svelte_raw_text] language: svelte, range: 0:23-0:32, text: "count++; "
│ └── [program] language: javascript, range: 0:23-0:32, text: "count++; "
│ └── [expression_statement] language: javascript, range: 0:23-0:31, text: "count++;"
│ ├── [update_expression] language: javascript, range: 0:23-0:30, text: "count++"
│ │ ├── [identifier] field: argument, language: javascript, range: 0:23-0:28, text: "count"
│ │ │ └── @variable language: javascript, range: 0:23-0:28, text: "count"
│ │ └── @operator language: javascript, range: 0:28-0:30, text: "++"
│ └── @punctuation.delimiter language: javascript, range: 0:30-0:31, text: ";"
└── @punctuation.bracket language: svelte, range: 0:32-0:33, text: "}"lumis dump events
Print the raw highlight event stream as JSON. Start events include the resolved highlight scope and language; source events use byte offsets into the original input.
lumis dump events src/main.jsecho 'function increment() { count++; }' \
| lumis dump events -l svelteAll dump commands accept an optional path and --language / -l. They read
stdin when the path is omitted, using the same language detection behavior as
lumis highlight. Exact-version parser WASMs are verified and cached on first
use when needed.
lumis languages list
lumis languages listPrints all supported languages with their file extensions and patterns.
lumis languages show
lumis languages show elixir
lumis languages show jsPrints one language's id, name, aliases, extensions, globs, Emacs modes and
shebangs. Aliases resolve the way highlighting resolves them, so js finds
JavaScript. Exits non-zero on an unknown name.
lumis languages download
Download exact, integrity-checked parser WASM files ahead of time, and compile them. Highlighting does both anyway; this moves them off the first run.
A cold parser costs a download and then a Wasmtime compile, and the compile is
the larger half. Parser cache lifecycle
covers what the store keeps and how --force refreshes it.
lumis languages download rust javascript elixirlumis languages download bundle-webThe bundle-* names cover the same languages as the matching
@lumis-sh/wasm-bundle-* package. Lumis.Languages.async_load/1 and the
JavaScript / TypeScript languages.load() accept the same names in application
code.
lumis languages download --alllumis languages download rust javascript --forcePinning parsers
The CLI has no lock. lumis highlight resolves freely and lumis languages download fills its store — a viewer is not the application whose output a lock
governs. Pinning belongs to a project and its own runtime; see
Pinning parsers.
lumis themes list
lumis themes listLists built-in themes and any custom themes found in the data directory, one
per line with its SPDX license. Custom themes are marked (file), and a theme
JSON without a license field lists as NOASSERTION:
catppuccin_frappe MIT
my_theme (file) NOASSERTIONCustom theme lookup uses the filename stem, not the JSON's name field.
lumis themes show
lumis themes show catppuccin_frappe
lumis themes show ./my-theme.jsonPrints a theme's appearance, license, foreground, background and how many highlight scopes it defines. Accepts a built-in name, data-directory filename stem, or explicit JSON path. Exits non-zero on an unknown name or a missing or malformed explicit file.
lumis themes build-css
Write CSS for a built-in or local theme to stdout. Redirect it to save a file:
lumis themes build-css catppuccin_frappe > theme.css
lumis themes build-css catppuccin_frappe --no-layout > colors.css
lumis themes build-css ./my-theme.json > my-theme.css| Flag | Default | Behavior |
|---|---|---|
--no-layout | Layout included | Omit the built-in line layout layer. |
--scope <selector> | Empty | Prefix every selector with a parent selector. |
--container-selector <selector> | .lumis | Change the container color rule's selector. |
--container-style <property=value> | None | Add or replace a container declaration; repeat for more properties. |
The command uses the same CSS builder as the libraries.
Theme lookup is shared with --theme, themes show, and multi-theme HTML's
--themes entries; see local custom themes.
Theme styles and supplied container declarations remain when layout is disabled.
Quote values containing spaces, for example --container-style 'padding=1rem 2rem'.
CSS custom properties work too: --container-style '--code-bg=#111'.
lumis themes generate
Extract a theme from a Neovim colorscheme Git repository. Requires Git and
Neovim with the built-in vim.pack plugin manager on PATH. See the
generation recipe for a complete
example, runtime loading, and source-license and redistribution considerations.
| Flag | Short | Description |
|---|---|---|
--url <url> | -u | Git repository URL |
--colorscheme <name> | -c | Colorscheme name to activate (e.g., catppuccin-mocha) |
--output <path> | -o | Write JSON to this path (prints to stdout if omitted) |
--setup <lua> | -s | Lua code to run before loading the colorscheme |
--appearance <mode> | -a | light or dark (default: dark) |
lumis themes generate \
-u https://github.com/folke/tokyonight.nvim \
-c tokyonight-night \
-o tokyonight.jsonlumis themes generate \
-u https://github.com/projekt0n/github-nvim-theme \
-c github_light \
-a light \
-o github-light.jsonConfiguration
Lumis reads ~/.config/lumis/config.toml by default on macOS and Linux. Set XDG_CONFIG_HOME to change the base directory, or use --config / LUMIS_CONFIG to select another file.
[highlight]
theme = "auto" # or a theme name such as "tokyonight_moon"auto uses the terminal's background, foreground and ANSI accent colors to choose a nearby light or dark theme, excluding monochrome themes. It only queries for the terminal formatter when stdout is a terminal. If colors are unavailable or no suitable theme matches, Lumis renders without a theme and explains why on stderr. Use an explicit --theme for pipes or HTML output; it takes precedence over the config file. See theme selection for the selection rules.
Data directory
Lumis stores parser WASM files and custom theme JSON in a local data directory.
| OS | Default path |
|---|---|
| macOS / Linux | ~/.local/share/lumis/ |
| Windows | %APPDATA%/lumis/ |
Override with --data-dir or LUMIS_DATA_DIR.
Contents:
parsers/— verified Tree-sitter WASM files keyed by version and SHA-256themes/— custom theme JSON files (visible inlumis themes list)