# CLI Commands (/cli/commands)

## 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`

```bash title="Terminal output (default formatter)"
lumis highlight main.rs --theme catppuccin_frappe
```

```bash title="Pipe from stdin"
cat main.rs | lumis highlight -l rust
echo 'const x = 1' | lumis highlight \
  -l javascript \
  --formatter html-inline \
  --theme catppuccin_frappe
```

### Options

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:

```bash
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 accepts
```

`lumis 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](/formatters#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](/formatters#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

```bash title="HTML inline"
lumis highlight main.rs -f html-inline -t catppuccin_frappe
```

```bash title="HTML linked"
lumis highlight main.rs -f html-linked
```

```bash title="HTML multi-themes"
lumis highlight main.rs \
  -f html-multi-themes \
  --themes light:catppuccin_latte \
  --themes dark:catppuccin_frappe \
  --default-theme light
```

```bash title="BBCode Scoped"
lumis highlight main.rs -f bbcode-scoped
```

```bash title="Verbose mode — see cache hits and parser paths"
lumis highlight main.rs -v
```

## `lumis formatters`

```bash title="List the formatters"
lumis formatters list
```

```text
html-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 tags
```

```bash title="See what one formatter accepts"
lumis formatters show terminal
```

```text
terminal: 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 |

```bash title="Parse a file with automatic language detection"
lumis dump tree src/main.js
```

```bash title="Add source text previews"
lumis dump tree component.svelte --text
lumis dump tree component.svelte --text=120
lumis dump tree component.svelte --text=full
```

Limits 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.

```bash title="Show a mixed-language annotated tree"
lumis dump tree component.svelte \
  --injections --text --highlights
```

```bash title="Use the canonical parser representation"
lumis 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.

```text title="Example mixed-language annotated tree"
[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.

```bash title="Inspect highlight captures"
lumis dump events src/main.js
```

```bash title="Debug a partial mixed-language snippet"
echo 'function increment() { count++; }' \
  | lumis dump events -l svelte
```

All 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`

```bash
lumis languages list
```

Prints all supported languages with their file extensions and patterns.

## `lumis languages show`

```bash
lumis languages show elixir
lumis languages show js
```

Prints 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](/cli/behavior#parser-cache-lifecycle)
covers what the store keeps and how `--force` refreshes it.

```bash title="Selected parsers"
lumis languages download rust javascript elixir
```

```bash title="A bundle"
lumis languages download bundle-web
```

The `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.

```bash title="All parsers"
lumis languages download --all
```

```bash title="Replace valid cached parsers"
lumis languages download rust javascript --force
```

## Pinning 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](/advanced/lock).

## `lumis themes list`

```bash
lumis themes list
```

Lists 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`:

```text
catppuccin_frappe   MIT
my_theme (file)     NOASSERTION
```

Custom theme lookup uses the filename stem, not the JSON's `name` field.

## `lumis themes show`

```bash
lumis themes show catppuccin_frappe
lumis themes show ./my-theme.json
```

Prints 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:

```sh
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](/themes/css-builder) as the libraries.
Theme lookup is shared with `--theme`, `themes show`, and multi-theme HTML's
`--themes` entries; see [local custom themes](/cli/behavior#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](/recipes/generate-theme-from-neovim-colorscheme) 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`) |

```bash
lumis themes generate \
  -u https://github.com/folke/tokyonight.nvim \
  -c tokyonight-night \
  -o tokyonight.json
```

```bash title="Light theme"
lumis themes generate \
  -u https://github.com/projekt0n/github-nvim-theme \
  -c github_light \
  -a light \
  -o github-light.json
```

## Configuration

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.

```toml
[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](/cli/behavior#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-256
- `themes/` — custom theme JSON files (visible in `lumis themes list`)