자동화 대상은 “어려운 일”이 아니라 “판정이 쉬운 일”입니다

자동화할 업무를 고를 때 난이도부터 보면 대개 실패합니다. 기준은 다른 데 있습니다. 결과가 맞았는지 5초 안에 판정할 수 있는가. 커밋 메시지 초안은 읽으면 바로 압니다. 빌드 에러 원인 요약도 그렇습니다. 반대로 시장 분석이나 전략 제안은 결과가 그럴듯해 보여서 검증에 30분이 걸립니다. 그런 작업은 대화창에서 사람이 옆에 붙어 있는 게 맞습니다.

업무판정 시간어디서 돌릴까
변경분에서 오타·깨진 링크 찾기즉시스크립트
에러 로그에서 원인 한 줄 요약즉시스크립트
회의록에서 결정사항만 추출짧음스크립트
코드 리뷰(보안 관점)중간스크립트 + 사람 확인
기획안 작성, 우선순위 판단길다대화창

여기서 ‘스크립트’라고 적은 것들은 전부 클로드를 사람처럼 대하지 않고 명령줄 도구처럼 쓰는 작업입니다. 입력을 파이프로 넣고, 출력을 파일이나 다음 명령으로 넘기는 방식입니다.

시작은 -p 한 글자입니다

Claude Code는 기본적으로 대화형 세션을 띄우지만, -p(또는 --print)를 붙이면 대답을 출력하고 바로 종료합니다. 설치된 버전에서 도움말을 그대로 확인하면 이렇게 적혀 있습니다.

설치 버전과 옵션 설명 (2026.09.17 실행)

$ claude --version 2.1.271 (Claude Code) $ claude --help -p, --print Print response and exit (useful for pipes)

Claude Code 공식 문서의 Run Claude Code programmatically 페이지. -p 플래그와 --allowedTools를 사용한 예시 명령이 코드 블록으로 표시돼 있다
Claude Code 공식 문서 비대화형 실행은 -p에 프롬프트를 넘기는 형태로 안내되며, 오른쪽 목차에 bare 모드·종료 처리·구조화 출력 항목이 나열돼 있습니다. 촬영 2026.09.17 · 출처 code.claude.com/docs/en/headless

이 모드는 표준 입력을 읽습니다. 그래서 다른 명령의 출력을 그대로 넘길 수 있습니다. 공식 문서가 드는 예시가 가장 직관적입니다.

빌드 로그를 넘겨 원인만 받기

cat build-error.txt | claude -p '이 빌드 에러의 근본 원인만 간단히 설명해줘' > output.txt

파이프로 넣는 입력에는 상한이 있습니다. 10MB를 넘기면 명령이 오류와 함께 0이 아닌 상태 코드로 끝납니다. 큰 파일은 파이프 대신 경로를 알려주고 읽게 하는 편이 맞습니다.

스크립트에 넣을 때는 --bare를 같이 봅니다

그냥 -p로 실행하면 대화형 세션과 똑같은 맥락을 불러옵니다. 작업 폴더와 ~/.claude의 훅, 스킬, 서브에이전트, MCP 서버, CLAUDE.md까지 전부입니다. 내 컴퓨터에서는 편하지만 CI에서는 재현성이 깨집니다. --bare는 이 자동 탐색을 건너뛰어 어느 기계에서 돌려도 같은 결과가 나오게 합니다. 대신 인증은 구독 로그인이 아니라 ANTHROPIC_API_KEY만 씁니다. 공식 문서는 스크립트와 SDK 호출에는 --bare를 권장하며, 향후 -p의 기본값이 될 예정이라고 밝히고 있습니다.

사람이 읽을 답이 아니라 프로그램이 읽을 데이터를 받습니다

자동화의 갈림길은 출력 형식입니다. 텍스트를 받으면 결국 사람이 읽어야 하고, JSON을 받으면 다음 단계가 자동으로 이어집니다. --output-format은 세 가지를 지원합니다. 기본 text, 한 덩어리로 받는 json, 줄 단위로 흘려받는 stream-json입니다.

