Official Docs Analysis — 9 Reference Pages

공식 레퍼런스 9개 페이지를 읽었더니
Claude Code 실행 모드는 셋이었다

문제는 이것이었다. 내가 Claude Code(터미널에서 쓰는 Anthropic의 AI 코딩 에이전트) 위에 손수 지어 온 장치들이 있다. nohup·tmux로 띄우는 백그라운드 루프, 훅(hook — 정해진 순간마다 자동으로 실행되는 작은 스크립트)의 무한 재귀를 막는 자체 마커, 두 시간 뒤 바깥에서 세션을 죽이는 타이머 같은 것들이다. 그런 것들에 공식 대체가 있는지 모른 채 써 왔다. 그래서 code.claude.com 공식 레퍼런스(공식 참조 문서) 전 페이지, 곧 CLI · Commands · Env vars · Tools · Interactive mode · Checkpointing · Hooks · Plugins · Channels 아홉 쪽을 처음부터 끝까지 읽었다. 그리고 "어느 실행 모드에서 무엇이 되는가"라는 한 축으로 다시 정리했다. 결과는 첫 발견부터 정정이었다. Claude Code의 실행 모드는 흔히 2개로 알려져 있지만 실제로는 3개다.

모드는 2개가 아니라 3개다

결론부터 말하면 실행 모드는 셋이다. CLI reference(명령줄 옵션을 전부 적어 둔 공식 문서. 명령줄 인터페이스, 곧 터미널에 명령을 쳐서 쓰는 방식을 다룬다)를 정독하면 claude(대화형 — 사람이 터미널에서 대화하듯 쓰는 모드)와 claude -p(헤드리스 — 화면 없이 프롬프트, 즉 지시문 하나를 주고 결과만 받는 모드) 사이에 네이티브 백그라운드 세션 계층이 따로 있다. 이 계층은 --bg(세션을 뒤에서 띄우는 옵션) · claude agents(뒤에서 도는 세션들을 한눈에 보는 관제 명령) · attach/logs/respawn(붙기·로그 보기·다시 띄우기)으로 이루어진다. 하네스(harness — AI가 "다 했다"고 거짓말 못 하게 증거를 강제하는 감시 장치. 여기서는 내가 Claude Code 위에 얹어 둔 훅·스크립트 묶음)들이 nohup·tmux·lock으로 손수 짓던 백그라운드 루프의 공식 등가물이 바로 이것이다. 그리고 --bg-p는 함께 쓰는 것이 금지된 별개 모드다.

9레퍼런스 페이지
3실행 모드
30+hook events
43built-in tools
세 실행 모드 — 전용 플래그와 결합 제약 claude 대화형 세션 · Shift+Tab 권한 사이클 · /rewind 체크포인트 · ! 셸 모드 · Ctrl+B 백그라운딩 · 채널(외부 이벤트 인입) · API 키 사용 전 승인 프롬프트 사람이 상시 조향 claude -p 헤드리스 (단발 프롬프트) · --max-turns / --max-budget-usd · --json-schema · stream-json · --no-session-persistence · Setup hook (--init/--maintenance) · bg 태스크는 종료 시 함께 소멸 스크립트가 소비 (SDK) claude --bg 백그라운드 세션 · claude agents 관제 뷰 · attach / logs / stop / respawn · supervisor가 생명주기 관리 · bypass 설정 재시작에도 지속 · nohup/tmux 수제 루프의 공식판 데몬이 관리 --bg ✕ -p 결합 금지 (v2.1.198+) = 서로 다른 모드라는 공식 선언 종료된 세션을 -p로 resume → exit 1 (스크립트가 죽은 런을 성공으로 오독하지 못하게 하는 계약)
세 모드는 전용 플래그(flag — 명령 뒤에 붙이는 옵션) 집합이 다르다. --bg-p는 함께 쓰는 것이 명시적으로 금지된다. 공식 CLI reference에서 실측한 내용이다.
플래그와 슬래시 명령의 모드 경계

슬래시 명령(/로 시작하는 짧은 명령)은 모드마다 쓸 수 있는 범위가 다르다. 커스텀 명령(사용자가 직접 만든 슬래시 명령)은 이제 스킬로 통합됐다. 스킬(skill — 특정 작업의 절차를 적어 둔 지시 묶음)은 한 메시지에 최대 6개까지 이어 붙일 수 있다(체이닝). 슬래시 명령의 헤드리스 지원은 v2.1.205+(버전 2.1.205 이후)에서 "인자 직접 지정 + 픽커 없음" 형태만 열렸다. 픽커(picker)란 선택지를 화면에 띄워 사람이 고르게 하는 대화형 창이다.

