Command Line
The free marsdawn command-line tool: export Markdown to PDF from a shell or an LLM agent, and, with the MarsDawn app installed, open files in it.
marsdawn is free and distributed separately from the Mac App Store. Install it with Homebrew: on an Apple silicon Mac it arrives ready to run. export works on its own; open needs the MarsDawn app.
Calling marsdawn from an AI agent or a script? See marsdawn for agents for the JSON output, its schemas and every exit code, or the MCP server if your agent calls tools over MCP instead.
Install
With Homebrew:
brew tap redtear1115/tap && brew install marsdawn
Using a coding agent? Run marsdawn skill --install to add the marsdawn skill: one file that teaches it to open what it wrote in MarsDawn for your review, and to export PDFs.
On an Apple silicon Mac, Homebrew installs a prebuilt copy in seconds, with nothing else to install. On an Intel Mac it builds marsdawn from source instead, which takes a few minutes and needs Xcode 26 or later (Swift 6.2). The tool runs on macOS 15 or later.
Or build it from the source with Swift Package Manager:
git clone https://github.com/redtear1115/mars-dawn-kit.git
cd mars-dawn-kit
swift build -c release --product marsdawn
Check which version you have with marsdawn --version.
Commands
marsdawn open
Opens one or more Markdown files in the MarsDawn app for review. It needs the app installed: without it, marsdawn open exits with code 3 and says MarsDawn isn't installed. export doesn't need the app. The app is on the Mac App Store.
marsdawn open notes.md
marsdawn open notes.md:120
marsdawn open notes.md --line 120
marsdawn open .
marsdawn open notes.md --folder .
path:line: asks MarsDawn to land on that line. A column after it, as innotes.md:120:8, is ignored. If a file with the whole name exists, the argument is that file.--line <n>: the same for a single file, and the way to ask for a line on a path that itself ends in a colon and digits. Needs exactly one file.- Lines run from 1 to 999999999.
- MarsDawn 1.0 opens the file at that line.
- A folder argument opens in the window's sidebar instead of as a document:
marsdawn open .shows the current folder.--folder <path>does the same alongside files. A window's sidebar shows one folder, so naming two is a usage error. --wait <n>: with MarsDawn 1.0.2 or later, which reports back,--folderwaits up to n seconds (0 to 30, default 2) for the app's answer about the folder.--wait 0, or an app that doesn't report back, doesn't wait and sends the same request as before.- A
--waitvalue outside 0 to 30 is a usage error (exit 64). Write a negative value as--wait=-1. - With
--json, the folder is reported as requested, not attached, because the app decides; with--wait, the result also says what happened to it. The full list is in marsdawn for agents. --background: open without bringing MarsDawn to the front.--json: print a JSON result instead of text.
Lines were added in marsdawn 0.3.0, folders and --background in 0.5.1, and --wait with the folder status in 0.5.3.
marsdawn export
Renders a Markdown file to a paginated PDF, with the same exporter MarsDawn's own PDF export uses. It doesn't need the MarsDawn app. Relative images resolve against the input file's folder.
marsdawn export notes.md -o notes.pdf --theme classic --paper a4
-o, --output <path>: where to write the PDF. Defaults to the input path with a.pdfextension.--theme <dawn|classic|modern|vivid>: the preview theme's light palette. Defaults to$MARSDAWN_THEME, thendawn.--paper <a4|letter>: paper size. Defaults toa4.--breaks: turn every newline inside a paragraph into a line break, as HackMD does. Without it, a newline between two Chinese or Japanese characters is dropped, so the lines read as one sentence.--layout <document|handbook>: the page layout. Defaults todocument.handbookprints a handbook: wider margins with a binding side, each top-level heading on a new page, a contents page with page numbers, page numbers in the footer and PDF bookmarks, plus a cover when the front matter has atitle.--toc-title <text>: the heading of the handbook's contents page. Defaults toContents.<!--BREAK-->on a line of its own starts a new page, in either layout.--allow-remote-images: load images from the web while rendering. Off by default.--force: replace the output file if it already exists.--json: print a JSON result instead of text.- A file over 16 MiB isn't exported:
exportexits 5 and writes nothing.
--breaks was added in marsdawn 0.7.0, --layout and --toc-title in 0.7.1, and the name handbook in 0.7.2. The 0.7.1 name, manual, still works.
marsdawn theme
Checks a theme file (theme.json) and shows what it looks like, before you share it. It doesn't need the MarsDawn app. For the fields of a theme, see Make a theme with your agent.
marsdawn theme validate my-theme.json
marsdawn theme css my-theme.json
marsdawn theme preview my-theme.json --appearance dark -o preview.png
validate <file>: checks the file against every rule a MarsDawn theme must meet, with the validator the app uses. Exits 0 when the theme is valid, and 1 when it isn't, listing each problem.--require-completealso requires the syntax and diagram colors, which a published theme must have.css <file>: prints the CSS the preview uses for a valid theme.preview <file> --appearance <light|dark> -o <out.png>: renders a sample document with the theme to a PNG.--widthsets its width in pixels, from 600 to 2000 (default 1200). An existing file is replaced only with--force.--json: print a JSON result instead of text.
The theme commands were added in marsdawn 0.6.1.
The $MARSDAWN_THEME variable
When --theme isn't passed, export reads the $MARSDAWN_THEME environment variable. Its value must be one of dawn, classic, modern or vivid; anything else falls back to dawn. The CLI doesn't read the app's own theme setting, because reading another app's container can trigger a macOS privacy prompt.
Overwriting files
export refuses to replace an existing output file unless you pass --force.
Exit codes
| Code | Means | What to do |
|---|---|---|
0 | success. | With --json, read the one JSON line on stdout |
2 | input not found. | Check the path and the file name |
3 | MarsDawn is not installed (open only). | Install the app, or use export, which doesn't need it |
4 | output exists (pass --force). | Pass --force to replace it, or -o to write elsewhere |
5 | export failed. | Read message in the JSON result |
6 | this MarsDawn can't show a folder, so nothing was opened (open only). | |
64 | usage error, including a line out of range, --line with more than one file or with a folder, or more than one folder. | Fix the option or value; this error is text on stderr, even with --json |
--json output
On success, marsdawn open --json prints ok, opened (a list with each file's path, plus line when one was asked for), app (the app path) and, when a folder was given, folder. marsdawn export --json prints ok, output, pages, theme, paper and diagramErrors. On failure, both print ok, error and message.