실제로 이 사이트 저장소에서 --output-format json을 실행해 받은 응답에 어떤 필드가 들어 있는지만 추려보면 이렇습니다. 값은 자리표시로 두었습니다.

JSON 응답의 주요 필드 (실행 응답에서 필드명만 발췌)

{ "type": "result", "subtype": ..., "is_error": ..., "result": ..., // 답 본문 또는 실패 메시지 "session_id": ..., "num_turns": ..., "duration_ms": ..., "duration_api_ms": ..., "total_cost_usd": 0, "usage": { "input_tokens": 0, "output_tokens": 0, "cache_read_input_tokens": ... }, "permission_denials": [...], "modelUsage": { ... } }

실무에서 바로 쓰게 되는 필드는 네 개입니다. result(답 본문), is_error(성공 여부 분기), session_id(이어서 질문할 때), total_cost_usd(호출별 비용 기록). 특히 마지막 값은 대시보드를 열지 않고도 스크립트가 스스로 지출을 남길 수 있게 해줍니다. 다만 공식 문서는 이 수치가 클라이언트 측 추정치이며 실제 청구와 다를 수 있다고 명시합니다. 사내 정산 근거로 쓰기보다 추세 감시용으로 쓰는 게 맞습니다.

답의 형태까지 고정하고 싶다면 한 걸음 더 갈 수 있습니다. --json-schema에 JSON Schema를 주면 결과가 structured_output 필드에 스키마대로 들어옵니다.

답의 구조를 강제하기

claude -p "auth.py의 주요 함수 이름을 뽑아줘" \ --output-format json \ --json-schema '{"type":"object","properties":{"functions": {"type":"array","items":{"type":"string"}}}, "required":["functions"]}' | jq '.structured_output'

여기서 주의할 점이 하나 있습니다. 스키마에 "format": "email" 같은 키워드를 써도 Claude Code는 이를 주석으로만 취급하고 강제하지 않습니다. 이메일 형식 검증은 받아온 뒤 직접 해야 합니다.

사람이 없는 시간에 돌리려면 권한을 먼저 잠급니다

자동화에서 가장 흔한 실패는 모델이 답을 못 하는 게 아니라 승인 프롬프트 앞에서 멈춰 서는 것입니다. 새벽 3시에 실행된 작업이 “이 명령을 실행할까요?”에서 대기하고 있으면 그 작업은 없는 것과 같습니다.

-p 실행은 모든 요금제에서 수동(Manual) 모드로 시작합니다. 그래서 원하는 모드를 명시적으로 넘겨야 합니다.

설정동작쓰는 상황
--allowedTools "Read,Edit"지정한 도구만 프롬프트 없이 허용범위가 뚜렷한 단일 작업
--permission-mode dontAsk물어봐야 할 건 전부 거부하고 진행잠가둔 CI 실행
--permission-mode acceptEdits파일 쓰기와 mkdir·mv 같은 기본 명령 자동 승인린트 수정 같은 편집 작업
--permission-prompts none승인 요청을 기다리지 않고 거부한 뒤 계속응답할 사람이 아예 없는 예약 작업
Claude Code 공식 문서의 무인 실행 관련 섹션. --permission-prompts none 플래그 설명과 예시 명령이 표시돼 있다
무인 실행 관련 공식 설명 승인을 답할 사람이 없는 예약 작업을 위한 플래그와, 권한 모드별 동작이 예시 명령과 함께 정리돼 있습니다. 촬영 2026.09.17 · 출처 code.claude.com/docs/en/headless

도구 이름만 나열하는 대신 명령 단위로 좁힐 수도 있습니다. 공식 문서의 커밋 예시가 이 문법을 잘 보여줍니다.

git 명령만 골라서 허용

claude -p "스테이징된 변경을 보고 적절한 커밋을 만들어줘" \ --allowedTools "Bash(git diff *),Bash(git log *), Bash(git status *),Bash(git commit *)"

괄호 안 * 앞의 공백 한 칸이 의미를 바꿉니다. Bash(git diff *)는 git diff로 시작하는 명령을 허용하지만, 공백을 뺀 Bash(git diff*)는 git diff-index 같은 다른 명령까지 함께 열어버립니다. 권한 규칙을 손으로 적을 때 가장 놓치기 쉬운 지점입니다.

모드별 세부 규칙과 settings.json에서의 deny·ask·allow 우선순위는 Claude Code 권한 설정 글에 따로 정리해 두었습니다.

예약 실행에서 제일 먼저 터지는 건 모델이 아니라 인증입니다

여기가 직접 부딪혀 본 지점입니다. 로그인 자격이 없는 환경에서 -p를 실행하면 명령은 정상적으로 돌아가고, JSON도 정상적으로 나옵니다. 문제는 그 JSON의 내용입니다.

인증이 없는 환경에서의 실제 응답 (2026.09.17 실행)

{ "is_error": true, "subtype": "success", "terminal_reason": "api_error", "result": "Not logged in · Please run /login", "num_turns": 1, "duration_ms": 92 }

이 응답에서 읽어야 할 것은 세 가지입니다. 첫째, subtype은 여전히 "success"입니다. 이 필드만 보고 성공 여부를 판단하는 스크립트는 실패를 성공으로 기록합니다. 둘째, 실제 판정 기준은 is_error와 terminal_reason입니다. 셋째, /login은 터미널 대화 세션에서만 동작하는 명령이라 -p 모드 안에서는 해결할 방법이 없습니다.

정리하면 무인 실행 환경에서는 로그인 세션에 기대지 말고 --bare와 ANTHROPIC_API_KEY 조합으로 고정하는 편이 안정적입니다. 실행 후에는 텍스트 결과만 보지 말고 상태를 분기해야 합니다.

실패를 조용히 넘기지 않는 최소 형태

out=$(claude --bare -p "$PROMPT" --allowedTools "Read" --output-format json) if [ "$(echo "$out" | jq -r '.is_error')" = "true" ]; then echo "실패: $(echo "$out" | jq -r '.result')" >&2; exit 1 fi echo "$out" | jq -r '.result'

참고로 잘못된 플래그를 넘긴 경우는 이와 다르게 처리됩니다. 실행이 시작되기도 전에 표준 오류로 에러를 내고, 성공 시 종료 코드 0, 실패 시 0이 아닌 코드로 끝납니다. 즉 플래그 오타는 종료 코드로, 실행 중 실패는 stdout의 JSON으로 잡는다고 기억하면 됩니다.

오늘 바로 붙일 수 있는 작업 세 개

거창한 파이프라인보다 하루에 몇 번씩 반복하는 작업부터 옮기는 쪽이 오래 갑니다.

① 커밋 전 오타 린터변경분을 파이프로 넘기면 파일을 읽을 권한조차 필요 없습니다. package.json의 스크립트로 등록해 두고 npm run lint:claude로 부릅니다. 공식 문서가 이 형태를 예시로 제시합니다.

② 실패한 빌드 로그 요약CI가 실패하면 로그 마지막 200줄만 잘라 넘기고, 결과를 알림 메시지로 보냅니다. 이건 판정이 즉시 되는 대표적인 작업입니다.

③ 보안 관점 PR 리뷰--append-system-prompt로 역할만 덧붙이면 기본 동작을 유지한 채 관점을 바꿀 수 있습니다.

③의 스크립트 형태 (review.sh)

gh pr diff "$1" | claude -p \ --append-system-prompt "당신은 보안 엔지니어입니다. 취약점 관점에서 검토하세요." \ --output-format json

세 작업 모두 공통점이 있습니다. 입력이 파이프로 들어가고, 출력이 짧고, 틀렸는지 바로 보입니다. 반대로 “우리 서비스 개선점을 정리해줘” 같은 작업을 크론에 걸면, 매일 아침 검토해야 할 문서가 한 장씩 쌓이기만 합니다.

여러 작업을 순서대로 이어야 한다면 세션을 이어붙일 수 있습니다. 세션 ID를 받아 두고 --resume으로 넘기는 방식입니다.

세션 이어서 쓰기

session_id=$(claude -p "리뷰 시작" --output-format json | jq -r '.session_id') claude -p "이제 DB 쿼리만 집중해서 봐줘" --resume "$session_id"

멈추는 법을 먼저 정해둡니다

무인 실행에서 의외로 중요한 건 시작이 아니라 종료 조건입니다. 알아두면 좋은 동작이 몇 가지 있습니다.

상황Claude Code의 동작
SIGTERM으로 중단종료 코드 143, 진행 중이던 턴은 결과 없이 미완으로 남음
백그라운드 Bash 작업이 남음최종 결과 반환 후 약 5초 뒤 종료
백그라운드 서브에이전트가 남음작업이 끝날 때까지 대기, 연속 대기 10분에서 상한
스트리밍 출력을 느리게 읽음큐가 빠질 때까지 대기, 최대 30초

예약 작업에는 별도의 타임아웃을 씌우는 게 안전합니다. 10분 상한은 서브에이전트가 멈췄을 때의 방어선이지, 작업 전체의 실행 시간 제한이 아니기 때문입니다.

흔한 실수

subtype만 보고 성공 판정인증 실패에서도 subtype은 success로 옵니다. is_error를 봐야 합니다.

내 컴퓨터에서만 되는 스크립트--bare 없이 쓰면 내 ~/.claude 설정과 프로젝트 훅이 함께 로드됩니다. 동료 기계에서는 다르게 동작합니다.

권한 규칙의 공백 누락Bash(git diff*)는 의도보다 넓게 열립니다. * 앞 공백을 확인하세요.

비용 필드를 청구액으로 오해total_cost_usd는 클라이언트 추정치입니다. 실제 청구와 차이가 날 수 있습니다.

판정이 오래 걸리는 업무를 크론에검토가 밀리면 자동화가 아니라 숙제가 됩니다. 판정 5초 규칙으로 걸러내세요.

자주 묻는 질문

구독 요금제로도 스크립트 자동화가 되나요?
-p만 쓰는 경우에는 로그인된 세션의 자격을 그대로 사용합니다. 다만 --bare를 붙이면 OAuth와 키체인을 읽지 않으므로 ANTHROPIC_API_KEY가 필요합니다. 재현성이 중요한 CI라면 API 키 쪽으로 가는 게 관리가 쉽습니다.

스킬이나 커스텀 명령도 -p에서 쓸 수 있나요?
프롬프트 문자열 안에 /스킬이름을 넣으면 실행 전에 확장됩니다. 다만 /login처럼 터미널 화면에서만 동작하는 내장 명령은 쓸 수 없습니다. 스킬과 서브에이전트의 차이는 별도 글에 정리했습니다.

n8n 같은 자동화 도구와 무엇이 다른가요?
역할이 다릅니다. n8n은 여러 서비스를 연결하고 일정·재시도·분기를 관리하는 오케스트레이션 쪽이고, claude -p는 그 흐름 안에서 판단이 필요한 한 단계를 처리하는 도구입니다. 둘을 붙여 쓰는 구성이 가장 흔합니다.

확인한 자료

설치 버전(v2.1.271), --help 출력, --output-format json 응답 필드와 인증 실패 응답은 2026년 9월 17일 로컬에서 직접 실행해 확인했습니다. 권한 모드·--bare·종료 동작·입력 상한 등 실행으로 재현하지 않은 사양은 Anthropic 공식 문서의 헤드리스 모드 문서를 근거로 했습니다.

Claude Code 프로그래밍 실행 공식 문서 ↗ · CLI 레퍼런스 ↗