에이전트를 위한 marsdawn
marsdawn 명령줄 도구를 호출하는 AI 에이전트와 스크립트를 위한 레퍼런스입니다. 이 페이지의 모든 예시는 현재 소스로 빌드한 도구에서 실제로 실행했습니다.
Markdown 파일을 PDF로 바꾸려면 marsdawn export notes.md --json을 실행하고 stdout에서 JSON 객체 하나를 읽으세요. Mermaid 다이어그램과 강조 표시된 코드는 MarsDawn 앱에서와 똑같이 렌더링됩니다. export에는 앱이 필요 없고, open에는 필요합니다.
하는 일
export는 MarsDawn 앱과 같은 내보내기 엔진으로 Markdown 파일 하나를 페이지가 나뉜 PDF로 렌더링합니다. 윈도우는 열리지 않습니다.open은 사람이 검토할 수 있도록 하나 이상의 Markdown 파일을 MarsDawn 앱에서 엽니다. 각 파일이 열릴 줄을 지정할 수 있고, 윈도우 사이드바에 폴더를 표시할 수도 있습니다.
하지 않는 일
- stdin에서 Markdown을 읽지 않습니다. 파일 경로를 전달하세요.
- PDF를 stdout에 쓰지 않습니다. PDF는 항상 파일로 저장되고, stdout에는 결과만 나옵니다.
--force를 주지 않으면 기존 파일을 덮어쓰지 않습니다.--allow-remote-images를 주지 않으면 웹에서 이미지를 불러오지 않으며, 줄 때도 https로만 불러옵니다.open은 MarsDawn 앱이 설치되어 있지 않으면 동작하지 않고 코드 3으로 종료합니다.export에는 앱이 필요 없습니다. 앱은 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 앱의 경로.
폴더를 준 경우(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에 폴더를 보여 달라고 요청했을 뿐이고, 앱이 먼저 사람에게 접근 권한을 물을 수 있으므로 사이드바에 실제로 표시됐는지는 알 수 없습니다. 완료가 아니라 요청됨으로 보고하세요.--wait가 0보다 크고 MarsDawn이 1.0.2 이상이면, 기다림이 끝난 뒤folder에status도 담깁니다. 값은attached,needsUser,declined,failed,attachedDifferentFolder,full,unavailable,unknown중 하나입니다.needsUser일 때만waitingFor(confirmation또는folderChoice)도 담깁니다.--wait가 없거나 결과를 알려 주지 않는 앱이면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 훅입니다. Claude가 Markdown 파일을 쓰거나 편집하면 그 파일을 MarsDawn에서 백그라운드로 엽니다. 세션마다 파일당 한 번입니다. 요청하지 않은 윈도우는 주의를 빼앗기 때문에, 직접 추가하기 전까지는 꺼져 있고 프로젝트별로 하나씩 켭니다. 셸 명령을 실행할 뿐이라 모델 토큰은 들지 않습니다.
--background를 쓰므로 marsdawn 0.5.1 이상과 MarsDawn 앱이 필요합니다.
다음을 프로젝트의 .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
그런 다음 프로젝트의 .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가 몇 번을 편집하든 각 파일은 Claude Code 세션마다 한 번만 열립니다. 목록은
$TMPDIR/marsdawn-hook/에 세션마다 파일 하나로 저장되므로, 새 세션에서는 파일이 다시 열립니다. --background덕분에 MarsDawn이 앞으로 나오지 않습니다. 작업하던 윈도우가 포커스를 유지합니다.- Claude를 방해하지 않습니다. 모든 경로가 0으로 끝나며, marsdawn이나 MarsDawn 앱이 설치되어 있지 않으면 아무 일도 일어나지 않습니다.
- 훅의 입력은
/usr/bin/jq로 읽습니다. jq는 MarsDawn 앱이 요구하는 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등이 해당합니다. 이 오류는--json을 줘도 stderr에 텍스트로 출력됩니다.
JSON 스키마
모든 --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 실리콘에서는 Homebrew가 미리 빌드된 bottle을 설치하므로 다른 것은 필요 없습니다. Intel Mac에서나 소스로 직접 빌드하려면 Swift 6.2 이상이 필요하며, 이는 Xcode 26 이상에 들어 있습니다.
- MarsDawn 앱은 macOS 26 이상이 필요합니다.
설치
Homebrew로 설치합니다. Apple 실리콘에서는 미리 빌드된 bottle을 몇 초 만에 설치하며 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 스킬.
- 이
export를 그대로 감싼 MCP 서버: marsdawn-mcp. - 이 JSON 결과가 에이전트 자신의 컨텍스트에 부담이 적은 이유: 토큰을 아끼는 검토.
- 에이전트로 MarsDawn 테마 만들기: 에이전트와 함께 테마 만들기.