대화형에서만 헤드리스(-p)에서도
슬래시 명령 픽커(선택창)·다이얼로그(대화창)형 전부: /rewind /resume /diff /plan /permissions /config key=value · /model <인자> · /effort · /mcp(텍스트 요약) · /color · /fast
권한 처리 프롬프트 UI + Shift+Tab 모드 사이클 --permission-prompt-tool(승인 질문을 MCP 서버에 넘겨 대신 답하게 하는 옵션. MCP는 Model Context Protocol, 외부 도구를 AI에 꽂는 표준 규약이다. 30s 대기) 또는 bypass(모든 승인을 건너뛰는 설정). 블랭킷 우회, 즉 bypass 하나로 전부 통과시키는 것이 유일한 길이 아니다
상한 없음 (사람이 중단) --max-turns(대화 턴 수 상한) · --max-budget-usd(달러 예산 상한). 프로세스 내부 상한을 공식 지원한다
세션 영속 항상 저장 + 체크포인트 동반 --no-session-persistence(세션 기록을 남기지 않는 옵션)로 무흔적 실행을 선택할 수 있다
구조화 출력 --json-schema(답을 정해진 자료 틀에 맞춤) · --output-format stream-json(결과를 한 줄씩 기계가 읽는 형식으로 흘려보냄) · --include-hook-events(훅 실행 기록까지 출력에 포함)
공식 권장이 답이었던 것

결론은 공식 권장 옵션이 이미 답이었다는 것이다. --exclude-dynamic-system-prompt-sections(시스템 프롬프트 가운데 세션마다 달라지는 동적 부분을 빼고 띄우는 옵션)는 문서에 "-p 스크립트·멀티유저 워크로드에 권장"으로 명시돼 있다. 이 세션에서 실측한 스폰 실패란 이런 것이다. 스폰(spawn — 세션이 다른 세션을 새로 띄우는 것)한 하위 세션이 시작하자마자 "Prompt is too long"(프롬프트가 너무 길다)이라며 죽었다. 원인은 부모 세션의 대형 동적 주입, 곧 자동으로 끼워 넣는 규칙과 컨텍스트(context — AI가 한 번에 읽고 있는 대화·문서 전체) 덩어리를 자식이 그대로 상속한 것이다. 그 공식 완화 수단이 이미 존재했다는 뜻이다.

프로세스 신원, 우선순위, 도구 수명

환경 변수 두 개가 "내가 지금 어디서 도는가"를 알려준다. 하나는 Claude Code 아래에서 돌고 있다는 표시고, 다른 하나는 Claude Code가 나를 직접 띄웠다는 표시다. 둘은 뜻이 다르다. 중첩 세션(세션 안에서 띄운 세션)을 가려내는 데는 두 번째만 정확하다. 이어지는 표는 대화형과 헤드리스에서 API 키·백그라운드 태스크·환경 변수 우선순위·도구 권한이 어떻게 다른지 정리한 것이다.

CLAUDECODE=1

"Claude Code 아래에 있다"

"모든 하위 프로세스에 설정 — IDE 터미널 포함"

  • Bash(셸 명령) · 훅 · statusline(화면 아래 상태줄) · stdio MCP(표준 입출력으로 붙는 MCP 서버) 전부에 주입된다
  • IDE(코드 편집기) 통합 터미널에도 설정된다. 그래서 중첩 판별에는 부정확하다
  • 용도: "지금 Claude Code 환경인가" 감지
CLAUDE_CODE_CHILD_SESSION=1

"Claude Code가 나를 스폰했다"

"중첩 세션의 공식 판별자"

  • Claude Code 자신이 띄운 세션에만 설정된다 (IDE·MCP 서버는 제외)
  • 훅 재귀 가드의 공식 마커다. 재귀 가드란 훅이 세션을 띄우고 그 세션이 다시 훅을 부르는 무한 반복(fork bomb)을 막는 장치다
  • 손수 만든 env(환경 변수) 마커나 lock 파일 대신 이 변수 하나를 검사하면 된다
사실 대화형 헤드리스(-p)
API 키 사용 ANTHROPIC_API_KEY(API 키를 담는 환경 변수)를 쓰기 전 1회 승인 프롬프트가 뜬다 무언 사용, 즉 묻지 않고 쓴다. 구독 결제를 조용히 덮어쓴다
백그라운드 태스크 턴(한 번의 질문과 답)을 넘어 지속된다 (Ctrl+B·/tasks) 최종 결과 직후 종료된다. 데몬(뒤에서 계속 도는 프로세스)을 남길 수 없는 구조다
MCP 자동 백그라운딩 미적용 CLAUDE_AUTO_BACKGROUND_TASKS(오래 걸리는 MCP 호출을 자동으로 뒤로 보내는 환경 변수)는 비대화형 전용이다 (v2.1.212+)
env 우선순위 settings(설정 파일)의 env 블록이 셸 env(환경 변수)를 덮어쓴다. scope(설정이 적용되는 범위) 사이 우선순위는 managed > local > project > user 순이다. 그래서 워커(worker — 사람이 지켜보지 않는 채 뒤에서 일하는 헤드리스 세션)가 launchd(맥에서 백그라운드 작업을 띄우는 시스템 실행기)의 최소 env로 떠도 settings의 env는 똑같이 적용된다
도구 권한 (43종) 내장 도구 43종 가운데 승인 프롬프트를 요구하는 것은 13종(Bash·Edit·Write·WebFetch·Skill·Workflow 등)이다. bypass가 없애는 것은 이 승인 프롬프트 계층뿐이다. 훅의 exit-2 게이트(gate — 훅이 종료 코드 2를 돌려주면 그 작업을 막는 관문)는 세 모드에서 똑같이 작동한다
되돌리기의 두 구현

