ArtCraft 자동화: 제어 채널, CLI 및 MCP
선언
본 스킬은 ArtCraft 시리즈 소프트웨어를 위한 agent skill이며, ArtCraft 공식 저장소가 아닙니다. ArtCraft / LightCraft / FilmCraft / PhotoCraft의 저작권 및 공식 문서는 storyteller(github.com/storytold)에게 귀속됩니다. 본 저장소는 공개된 프로토콜과 CLI를 AI 에이전트용 조작 설명서 및 도구 스크립트로 정리한 것일 뿐, 공식과의 소속이나 보증 관계가 없습니다. 상위 문서와 본 저장소의 내용이 충돌할 경우 공식 문서를 따릅니다.
공식 저장소: lightcraft · filmcraft · photocraft
이게 무엇인가요
ArtCraft 스위트(github.com/storytold)의 각 데스크톱 앱은 UI에서 클릭할 수 있는 모든 메뉴 항목, 슬라이더, 브러시 스트로크를 안정적인 ID와 JSON 파라미터가 있는 명령으로 구현하고, 세 가지 동등한 진입점을 통해 개방합니다:
| 진입점 | 형태 | 용도 |
|---|---|---|
| 제어 채널 | 앱이 TCP 포트를 열고 JSON 라인을 주고받음 | 사용자가 보고 있는 창 직접 조작 |
| CLI | lightcraft-cli / filmcraft-cli / photocraft-cli | 무인 배치 처리 |
| MCP | xxx-cli mcp | Claude 등 클라이언트가 호출하도록 함 |
셋은 동일한 명령 레지스트리를 공유하므로 스크립트와 에이전트가 사람처럼 작업할 수 있으며, 편집 내용도 취소(undo) 가능합니다.
네 가지 핵심 규칙 (이것부터 기억하고 나머지를 보세요)
- 런타임 발견 우선. 본 스킬의 참고 문서는 특정 시점의 스냅샷으로, 탐색과 참고용일 뿐이며 실행 중인 인스턴스가 실제 기준입니다:
engine.commands(명령 레지스트리),methods(메서드 테이블), CLI의--help/commands/controls. 명령 ID를 기억에 의존하지 마세요 — 각 앱과 버전마다 레지스트리가 다릅니다. - 인증 방식이 세 가지로 다르며 변경될 수 있습니다. 작업 전에
scripts/craft_env.py를 실행하여 로컬 머신의auth필드를 확인하세요. 블로그의 포트 명령을 그대로 복사하지 마세요. 알려진 세 가지 상태:- LightCraft: 채널 인증 없음(모든 로컬 프로세스가 구동 가능하며, 사용 후 즉시 종료)
- FilmCraft: 자격 증명을 각 요청의 최상위
token필드에 포함(최신 버전에서는 강제; 출시된 0.9.0에서는 실제로 강제되지 않음) - PhotoCraft: 각 연결의 **첫 번째 프레임은 반드시
auth**여야 함; 파일 접근은 automation 읽기/쓰기 루트 디렉터리로 fail-closed 제한scripts/craft_ctl.py --app <light|film|photo>가 자동으로 해당 방식을 적용합니다; 자격 증명이 없으면 임의로 실패하지 않고 서버 판단에 맡기며 오류를 그대로 읽어옵니다.
- 자격 증명은 명령줄, 로그, 저장소에 절대 기록하지 마세요. 토큰 파일(Unix mode 0600) 또는 환경 변수를 사용하세요; 공유 머신에서 토큰을 프로세스에 평문으로 전달하지 마세요.
- 편집 전에 영향을 알리세요. 사용자의 실제 사진 라이브러리/프로젝트를 건드리기 전에 무엇을 변경할지, 취소 가능 여부, 내보내기 위치를 명확히 설명하고, 불확실한 범위는 질문하세요.
시작: 환경 자체 점검 먼저
python3 scripts/craft_env.py --table # 설치된 버전, CLI 위치, 채널 열림 여부, 자격 증명 위치
python3 scripts/craft_env.py # 동일 내용 JSON
이 단계는 "내가 X 버전을 설치했다고 기억한다"를 대체합니다. 읽기 전용입니다.
진입점 결정
| 사용자 요구 | 선택 | 한 줄 이유 |
|---|---|---|
| "지금 이 앱을 열고 있는데, 클릭/보기를 도와줘" | 제어 채널 | 실제 창 상태를 볼 수 있는 유일한 진입점 |
| "이 200장을 일괄 처리해줘" | CLI headless | 창 렌더링에 의존하지 않아 더 빠르고 안정적 |
| "앞으로 AI에게 이 작업을 바로 시키고 싶어" | MCP | 한 번 연결하면 장기 사용 가능 |
| "지금 무슨 명령을 실행할 수 있지?" | 아무 진입점의 engine.commands / command_list | 유일한 권위 있는 목록 |
A. 제어 채널
시작
세 앱 모두 --control PORT로 채널을 열지만, 시작 플래그와 자격 증명 요구 사항이 다르므로 먼저 craft_env.py와 references/app-matrix.md를 확인하세요:
# LightCraft: 일회성 메모리 세션, 테스트에 최적, 디스크에 저장 안 함
nohup "/Applications/LightCraft.app/Contents/MacOS/LightCraft" --control 7980 --memory > /tmp/lc.log 2>&1 & disown
# FilmCraft: 먼저 자격 증명을 내보내야 함, 그렇지 않으면 수신 대기 안 함
export FILMCRAFT_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_hex(32))')"
nohup "/Applications/FilmCraft.app/Contents/MacOS/FilmCraft" --control 9876 > /tmp/fc.log 2>&1 & disown
# PhotoCraft: 토큰 파일(앱 최초 시작 시 자동 생성, mode 0600)
nohup "/Applications/PhotoCraft.app/Contents/MacOS/PhotoCraft" --control 7878 \
--control-token-file ~/.photocraft/control.token > /tmp/pc.log 2>&1 & disown
프로세스 유지: 단순
&로 시작한 GUI는 시작 셸이 종료되면 회수되어 이후 연결이 모두 거부됩니다.nohup ... & disown을 사용하거나, "시작→조작→종료"를 단일 명령어로 작성하세요.
조작
내장 클라이언트를 사용하고 매번 소켓 코드를 다시 작성하지 마세요:
# 일반 형식: --app이 인증 방식 결정, --port가 포트 번호
python3 scripts/craft_ctl.py --app light --port 7980 engine.commands
python3 scripts/craft_ctl.py --app film --port 9876 --method engine.execute --params '{"command":"sequence.inspect"}'
python3 scripts/craft_ctl.py --app photo --port 7878 --token-file ~/.photocraft/control.token '{"method":"ui.inspect"}'
# 조건부 발견: 명령 레지스트리 간소화 테이블 (--filter로 필터링, 수천 줄 출력 방지)
python3 scripts/craft_ctl.py --app light --port 7980 --discover --filter develop
# 스크립트 모드: stdin에 한 줄에 하나의 요청, '#'로 시작하는 줄은 주석
echo '{"method":"engine.commands"}' | python3 scripts/craft_ctl.py --app light --port 7980
종료 코드: 0 모두 성공 / 1 ok=false 있음 / 2 사용법 또는 연결 오류.
B. CLI (헤드리스 배치 처리)
CLI는 독립적인 릴리스 자산으로, .app 안에 없으며 ArtCraft Launcher도 설치하지 않습니다. 다운로드 및 설치는 references/cli-reference.md를 참조하세요.
lightcraft-cli run --import in.dng develop.set control=light.exposure value=0.7 app.export path=out.jpg longEdge=2048
lightcraft-cli render in.dng -o out.jpg --set light.exposure=0.5
lightcraft-cli commands --json # 명령 레지스트리 (채널의 engine.commands와 동일)
lightcraft-cli controls --json # develop 슬라이더 ID 및 범위
photocraft-cli run wave.psd --cmd filter.sharpen.smartSharpen --params '{"amount":80}' --out out.png
photocraft-cli batch --actions grade.json --in ./raw --out ./graded
filmcraft-cli commands razor # 키워드로 명령 ID 검색
filmcraft-cli describe timeline.razor # 단일 명령의 메뉴/단축키/파라미터/현재 활성화 상태
filmcraft-cli --project p.fcproj --save exec timeline.razor seconds=3.5
filmcraft-cli --bridge 127.0.0.1:9876 exec window.workspace.color # 실행 중인 앱 역제어
일반 규칙: 옵션 위치 자유; JSON 출력; 종료 코드 0=성공 / 1=명령 실패 / 2=사용법 오류; key=value는 JSON으로 파싱 가능하면 JSON으로, 아니면 문자열로 처리; 점 표기법은 중첩을 의미함(color.r=1).
C. MCP (Claude 등 클라이언트 연결)
claude mcp add lightcraft -- lightcraft-cli mcp ~/Pictures/shoot
claude mcp add lightcraft-app -- lightcraft-cli mcp --connect 127.0.0.1:7980
claude mcp add filmcraft -- filmcraft-cli mcp --bridge 127.0.0.1:9876
claude mcp add photocraft -- photocraft-cli mcp --bridge 127.0.0.1:7878 --control-token-file /path/token
헤드리스(프로세스 내 엔진, 창 없음)와 브리지(실행 중인 앱 구동) 두 가지 모드가 있으며, 자격 증명 요구 사항은 references/mcp-servers.md를 참조하세요.
핵심 워크플로: 발견 → 실행 → 검증 → 되돌리기
- 발견:
engine.commands/command_list로 레지스트리를 가져와 label/menu로 대상 명령 ID와 파라미터 문서를 찾습니다. - 실행:
engine.execute {command, params}. 의미 차이에 주의하세요 —ui.menu.invoke는 "메뉴 클릭"(파라미터가 없으면 명령의 대화상자가 열림),engine.execute는 기본 파라미터로 직접 실행하며 대화상자가 열리지 않습니다. - 검증: 추측하지 말고 상태를 읽으세요.
ui.inspect는 일반 UI 상태; 각 앱에는 추가 도메인 상태 메서드가 있습니다(LightCraftlibrary.state/photo.inspect/develop.get, FilmCraftsequence.inspect, PhotoCraftdocument.inspect). - 결과 확인:
ui.screenshot {path}로 창을 캡처합니다(렌더링 완료 후에만 캡처; 창이 프레임을 그리지 않으면 headless 스크린샷 사용). - 되돌리기:
edit.undo/edit.redo. 에이전트의 편집도 undo 스택에 포함됩니다.
프로토콜 불변 규칙 (세 앱이 동일한 부분):
- 한 줄에 하나의 JSON 요청, 한 줄에 하나의 응답, 순서대로 대응:
{"id":N,"method":...,"params":{...}}→{"id":N,"ok":true,"result":...}또는{"id":N,"ok":false,"error":"..."}. - 이벤트 푸시 없음: 채널은 요청에만 응답합니다. GUI 측에서 발생한 일을 알려면 inspect 메서드를 폴링하여 스냅샷을 비교하세요.
- 각 요청은 독립적인 스냅샷: 개체가 변경되면 상태를 다시 읽어야 하며, 캐시된 ID로 현재 상태를 추론하지 마세요.
- 서버 응답 제한 시간 60초; 시간 초과된 명령은 여전히 실행 중일 수 있으므로 재시도 전에 상태를 확인하세요. 긴 작업은
wait:false로 시작하고jobs.list를 폴링하세요.
보안 경계
- 모든 채널은
127.0.0.1만 수신하며, 프로토콜은 암호화되지 않습니다 — 신뢰할 수 없는 호스트로 터널링하거나 프록시하지 마세요. 루프백은 원격만 차단하며, 동일 머신의 다른 프로세스는 차단하지 않습니다. - LightCraft 채널 인증 없음: 필요에 따라 열고,
LIGHTCRAFT_CONFIG_DIR로 구성을 격리하여 자동화에 사용하고, 사용 후 닫습니다. - PhotoCraft 파일 시스템 fail-closed: 자동화 읽기/쓰기는
--automation-read-root/--automation-write-root범위로 제한되며, 권한이 없으면 거부됨;file.open/file.save는 채널에서 거부되므로app.open/app.save를 사용하세요. - FilmCraft의
FILMCRAFT_CONTROL_TOKEN은 모든 제어 권한과 동일: 기밀로 유지하고 명령줄 기록이나 MCP 설정에 넣지 마세요. - 기본적으로 사용자의 기존 데이터를 건드리지 않습니다(예: LightCraft의
~/Pictures/LightCraft Library), 사용자가 명시적으로 요청하지 않는 한.
문제 발생 시 먼저 확인할 곳
references/known-pitfalls.md에는 실제로 경험한 함정(연결 거부, 프레임 없음 시간 초과, PhotoCraft에 --help 없음, 내보내기 원자 저장이 시스템 정책에 의해 차단됨, 레이어 원점 오프셋, quad 상대 좌표 등)이 기록되어 있습니다. 먼저 표를 확인하고, 동일한 오류 명령을 반복하지 마세요.
참고 문서 색인
| 파일 | 내용 |
|---|---|
references/app-matrix.md | 세 앱 차이점 빠른 참조(시작 플래그, 자격 증명, 샌드박스, 상태 메서드, CLI/MCP 진입점) — 이것부터 보세요 |
references/control-protocols.md | 제어 채널 프로토콜: 일반 메커니즘 + 각 앱의 메서드 테이블 + 인증 세 가지 상태 |
references/cli-reference.md | 세 CLI의 다운로드, 하위 명령, 파라미터 의미, 종료 코드 |
references/mcp-servers.md | MCP 서버 도구 목록, 두 가지 모드, 연결 방식 |
references/known-pitfalls.md | 실제 함정 및 문제 해결 경로 |
references/upstream-sources.md | 상위 문서 주소, 스냅샷 날짜, 이 참고 문서를 새로 고치는 방법 |
scripts/craft_ctl.py | 제어 채널 클라이언트 (세 앱의 인증 차이점 내장) |
scripts/craft_env.py | 환경 자체 점검: 앱, 버전, CLI, 채널, 자격 증명 |