A command-line tool that starts a simple web server to display Markdown files rendered as HTML in the browser, with live reload on file changes.
- Two modes: One-off mode for quick viewing, daemon mode for multiple files
- Server-side rendering: Markdown to HTML conversion with goldmark
- Syntax highlighting: Code blocks styled with goldmark-highlighting
- Live reload: Automatic browser refresh on file changes via Server-Sent Events (SSE)
- Browser auto-open: Opens the URL in your default browser, skipped on headless systems
- Multiple file support: Serve multiple Markdown files from a single daemon instance
- File watching: Intelligent file monitoring with fsnotify
- GitHub Flavored Markdown: Tables, task lists, strikethrough, alerts, and more
- Mermaid diagrams:
```mermaidcode blocks render as diagrams, with the runtime (mermaid, MIT, seeassets/mermaid.LICENSE) embedded in the binary (works offline) - Index page: Browse all tracked files from a single page
- HTML export: Download any file as a self-contained HTML snapshot, keeping the selected viewport width
- Linked documents: Links to other Markdown files are followable; the target is rendered and watched the first time it is opened
- Static asset serving: Images, and links to files that aren't Markdown, are served from wherever they live, including outside the file's directory
- Minimal styling: Clean, readable CSS
- Single binary: All assets embedded, no external dependencies
Run the install script:
curl -fsSL https://raw.githubusercontent.com/Ch00k/lum/main/install.sh | shIt detects your OS and architecture (Linux/macOS, amd64/arm64), downloads the latest release, and installs it as lum into the first of ~/.local/bin, ~/bin, or /usr/local/bin that exists, is writable, and is in your PATH.
Alternatively, download an executable for your operating system from the releases page, rename it to lum, make it executable, and put it into a directory in your PATH.
lum [OPTIONS] [FILE]
Options:
-p, --port PORT Port to run the server on (default: 6333)
-d, --daemon Run as daemon (allows serving multiple files)
-s, --stop Stop the running daemon
-h, --help Show this help messageFor quickly viewing a single file, just run:
lum README.mdThis starts a server that:
- Prints the URL to access the file
- Stays in the foreground (Ctrl+C to stop)
- Serves only the specified file
- No daemon process or log files
If a daemon is already running, the file is automatically added to it instead.
For working with multiple files, start a daemon:
# Start daemon with no files
lum --daemon
# Or start daemon with an initial file
lum --daemon README.mdThe daemon:
- Runs in the background (detaches from terminal)
- Logs to
$XDG_RUNTIME_DIR/lum/lum.log(typically/run/user/$UID/lum/lum.log), or/tmp/lum-$UID/lum.logifXDG_RUNTIME_DIRis not set - Allows adding multiple files
- Persists until explicitly stopped
With a daemon running, add files simply by running:
lum CONTRIBUTING.md
lum docs/API.mdlum automatically detects the running daemon and adds files to it.
- Index page:
http://localhost:6333/- Lists all tracked files - Specific file:
http://localhost:6333/?file=/path/to/file.md
Pages automatically reload when their source file changes.
A link to another Markdown file just works: clicking it renders that file and starts watching it, without a separate lum invocation. Following a link into a document makes that document's own links followable in turn, so a set of cross-referencing documents can be browsed from whichever one you started with. The index page lists the files you have actually opened.
A link to a file that isn't Markdown - a PDF, an image, an archive - serves that file, so an attachment beside a document can be opened from it.
Only files a rendered document references are reachable this way. A Markdown file that nothing links to has to be passed to lum to be served, and the same holds for images and other assets: a document's referenced files are served from wherever they live, and nothing else in their directories is.
This works from Markdown links and images. A raw HTML <img src="./diagram.png"> written directly in the document is passed through untouched and will not load; use  instead.
lum trusts the documents you point it at, the way a shell trusts a script you run.
A document decides what lum will serve on its behalf. It can reference any path its author chose - an absolute one, or one well outside its own directory - and lum serves that path for as long as the document is tracked. Markdown is also rendered with raw HTML enabled, so a document can run scripts in your browser on lum's own origin.
Together those mean that opening a Markdown file you don't trust lets it read any file your user account can read. The server listens on 127.0.0.1 only, so nothing on the network can reach it, but treat lum somefile.md the way you would treat running somefile.sh.
lum --stop
# or
lum -sWhenever lum prints a URL, it also tries to open it in your default browser (xdg-open on Linux, open on macOS). This is skipped when no browser is expected to be available: on headless systems (no DISPLAY or WAYLAND_DISPLAY on Linux) or when the opener is not installed. To disable it entirely, set the LUM_NO_BROWSER environment variable to any non-empty value.
# One-off mode on custom port
lum --port 8080 README.md
# Daemon mode on custom port
lum --daemon --port 8080