MarsDawn

marsdawn for agents

A reference for AI agents and scripts that call the marsdawn command-line tool. Every example on this page was run against the tool built from the current source.

To turn a Markdown file into a PDF, run marsdawn export notes.md --json and read one JSON object from stdout. Mermaid diagrams and highlighted code are rendered the same way as in the MarsDawn app. export doesn't need the app; open does.

What it does

What it does not do

export

marsdawn export notes.md --json

Writes notes.pdf next to notes.md. Options:

marsdawn export notes.md -o out.pdf --theme classic --paper letter --force --json

Success, exit code 0:

{"diagramErrors":[],"ok":true,"output":"/path/to/out.pdf","pages":1,"paper":"letter","theme":"classic"}

open

marsdawn open notes.md --json
marsdawn open notes.md:120 --json
marsdawn open notes.md --line 120 --json
marsdawn open . --json
marsdawn open notes.md --folder . --background --json

Success, exit code 0:

{"app":"/Applications/MarsDawn.app","ok":true,"opened":[{"line":120,"path":"/path/to/notes.md"}]}

With a folder (marsdawn 0.5.1 and later), exit code 0:

{"app":"/Applications/MarsDawn.app","folder":{"path":"/path/to/project","requested":true},"ok":true,"opened":[{"path":"/path/to/project/notes.md"}]}

marsdawn 0.2.x printed opened as a list of path strings. Check marsdawn --version if you need to handle both.

Open files as Claude Code edits them

An opt-in Claude Code hook: after Claude writes or edits a Markdown file, it opens that file in MarsDawn in the background, once per file per session. It's off unless you add it, one project at a time, because a window you didn't ask for takes attention. It runs a shell command and costs no model tokens.

It needs marsdawn 0.5.1 or later, for --background, and the MarsDawn app.

Save this as .claude/hooks/marsdawn-open.sh in your project, and make it executable with chmod +x:

#!/bin/sh
# Claude Code PostToolUse hook: open a Markdown file Claude just wrote or edited in MarsDawn,
# in the background, once per file per session. Never blocks Claude: every path exits 0.
input=$(cat)
file=$(printf '%s' "$input" | /usr/bin/jq -r '.tool_input.file_path // empty' 2>/dev/null)
session=$(printf '%s' "$input" | /usr/bin/jq -r '.session_id // "unknown"' 2>/dev/null)

case "$file" in
  *.md|*.markdown) ;;
  *) exit 0 ;;
esac
[ -f "$file" ] || exit 0
# A hook runs with Claude Code's PATH, which may not include Homebrew's.
marsdawn=$(command -v marsdawn || { [ -x /opt/homebrew/bin/marsdawn ] && echo /opt/homebrew/bin/marsdawn; }) || exit 0
[ -n "$marsdawn" ] || exit 0

# One list per session, so a file opens once however often Claude edits it.
seen="${TMPDIR:-/tmp}/marsdawn-hook/$session"
mkdir -p "$(dirname "$seen")"
grep -qxF "$file" "$seen" 2>/dev/null && exit 0
echo "$file" >> "$seen"

"$marsdawn" open --background "$file" >/dev/null 2>&1 || true
exit 0

Then add the hook to .claude/settings.json in the project, or to .claude/settings.local.json to keep it to yourself:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/marsdawn-open.sh" }
        ]
      }
    ]
  }
}

Failures

With --json, a failure prints one JSON object on stdout and exits with its code:

{"error":"output_exists","message":"/path/to/notes.pdf already exists. Pass --force to replace it.","ok":false}

JSON Schemas

JSON Schema (draft 2020-12) for every --json result:

Environment variables

Requirements

Install

With Homebrew. On Apple silicon it pours a prebuilt bottle in seconds, with no Xcode needed. On an Intel Mac it compiles marsdawn from source, which takes a few minutes and needs Xcode 26 or later.

brew tap redtear1115/tap && brew install marsdawn
marsdawn --version

Or build it from the source. The first build fetches dependencies and compiles, which also takes a few minutes.

git clone https://github.com/redtear1115/mars-dawn-kit.git
cd mars-dawn-kit
swift build -c release --product marsdawn
.build/release/marsdawn export notes.md --json

marsdawn --version prints the version number, such as 0.3.0, and exits with code 0.

Next