되돌리기는 모드마다 구현이 다르다. 대화형은 세션 안의 체크포인트로 되돌리고, 헤드리스 워커는 세션 밖의 git으로 되돌린다. Interactive mode(대화형 모드) 페이지 전체가 사실상 "사람이 조향하는 표면"의 목록이다. Shift+Tab(권한 모드 전환), Ctrl+B 백그라운딩(작업을 뒤로 보내기), ! 셸 모드(터미널 명령 직접 실행), Esc Esc 되감기, /btw(본 작업을 멈추지 않고 곁가지 질문 하기), vim 모드(vim 편집기식 키 조작)가 그것이다. 전부 헤드리스 등가물이 없다. 그리고 Checkpointing(체크포인트 — 프롬프트마다 파일 상태를 자동 저장해 두는 기능) 페이지의 한계 목록이 두 모드의 "되돌리기" 구현 차이를 정확히 보여준다.

되돌리기(undo)의 두 구현 — 세션 내부 vs 구조 외부 대화형 — 체크포인트 (세션 내부) 사용자 프롬프트마다 자동 체크포인트 최근 100개 유지 · 세션과 함께 30일 보존 /rewind = 코드·대화 개별 복원 + 구간 요약 추적하지 못하는 것 (공식 한계 4) · bash가 바꾼 파일 (rm·mv·cp) · 서브에이전트의 편집 (복원 불가) · 동시 세션·외부 수정 · 심링크·하드링크 경로 (스킵 경고) 헤드리스 워커 — git worktree (구조 외부) 단발 프롬프트 = 체크포인트 사실상 1개 /rewind 할 사람도, 픽커 UI도 없음 되돌리기 = git reset · worktree 폐기 git이 전부 커버 · bash 변경 포함 워킹트리 전체 추적 · 서브에이전트 편집도 diff에 잡힘 · 워크트리 격리 → 동시 세션 간섭 없음 · 폐기(discard) = 브랜치 삭제 한 번 공식 문서도 명시: "체크포인트는 로컬 undo, Git은 영구 히스토리 — 대체가 아니라 보완"
체크포인트가 못 잡는 네 가지(bash·서브에이전트·동시 세션·링크)는 정확히 워커 구조에서 git(코드 변경 이력을 기록하는 버전 관리 도구)이 잡는 것들이다. bash가 바꾼 파일, 서브에이전트(하위 에이전트)의 편집, 동시에 열린 다른 세션의 수정, 심링크 경로가 그 넷이다. git은 워킹트리 전체를 추적하므로 이 넷을 전부 본다.
이벤트 30여 종, 출처 6곳, 병합 규칙 하나

훅 설정은 여섯 곳에서 모여 합쳐진다. 훅은 user(내 계정)·project(저장소)·local(저장소 안 개인 설정)·managed(조직이 관리)·플러그인·스킬/에이전트 frontmatter(파일 머리에 적는 메타데이터) 6개 출처에서 병합된다. 나중 것이 앞 것을 대체하는 방식이 아니다. 동일 핸들러(같은 명령)는 dedup(중복 제거)되고, 매칭된 훅은 병렬 실행된다. disableAllHooks(모든 훅을 끄는 설정)로도 managed 훅은 못 끈다.

이벤트 공간

30+ 종 (등록은 별개)

이벤트(훅이 걸리는 순간)는 세션 생명주기·턴·도구 호출·서브에이전트·압축·MCP·환경 변화·표시까지 30여 종이다. Setup헤드리스 전용 이벤트다(--init-only, 또는 -p+--init/--maintenance로 띄울 때만). 즉 CI(continuous integration — 코드를 올릴 때마다 자동으로 검사·빌드하는 서버) 준비용 이벤트가 따로 있다.

30+
공식 이벤트
16
내 하네스 등록
판정 계약

차단은 exit 2뿐

