给 AI 代理的 marsdawn 参考
给调用 marsdawn 命令行工具的 AI 代理与脚本参考。本页每个范例都用目前源代码构建的工具实际运行过。
要把 Markdown 文件转成 PDF,运行 marsdawn export notes.md --json,再从 stdout 读取一个 JSON 对象。Mermaid 图表与代码高亮的呈现方式和 MarsDawn app 相同。export 不需要 app,open 需要。
能做什么
export:用和 MarsDawn app 相同的导出程序,把一个 Markdown 文件导出成分页的 PDF,不会打开任何窗口。open:在 MarsDawn app 中打开一或多个 Markdown 文件,让人审阅,也可以指定每个文件要定位的行,或在窗口的侧边栏显示一个文件夹。
不做什么
- 不从 stdin 读取 Markdown,请传入文件路径。
- 不把 PDF 写到 stdout。PDF 一律写成文件,stdout 只输出结果。
- 文件已存在时不会覆盖,除非加上
--force。 - 不加载网络图片,除非加上
--allow-remote-images,而且只走 https。 - 没有安装 MarsDawn 时,
open无法使用,会以代码 3 结束。export不需要 app。App 已在 Mac App Store 上架。 - MarsDawn 1.0 会跳到
open指定的行。 - 只能在 macOS 上运行。
export
marsdawn export notes.md --json
在 notes.md 旁写出 notes.pdf。选项:
-o, --output <path>:PDF 的写入位置。默认为输入文件路径,扩展名换成.pdf。--theme <dawn|classic|modern|vivid>:使用主题的浅色调色板。默认为$MARSDAWN_THEME,其次是dawn。--paper <a4|letter>:纸张大小。默认为a4。--allow-remote-images:渲染时加载网络上的 https 图片。--force:输出文件已存在时覆盖。--json:在 stdout 输出一个 JSON 对象,而不是文本。
marsdawn export notes.md -o out.pdf --theme classic --paper letter --force --json
成功,退出代码 0:
{"diagramErrors":[],"ok":true,"output":"/path/to/out.pdf","pages":1,"paper":"letter","theme":"classic"}
output:写出的 PDF 的绝对路径。pages:页数。theme与paper:实际使用的值。diagramErrors:每个渲染失败的 Mermaid 图表各一则消息。PDF 仍会写出。
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
path:line指定要定位的行。后面再接列号,例如notes.md:120:8,会被忽略。如果参数本身就是一个存在的文件名,就一律当成那个文件,所以名为weird:12的文件会照原名打开。--line <n>为单一文件指定行号,包括文件名本身以冒号加数字结尾的情况。只能搭配一个文件。- 行号范围是 1 到 999999999,超出范围是用法错误。
- 行号从 marsdawn 0.3.0 开始提供。MarsDawn 1.0 会打开文件,并跳到指定的行。
- 文件夹参数会在窗口的侧边栏打开,而不是当成文稿,所以
marsdawn open .会显示当前的文件夹;--folder <path>可以在打开文件的同时做到一样的事。一个窗口的侧边栏只显示一个文件夹:指定两个是用法错误,--folder用两次也是(即使是同一个文件夹);同一个文件夹以参数再指定一次则算一个。文件夹没有行号,所以--line搭配文件夹是用法错误。没有-a:传入它是用法错误,错误消息会指向--folder。 --background打开时不把 MarsDawn 带到最前面,适合在用户做别的事时打开文件的代理。两种情况的 JSON 都一样。- 文件夹与
--background从 marsdawn 0.5.1 开始提供。
成功,退出代码 0:
{"app":"/Applications/MarsDawn.app","ok":true,"opened":[{"line":120,"path":"/path/to/notes.md"}]}
opened:每个文件一个对象,顺序与传入时相同。path是文件的绝对路径;只有指定了行号时才有line。app:打开它们的 MarsDawn app 路径。
有文件夹时(marsdawn 0.5.1 以后),退出代码 0:
{"app":"/Applications/MarsDawn.app","folder":{"path":"/path/to/project","requested":true},"ok":true,"opened":[{"path":"/path/to/project/notes.md"}]}
folder:只有指定了文件夹时才有。path是它的绝对路径。requested一律是true:marsdawn 已请 MarsDawn 显示这个文件夹,但无法得知侧边栏是否真的显示了,因为 app 可能会先向用户请求访问权限。请报告为“已请求”,而不是“已完成”。--wait大于 0,且 MarsDawn 为 1.0.2 或更高版本时,等待结束后folder还会带有status:attached、needsUser、declined、failed、attachedDifferentFolder、full、unavailable或unknown。只有在needsUser时,才会再带有waitingFor:confirmation或folderChoice。没有--wait,或 app 不会回报时,folder保持{"path": …, "requested": true}。--wait超出 0 到 30 时以代码 64 结束,并带有error: "wait_out_of_range"。(marsdawn 0.5.3 及更高版本。)- 只指定文件夹时,
opened是空的。
marsdawn 0.2.x 的 opened 是路径字符串的清单。如果需要同时处理两种格式,请先查看 marsdawn --version。
在 Claude Code 编辑时打开文件
一个需要自行启用的 Claude Code hook:Claude 写入或编辑 Markdown 文件之后,在后台用 MarsDawn 打开那个文件,每个 session 每个文件只打开一次。除非你添加它,否则不会启用,而且要一个项目一个项目地添加,因为你没要求就弹出来的窗口会打断注意力。它运行的是 shell 命令,不花模型 token。
需要 marsdawn 0.5.1 或更新版本,才有 --background,以及 MarsDawn app。
把下面的内容保存为项目里的 .claude/hooks/marsdawn-open.sh,再用 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
然后把 hook 加到项目的 .claude/settings.json;如果只想自己用,改加到 .claude/settings.local.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/marsdawn-open.sh" }
]
}
]
}
}
- 它在 Claude 的 Write 和 Edit 工具之后运行。扩展名不是
.md或.markdown的文件不会处理。 - 在同一个 Claude Code session 里,每个文件只打开一次,不管 Claude 编辑几次。清单保存在
$TMPDIR/marsdawn-hook/,每个 session 一个文件,所以开新的 session 会再打开一次。 --background让 MarsDawn 不会跳到最前面:你正在用的窗口会保持焦点。- 它不会妨碍 Claude。每条路径都以 0 退出;如果没有安装 marsdawn 或 MarsDawn app,就什么都不做。
- 它用
/usr/bin/jq读取 hook 的输入。macOS 26 自带这个工具,而 MarsDawn app 也需要 macOS 26。 - 要关掉,从设置文件里删除这一项即可。
失败
加上 --json 时,失败会在 stdout 输出一个 JSON 对象,并以对应的代码结束:
{"error":"output_exists","message":"/path/to/notes.pdf already exists. Pass --force to replace it.","ok":false}
2,input_not_found:输入文件不存在、是文件夹,或不是 UTF-8 文本;或--folder的路径不存在、不是文件夹。3,app_not_installed:没有安装 MarsDawn。只有open会返回这个代码。4,output_exists:输出文件已存在,请加上--force。5,export_failed:导出本身失败。6,app_cannot_open_folders:这个版本的 MarsDawn 还不能显示文件夹,所以没有打开任何东西。只有open会返回这个代码。64:用法错误,例如未知的选项、无效的值、行号超出范围、--line搭配了多个文件或文件夹、指定了多个文件夹,或使用了-a。这种错误一律以文本输出到 stderr,即使加了--json也一样。
JSON Schema
每种 --json 结果的 JSON Schema(draft 2020-12):
- export.v1.json: export 成功
- open.v4.json: open 成功,marsdawn 0.5.3 以后,文件夹多了
status和waitingFor - open.v3.json: open 成功,marsdawn 0.5.1 和 0.5.2,包括在侧边栏显示的文件夹
- error.v3.json: 所有命令的失败结果,marsdawn 0.7.1 以后,新增
input_too_large(代码 5)和skill_install_failed(代码 7) - error.v2.json: 两个命令的失败结果,marsdawn 0.5.2 到 0.7.0
- open.v2.json: open 成功,marsdawn 0.3.0 到 0.5.0
- open.v1.json: open 成功,marsdawn 0.2.x,当时
opened是路径清单 - error.v1.json: 两个命令的失败结果,marsdawn 0.5.1 以前
环境变量
MARSDAWN_THEME:没有传入--theme时,export使用的主题。未知的值会直接改用dawn,不会报错。
系统需求
- 这个工具需要 macOS 15 以上。在 Apple 芯片的 Mac 上,Homebrew 会安装预先构建好的版本,不需要其他东西。自己构建时(在 Intel Mac 上,或从源代码构建),需要 Swift 6.2 以上,也就是 Xcode 26 以上。
- MarsDawn app 需要 macOS 26 以上。
安装
使用 Homebrew。在 Apple 芯片的 Mac 上,会直接安装预先构建好的版本,几秒就完成,不需要 Xcode。在 Intel Mac 上则会从源代码编译 marsdawn,需要几分钟,也需要 Xcode 26 以上。
brew tap redtear1115/tap && brew install marsdawn
marsdawn --version
也可以从源代码构建。第一次构建会下载依赖项并编译,同样需要几分钟。
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 会输出版本号,例如 0.3.0,并以代码 0 结束。
接下来
- 用代理做一个 MarsDawn 主题:和代理一起做主题。