marsdawn para agentes
Una referencia para agentes de IA y scripts que llaman a la herramienta de línea de comandos marsdawn. Cada ejemplo de esta página se ejecutó con la herramienta compilada desde el código fuente actual.
Para convertir un archivo Markdown en PDF, ejecuta marsdawn export notes.md --json y lee un objeto JSON de stdout. Los diagramas Mermaid y el código resaltado se renderizan igual que en la app MarsDawn. export no necesita la app; open, sí.
Qué hace
exportrenderiza un archivo Markdown como un PDF paginado, con el mismo exportador que la app MarsDawn. No se abre ninguna ventana.openabre uno o varios archivos Markdown en la app MarsDawn para que una persona los revise; puede indicar la línea en la que debe abrirse cada archivo y mostrar una carpeta en la barra lateral de la ventana.
Qué no hace
- No lee Markdown desde stdin. Pasa una ruta de archivo.
- No escribe el PDF en stdout. El PDF siempre va a un archivo; stdout solo lleva el resultado.
- No reemplaza un archivo existente a menos que pases
--force. - No carga imágenes de la web a menos que pases
--allow-remote-images, y en ese caso solo por https. openno funciona si la app MarsDawn no está instalada; termina con el código 3.exportno necesita la app. La app está en el Mac App Store.- MarsDawn 1.0 abre el archivo en la línea que indica
open. - Solo funciona en macOS.
export
marsdawn export notes.md --json
Escribe notes.pdf junto a notes.md. Opciones:
-o, --output <path>: dónde escribir el PDF. De forma predeterminada, la ruta de entrada con la extensión.pdf.--theme <dawn|classic|modern|vivid>: la paleta clara del tema. De forma predeterminada,$MARSDAWN_THEMEy, si no,dawn.--paper <a4|letter>: tamaño de papel. De forma predeterminada,a4.--allow-remote-images: carga imágenes https de la web durante el renderizado.--force: reemplaza el archivo de salida si existe.--json: imprime un objeto JSON en stdout en lugar de texto.
marsdawn export notes.md -o out.pdf --theme classic --paper letter --force --json
Éxito, código de salida 0:
{"diagramErrors":[],"ok":true,"output":"/path/to/out.pdf","pages":1,"paper":"letter","theme":"classic"}
output: ruta absoluta del PDF que se escribió.pages: número de páginas.themeypaper: los valores usados.diagramErrors: un mensaje por cada diagrama Mermaid que no se pudo renderizar. El PDF se escribe de todos modos.
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:lineindica la línea en la que abrir. Una columna después, como ennotes.md:120:8, se ignora. Un argumento que nombra un archivo existente siempre es ese nombre de archivo completo, así que un archivo llamadoweird:12se abre tal cual.--line <n>indica la línea para un solo archivo, incluida una ruta que termina en dos puntos y dígitos. Necesita exactamente un archivo.- Las líneas van de 1 a 999999999. Cualquier otro valor es un error de uso.
- Las líneas se agregaron en marsdawn 0.3.0. MarsDawn 1.0 abre el archivo en esa línea.
- Una carpeta como argumento se abre en la barra lateral de la ventana en lugar de como documento, así que
marsdawn open .muestra la carpeta actual;--folder <path>hace lo mismo junto con archivos. La barra lateral de una ventana muestra una sola carpeta: indicar dos es un error de uso, igual que usar--folderdos veces, aunque sea para la misma carpeta; la misma carpeta repetida como argumento cuenta una vez.--linecon una carpeta es un error de uso, porque una carpeta no tiene líneas. No existe-a: pasarlo es un error de uso que remite a--folder. --backgroundabre sin traer MarsDawn al frente, para un agente que abre archivos mientras la persona trabaja en otra cosa. El JSON es el mismo en ambos casos.- Las carpetas y
--backgroundse agregaron en marsdawn 0.5.1.
Éxito, código de salida 0:
{"app":"/Applications/MarsDawn.app","ok":true,"opened":[{"line":120,"path":"/path/to/notes.md"}]}
opened: un objeto por archivo, en el orden dado.pathes la ruta absoluta del archivo;linesolo aparece cuando se pidió una línea.app: ruta de la app MarsDawn que los abrió.
Con una carpeta (marsdawn 0.5.1 y posterior), código de salida 0:
{"app":"/Applications/MarsDawn.app","folder":{"path":"/path/to/project","requested":true},"ok":true,"opened":[{"path":"/path/to/project/notes.md"}]}
folder: solo aparece cuando se dio una carpeta.pathes su ruta absoluta.requestedsiempre estrue: marsdawn le pidió a MarsDawn que mostrara la carpeta y no puede saber si la barra lateral la muestra, porque la app puede pedirle acceso a la persona primero. Infórmalo como solicitado, no como hecho.- Con un
--waitmayor que 0 y MarsDawn 1.0.2 o posterior,foldertambién incluyestatuscuando termina la espera:attached,needsUser,declined,failed,attachedDifferentFolder,full,unavailableounknown. Solo junto conneedsUserincluyewaitingFor:confirmationofolderChoice. Sin--wait, o con una app que no informa del resultado,foldersigue siendo{"path": …, "requested": true}. Un--waitfuera de 0 a 30 termina con el código 64 yerror: "wait_out_of_range". (marsdawn 0.5.3 y posterior.) openedestá vacío cuando solo se dio una carpeta.
marsdawn 0.2.x imprimía opened como una lista de rutas en texto. Revisa marsdawn --version si necesitas manejar ambos casos.
Abrir archivos mientras Claude Code los edita
Un hook de Claude Code opcional: después de que Claude escribe o edita un archivo Markdown, lo abre en MarsDawn en segundo plano, una vez por archivo y por sesión. Está desactivado hasta que lo agregas, proyecto por proyecto, porque una ventana que no pediste se lleva tu atención. Ejecuta un comando de shell y no gasta tokens del modelo.
Necesita marsdawn 0.5.1 o posterior, por --background, y la app MarsDawn.
Guarda esto como .claude/hooks/marsdawn-open.sh en tu proyecto y hazlo ejecutable con 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
Luego agrega el hook a .claude/settings.json en el proyecto, o a .claude/settings.local.json para que sea solo tuyo:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/marsdawn-open.sh" }
]
}
]
}
}
- Se ejecuta después de las herramientas Write y Edit de Claude. Los archivos que no terminan en
.mdo.markdownno se tocan. - Cada archivo se abre una vez por sesión de Claude Code, sin importar cuántas veces Claude lo edite. La lista vive en
$TMPDIR/marsdawn-hook/, un archivo por sesión, así que una sesión nueva vuelve a abrir el archivo. --backgroundevita que MarsDawn pase al frente: la ventana en la que trabajabas conserva el foco.- Nunca le estorba a Claude. Cada ruta termina con 0, y si marsdawn o la app MarsDawn no están instalados, no pasa nada.
- Lee la entrada del hook con
/usr/bin/jq, que viene con macOS 26, la versión que necesita la app MarsDawn. - Para desactivarlo, quita la entrada del archivo de configuración.
Errores
Con --json, un error imprime un objeto JSON en stdout y termina con su código:
{"error":"output_exists","message":"/path/to/notes.pdf already exists. Pass --force to replace it.","ok":false}
2,input_not_found: la entrada no existe, es una carpeta o no es texto UTF-8; o una ruta de--folderno existe o no es una carpeta.3,app_not_installed: MarsDawn no está instalado. Soloopendevuelve este código.4,output_exists: el archivo de salida existe. Pasa--force.5,export_failed: la exportación en sí falló.6,app_cannot_open_folders: esta versión de MarsDawn no puede mostrar una carpeta, así que no se abrió nada. Soloopendevuelve este código.64: error de uso, como una opción desconocida, un valor no válido, una línea fuera de rango,--linecon más de un archivo o con una carpeta, más de una carpeta o-a. Este se imprime como texto en stderr, incluso con--json.
Esquemas JSON
JSON Schema (draft 2020-12) para cada resultado de --json:
- export.v1.json: éxito de export
- open.v4.json: éxito de open, marsdawn 0.5.3 y posterior, con
statusywaitingForde la carpeta - open.v3.json: éxito de open, marsdawn 0.5.1 y 0.5.2, incluida una carpeta mostrada en la barra lateral
- error.v3.json: error, todos los comandos, marsdawn 0.7.1 y posterior, con
input_too_large(código 5) yskill_install_failed(código 7) - error.v2.json: error, ambos comandos, marsdawn 0.5.2 a 0.7.0
- open.v2.json: éxito de open, marsdawn 0.3.0 a 0.5.0
- open.v1.json: éxito de open, marsdawn 0.2.x, donde
openedera una lista de rutas - error.v1.json: error, ambos comandos, marsdawn 0.5.1 y anterior
Variables de entorno
MARSDAWN_THEME: el tema que usaexportcuando no se pasa--theme. Un valor desconocido vuelve adawnsin error.
Requisitos
- La herramienta funciona en macOS 15 o posterior. En chips de Apple, Homebrew instala un bottle precompilado y no se necesita nada más. Compilarla tú mismo, en una Mac con Intel o desde el código fuente, requiere Swift 6.2 o posterior, que viene con Xcode 26 o posterior.
- La app MarsDawn requiere macOS 26 o posterior.
Instalación
Con Homebrew. En chips de Apple instala un bottle precompilado en segundos, sin necesidad de Xcode. En una Mac con Intel compila marsdawn desde el código fuente, lo que tarda unos minutos y requiere Xcode 26 o posterior.
brew tap redtear1115/tap && brew install marsdawn
marsdawn --version
O compílala desde el código fuente. La primera compilación descarga las dependencias y compila, lo que también tarda unos minutos.
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 imprime el número de versión, como 0.3.0, y termina con el código 0.
Siguiente
- Una skill de un solo archivo para agentes que leen instrucciones en lugar de usar una shell: la skill de marsdawn.
- Un servidor MCP que envuelve este mismo
export: marsdawn-mcp. - Por qué este resultado JSON sale barato para el contexto del propio agente: revisión con pocos tokens.
- Crear un tema de MarsDawn con un agente: Crea un tema con tu agente.