훅의 판정은 종료 코드(exit code — 프로그램이 끝나며 남기는 숫자)로만 전달된다. exit 1은 차단이 아니다(WorktreeCreate 이벤트만 예외다). 비차단 에러로 기록되고 작업은 계속 진행된다. exit 2일 때만 막히고, 그때 stderr(에러 출력)에 쓴 글만 Claude에게 전달된다. SessionEnd(세션 종료) 훅은 전부 합쳐 1.5초 공유 예산 안에 끝나야 한다.

2
유일한 차단 코드
1.5s
SessionEnd 예산
서브에이전트

훅은 안까지 따라간다

훅은 서브에이전트(subagent — 본 세션이 일을 나눠 맡기려고 띄우는 하위 에이전트) 안에서도 작동한다. settings·managed·플러그인 훅이 그 안에서도 발화하고, 훅 입력에 agent_id/agent_type(어느 에이전트인지 알려주는 필드)이 추가된다. agent frontmatter에 적은 Stop(응답 종료 이벤트)은 SubagentStop으로 자동 변환된다.

6
훅 출처 (병합)
Plugins — 컴포넌트 7종과 신뢰 게이트

플러그인(plugin — 스킬·에이전트·훅을 한 묶음으로 설치하는 확장 패키지)은 skills·agents·hooks·MCP에 더해 LSP(Language Server Protocol — 편집기에 자동완성·정의 이동을 제공하는 규약) 서버·모니터·테마까지 7종의 컴포넌트를 제공한다. 설치 스코프(설정이 적용되는 범위)는 셋이다. user 스코프는 내 계정 전체(~/.claude/settings.json)에, project 스코프는 저장소 하나(.claude/settings.json, 커밋해서 팀과 공유)에, managed 스코프는 조직 관리자가 정한 범위에 적용된다. project 스코프는 신뢰 게이트 뒤에서만 로드되고, 코드를 실행하는 컴포넌트는 추가로 제한된다. "repo(저장소) 유래 구성은 검증 후 로드"가 설계 원칙이다. enabledPlugins(켜 둔 플러그인 목록을 적는 설정 키)는 한 번 기록되면 업데이트를 넘어 지속된다.

세 번째 통신 계층, 그리고 종합

채널(Channels, research preview 단계 — 정식 기능이 되기 전의 시험판)은 세션 안으로 바깥 이벤트를 밀어 넣는 MCP 서버다. 단방향(웹훅/알림을 받기만 함)·양방향(reply tool로 답장까지 함)에 더해 permission relay(권한 중계)로 도구 승인 프롬프트를 폰으로 보내고, yes <id>/no <id>로 원격 승인까지 한다. 발신자 allowlist(허용 목록) 게이팅이 명문 요구사항이다. 바깥에서 들어오는 메시지는 프롬프트 인젝션(injection — 문서나 메시지에 숨긴 지시로 AI를 조종하는 공격)의 통로가 되기 때문이다.

1
외부 시스템 → 로컬 채널 MCP 서버
CI 서버·모니터링·챗봇이 로컬 포트로 POST(데이터를 담아 보내는 웹 요청)를 보내거나, 채널 서버가 플랫폼 API를 폴링(주기적으로 새 메시지가 있는지 물어보기)한다
2
발신자 allowlist 게이트 (필수)
message.from.id(보낸 사람의 고유 번호) 기준으로 거른다. room(대화방) 기준은 금지다. 그룹방에서는 누구나 끼어들 수 있어 우회된다
3
<channel> 태그로 세션 컨텍스트 인입
stdio(표준 입출력) 전송이다. 권한 프롬프트는 로컬 다이얼로그(화면의 승인창)와 병렬로 뜨고, 먼저 온 답이 적용된다
Verdict — 하네스에 바로 적용 가능한 공식 대체 6

손수 구현 중인 여섯 가지에 네이티브(공식 내장) 대체가 문서에 이미 있었다. 첫째, 블랭킷 bypass(승인을 전부 건너뛰는 설정)는 --permission-prompt-tool로 바꿀 수 있다. 둘째, 자체 재귀 가드CLAUDE_CODE_CHILD_SESSION=1 검사로 대신한다. 셋째, 2h 외부 kill(두 시간 뒤 바깥에서 프로세스를 죽이는 타이머)은 --max-turns/--max-budget-usd로 프로세스 안에서 건다. 넷째, 주입 과중(스폰 실패)--exclude-dynamic-system-prompt-sections로 푼다. 다섯째, nohup/tmux 수제 백그라운드--bg+claude agents가 공식판이다. 여섯째, telegram rc 브릿지(텔레그램으로 원격 승인을 중계하던 자체 장치)는 Channels permission relay(preview 단계, allowlist 제약)로 대체된다. 그리고 네 번째 분기가 있다. 대화형과 워커는 "되돌리기·조향"을 각각 세션 내부 장치(체크포인트·Shift+Tab·채널)와 세션 외부 장치(worktree·타임아웃·보드)로 푼다.