Claude Code의 잘못 설계된 자동 진행 기능 해부
요약
Claude Code 버전 2.1.198은 사용자 응답 부재 시 모델이 자동으로 작업을 계속하는 '자동 진행 기능'을 기본 활성화했으나, 출시 당시 문서화되지 않은 문제가 있었습니다. 이 기능은 권한 게이트를 우회하거나 부분 답변만으로도 작업이 진행될 수 있게 하여 안전 가정을 약화시켰습니다.
핵심 포인트
- 기본 자동 진행 기능(2.1.198)이 사용자 개입 없이 작업을 지속함.
- 권한 프롬프트가 나타나지 않는 환경에서는 보호 장치가 무력화됨.
- 자동 업데이트 및 불완전한 변경 기록은 안전 가정을 위협할 수 있음.
- 후속 버전(2.1.200)에서 옵트인 방식으로 전환하여 위험을 줄임.
- Claude Code
2.1.198
은 AskUserQuestion
에 60초간 답이 없으면 모델이 자체 판단으로 작업을 계속하는 자동 진행 기능을 기본 활성화했지만, 출시 당시 변경 로그와 문서에는 기록하지 않았음
- 권한 요청을 자동 승인하지는 않았으나, 이미 허용된 도구나
--dangerously-skip-permissions
환경에서는 “staging 또는 production” 같은 의사결정 게이트를 대신 통과할 수 있었고 일부 답변만 입력해도 나머지는 모델이 선택했음
- 문제 제기 약 이틀 뒤 나온
2.1.200
은 기능을 삭제하지 않고 기본값만 껐으며, /config
에서 60s
, 5m
, 10m
, never
중 하나를 고르는 옵트인 방식으로 전환함
- 공개 저장소에는 실제 제품 소스나 도입·되돌림 커밋이 없지만, npm의 Bun 실행 파일에 포함된 JavaScript 번들을 비교해
2.1.198
에서 AFK 문자열·스키마·분석 이벤트가 함께 추가됐음을 확인할 수 있음
- 기본 자동 업데이트와 불완전한 변경 기록이 결합하면 사용자 개입 없이 안전 가정이 달라질 수 있음. CLI를 고정하면서 플러그인은 갱신하려면
DISABLE_AUTOUPDATER=1
과 FORCE_AUTOUPDATE_PLUGINS=1
을 함께 설정해야 함
60초 뒤 사람 대신 결정한 2.1.198
- 2026년 7월 1일 출시된 Claude Code
2.1.198
은 AskUserQuestion
이 사람의 답을 기다린 지 60초가 지나면 차단을 해제하고, 모델에 문맥을 바탕으로 최선의 판단을 내려 계속하라고 지시했음
- 출력에는
No response after 60s — continued without an answer
가 표시됨
-
다시 질문할 수 있다는 안내도 있었지만 재질문에도 같은 타임아웃이 적용됨
-
사용자가 일부 질문에만 답한 상태에서 자리를 비우면 입력을 폐기하지 않고
부분 답변을 제출했음 -
세 질문 중 첫 번째에만 답하면 해당 답과 모델이 고른 나머지 답으로 작업을 계속함
-
화면 메시지는 답변 여부에 따라
continued with the answers selected so far
또는 continued without an answer
를 선택함
- 화면에 카운트다운이 전혀 없었던 것은 아님
- 키를 누르면 타이머가 다시 시작됐고
auto-continue in 12s · any key to stay
같은 문구가 나타남
- 다만
CLAUDE_AFK_COUNTDOWN_MS
기본값이 20초여서 처음 40초 동안은 일반적인 차단 질문처럼 보였고, 경고는 마지막 20초에만 표시됨
- 여러 에이전트를 각기 다른 탭에서 실행하거나 자리를 비운 사용자는 경고를 보지 못할 수 있음
적용 범위와 안전 게이트의 한계
- 타임아웃은
AskUserQuestion
에만 적용됐으며, 계획 승인이나 Do you want to allow …
같은 권한 프롬프트에는 연결되지 않았음
-
실행 파일에서 카운트다운 구성 요소와 타이머 훅은 질문 대화상자에만 연결됨
-
도구 레퍼런스도 권한 프롬프트가 유휴 상태에서 자동 해결되지 않는다고 명시함
-
권한 프롬프트가 애초에 나타나지 않는 실행 방식에서는 이러한 분리가 보호 장치가 되지 못함
bypassPermissions
, acceptEdits
, allowedTools
, --dangerously-skip-permissions
, PreToolUse
훅을 이용할 수 있었음
- 배포 명령이 허용 목록에 있거나 권한 확인을 우회했다면
AskUserQuestion
의 “staging 또는 production?”, “어떤 config인가?” 같은 선택이 남은 유일한 게이트일 수 있음
- 타이머가 권한을 부여하지는 않았지만, 이미 권한이 있는 작업의
선택 자체를 모델에 맡길 수 있었음 - 도구 스키마에는
timeout
입력이 없고 모델이 이를 설정하거나 제어할 수도 없었음
- 입력 매개변수는
questions
, answers
, annotations
, metadata
뿐임
- 답을 건너뛴 주체는 모델이 아니라 응답을 자동 반환한 에이전트 하네스였음
출시와 되돌림 연표
- 확인된 공개 기록은 다음 순서로 이어짐
2026-06-29:2.1.196
출시, 신고자가 추정한 마지막 정상 버전
2026-06-30: 2.1.197
출시, 변경 로그에는 Sonnet 5 출시 한 줄만 존재
2026-07-01: 자동 진행이 들어간 2.1.198
출시
2026-07-02 02:54 UTC: Aleksey Nogin이 이슈 #73125를 등록
2026-07-02 03:45 UTC: 댓글에서 비공개 탈출구였던 CLAUDE_AFK_TIMEOUT_MS
를 공유
2026-07-02: 이슈가 열린 상태에서 24개 항목을 담은 2.1.199
출시, 자동 진행은 여전히 미기재
2026-07-03: 2.1.200
에서 기본 동작을 되돌림
2026-07-04 18:04 UTC: 이슈 종료
- 이슈에는
384개 👍와 143개 댓글이 달렸으며, 신고 환경은2.1.198
, Opus, AWS Bedrock, VS Code 터미널이었음
- 문제 신고부터 기본값 전환까지 약
이틀이 걸림
2.1.200
이 수정한 방식
2.1.200
은 기능을 제거하지 않고 자동 진행을 기본 비활성화했으며 /config
를 통한 옵트인으로 바꿈
- 수정 전
2.1.198
에는 /config
설정인 askUserQuestionTimeout
이 없었고, 영향을 피하려면 출시 문서에 나오지 않은 환경 변수를 사용해야 했음
2.1.211
에서도 전체 구현은 유지됨
/config
항목 이름은 Question auto-continue timeout
- 허용값은
60s
, 5m
, 10m
, never
- 설정하지 않으면
never
로 처리돼 기능이 꺼짐
- 내부 기본 타임아웃은 여전히 60,000ms, 카운트다운 기준은 20,000ms
CLAUDE_AFK_TIMEOUT_MS
와 CLAUDE_AFK_COUNTDOWN_MS
가 설정값을 덮어쓸 수 있음
- 수정은 타이머를 삭제한 것이 아니라, 설정값 또는 환경 변수가 있을 때만 활성화하도록
게이트 조건 하나를 추가한 것임 - 영향을 받는 버전에 고정된 사용자는
settings.json
에서 CLAUDE_AFK_TIMEOUT_MS
에 매우 큰 값을 넣어 임시로 우회할 수 있었음
변경 로그에서 빠진 기능 도입
- 릴리스 노트는 공식 변경 로그와 저장소의
CHANGELOG.md
에 같은 내용으로 게시됨
- 당시 기록을 고정 커밋 기준으로 보면 자동 진행의 추가는 어느 버전에도 나타나지 않음
AskUserQuestion
은 2.0.55
이후 13개 버전에서 총 15회 등장할 만큼 평소 변경 로그에 기록되던 도구였음
- 하지만 변경이 들어간 구간인
2.1.181
부터 2.1.200
전까지는 한 번도 나타나지 않음
-
켜짐과 꺼짐이라는 두 번의 동작 변경 가운데 꺼짐만 기록됨
-
자동 진행을 처음 기록한 유일한 항목은
2.1.200
의 “기본적으로 더 이상 자동 진행하지 않으며 /config
로 옵트인”한다는 문구였음
CLAUDE_AFK_TIMEOUT_MS
는 변경 로그와 README 어디에도 없었음
동작을 되돌린 뒤 추가된 문서
- 현재 환경 변수 레퍼런스는 두 AFK 환경 변수를 기록하고,
2.1.198
과 2.1.199
에서 60초 자동 진행이 기본 활성화됐다고 명시함
- 이 문서는 출시 당일 상태를 담은 문서일 수 없음
- 현재 문구가 안내하는
askUserQuestionTimeout
은 2.1.198
실행 파일에 존재하지 않음
- Wayback Machine의 6월 23일 및 7월 1일 12:11·21:35 UTC 캡처에는
CLAUDE_AFK
와 AskUserQuestion
이 각각 0회였음
- 대조 항목인
DISABLE_AUTOUPDATER
는 모든 캡처에서 2회 확인돼 페이지 수집 실패로 인한 누락이 아니었음
2.1.198
은 7월 1일 16:50:16 UTC에 npm에 게시됐지만, 4시간 45분 뒤의 문서에도 AFK, 자동 진행, 질문 도구, 카운트다운이 없었음
- 관련 문구는 7월 1일 21:35부터 7월 5일 13:58 사이에 추가됐고, 이 구간에는
2.1.200
의 되돌림도 포함됨
- 새 문서는 이미 “기본 비활성화”된 수정 후 상태만 기록해, 7월 1~2일의 실제 기본 동작이 문서화된 시점은 없었음
공개 저장소에 없는 제품 소스와 커밋
- 기능을 도입한 공개 커밋과 되돌린 공개 커밋은 모두 없음
- 공개 Git 기록에는 변경 로그와
feed.xml
만 갱신한 자동 커밋 두 개가 남음
anthropics/claude-code
저장소에는 216개 추적 파일이 있고 그중 104개가 Markdown이며, 실제 배포 제품 소스는 없음
- 실행 가능한 파일은 예제나 이슈 추적 자동화 스크립트임
plugins/
와 examples/
도 샘플 플러그인, GCP 게이트웨이 Terraform 설정, MDM 프로필 등을 담음
2.1.197
과 2.1.198
태그의 차이는 CHANGELOG.md
와 이를 RSS로 반복한 feed.xml
뿐임
2.1.196
부터 2.1.206
까지 열 번의 연속 릴리스도 같은 두 파일만 바뀜
-
태그는 소스 릴리스가 아니라 사실상
릴리스 노트 태그임 -
변경 로그나 저장소·태그 비교로는 실제 배포 동작을 확인할 수 없으며, 작성된 소스는 공개되지 않은 채 컴파일된 실행 파일로만 배포됨
의도적으로 설계하고 계측한 흔적
- 공식 설계 문서, PR, 변경 로그 문구 등 도입 이유를 확인할 자료는 없음
- 이름과 메시지는 자리를 비운 사람 때문에 병렬 에이전트가 무기한 차단되는 상황을 겨냥했음을 보여주는
정황 증거임 - 내부 이름
AFK
는 away from keyboard를 뜻함
- 메시지는 “사용자가 키보드에서 떨어져 있을 수 있다”고 가정함
- 이슈 참가자들은 수십 개 에이전트가 며칠 동안 사람의 답을 기다리는 작업 흐름을 사용한다고 밝혔음
2.1.198
에는 자동 해결 여부를 나타내는 afkTimeoutMs
필드가 도구 결과 스키마에 추가됨
-
사람이 답한 경로에는 없고 자동 해결 시 유휴 시간을 기록함
-
모델에 자동 해결된 응답임을 알리고 터미널 출력 구성 요소를 선택하는 데 쓰임
-
같은 버전에
tengu_ask_user_question_afk_auto_advance
분석 이벤트도 추가됨
timeoutMs
, 질문 수, 계획 모드 여부, 부분 답변 여부를 전송함
- 질문 원문은 보내지 않고
source_hash
와 카운터를 사용함
hadPartialAnswers
가 별도 계측된 만큼 부분 답변 경로도 독립된 코드와 측정을 갖고 있었음
- 동작, 카운트다운 UI, 스키마 필드, 분석 이벤트가 한 버전에 함께 들어갔으므로 우발적인 한 줄이 아니라 측정 체계를 갖춘 기능이었음
- 이 증거만으로 누가 작성·검토·승인·병합했는지, 사람이 어느 단계에 개입했는지는 알 수 없음
닫힌 소스지만 읽을 수 있는 Bun 실행 파일
- 설치된 Claude Code는 약
250MB의 심볼이 제거되지 않은 네이티브 실행 파일임 - Bun 단일 실행 파일 형식은 런타임 뒤에 모듈 그래프를 붙이며, Claude Code 실행 파일에서도
---- Bun! ----
표식을 찾을 수 있음
- Bun이 JavaScript 번들을 실행 파일 안에 포함하므로
strings
로 설정 이름, 메시지, 분석 이벤트 등을 읽을 수 있음
- 로컬 설치 디렉터리는 최근 버전 일부만 보관하지만, npm에는 각 버전의 플랫폼별 실행 파일이 남아 있음
@anthropic-ai/claude-code
는 약 152KB의 설치용 스텁임
- 실제 Linux x64용
2.1.198
패키지는 약 249MB임
- 공개 소스는 없지만 각 릴리스 아티팩트를 내려받아 배포된 동작을 확인할 수 있으므로 완전한 블랙박스는 아님
2.1.197
과 2.1.198
실행 파일 비교
- 두 실행 파일에서 AFK 관련 문자열을 검색하면 경계가 명확함
2.1.197
: away from keyboard
, CLAUDE_AFK_TIMEOUT_MS
, CLAUDE_AFK_COUNTDOWN_MS
가 모두 0회
2.1.198
: 각각 2회, 3회, 3회 등장
- 수정 후
2.1.211
의 타이머 게이트에는 /config
값이나 환경 변수가 존재해야 한다는 조건이 추가됨
2.1.198
에도 외부 경쟁 실행 여부 등을 검사하는 게이트는 있었음
- 다만 사용자가 끌 수 있는 조건이 없었고, 수정은 여기에
&&
조건 하나를 더한 형태였음
- 기능명과 문제가 발생한 버전을 모른 채 일반적인 릴리스를 비교하기는 훨씬 어려움
strings -n 8
기준 단순 비교에서는 21,903개 문자열이 달라짐
-
최소 문자열 길이에 따라 81,289개 또는 29,910개로 달라질 수 있어 21,903은 고정된 릴리스 특성이 아님
-
빌드마다 미니파이어가 식별자 이름을 바꿔 대부분이 실제 기능 변경이 아닌 잡음임
-
추가된 문자열 중 대문자로 시작하고 일반 문장 형태이며 5단어 이상인 영어 문장만 걸러내면
156줄로 줄어듦 -
그 안에
Before going idle the user had selected:
가 포함됨
- 대화상자가 사람 대신 답할 때 대화에 삽입하는 문자열이므로, 사전 정보 없이 읽어도 검토를 멈출 만한 변화였음
curl
, strings
, diff
로 약 5분 안에 발견할 수 있었지만, 사용자가 모든 자동 업데이트 릴리스마다 실행 파일을 검사하는 방식은 변경 로그를 대신할 수 없음
비용보다 큰 안전 문제
- 잘못된 경로를 자동 선택하면 불필요한 토큰을 소비할 수 있음
- 더 큰 문제는
AskUserQuestion
을 차단형 안전 게이트로 전제한 훅과 규칙이 60초 카운트다운으로 바뀐다는 점임
- 배포, 인프라, 프로덕션 인접 스크립트처럼 위험한 환경에서도 Claude Code가 사용됨
- Claude Code가 기본 자동 업데이트되므로, 조용한 동작 변경과 결합하면 사용자가 아무 조치도 하지 않아도 기존 안전 가정이 달라질 수 있음
- 최신 버전을 즉시 받는 정책 자체가 위험한 선택일 수 있다는 논의는 On Cooldowns and Dependabot Tuning과 이어짐
자동 업데이트를 끄는 방법과 우선순위
- 업데이트 비활성화 여부는 다음 환경 변수를 순서대로 검사하며 첫 번째 일치값이 적용됨
DISABLE_UPDATES=1
: 수동 claude update
까지 포함해 모든 업데이트 경로를 차단
DISABLE_AUTOUPDATER=1
: 백그라운드 확인만 중단하고 수동 업데이트는 허용하며 autoUpdates
설정보다 우선
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
: 자동 업데이트, 피드백 명령, 오류 보고, 원격 측정을 함께 중단
- 셸 프로필보다
~/.claude/settings.json
의 env
블록에 넣으면 CI, cron, systemd, IDE 터미널을 포함한 모든 세션에 적용할 수 있음
{
"env": {
"DISABLE_AUTOUPDATER": "1"
}
}
- 설정 범위는 셸 프로필, 사용자별
~/.claude/settings.json
, 저장소별 .claude/settings.json
, 중앙 관리용 managed-settings.json
순으로 강해짐
managed-settings.json
경로는 다음과 같음
-
macOS:
/Library/Application Support/ClaudeCode/managed-settings.json -
Linux/WSL:
/etc/claude-code/managed-settings.json -
Windows:
C:\Program Files\ClaudeCode\managed-settings.json -
기존
C:\ProgramData\ClaudeCode
경로는 더 이상 읽지 않음
- 자동 업데이트를 끄는 CLI 플래그는 없으며
/doctor
는 설치 유형과 업데이트 채널을 표시함
CLI 업데이트를 끄면 플러그인도 멈춤
- 환경 변수나
autoUpdates: false
등 어떤 방식으로든 자동 업데이터를 끄면 플러그인 자동 업데이트도 중단됨
- 플러그인 탐색 문서는
DISABLE_AUTOUPDATER
와 함께 FORCE_AUTOUPDATE_PLUGINS=1
을 설정하면 CLI는 고정하고 플러그인은 계속 갱신할 수 있다고 안내함
- 반면 실제 자동 업데이트 비활성화를 안내하는
/setup
문서와 설정 환경 변수 표에는 플러그인 영향과 FORCE_AUTOUPDATE_PLUGINS
가 없음
- 실행 파일상 플러그인 업데이트를 멈추는 경로는 네 가지임
DISABLE_UPDATES
DISABLE_AUTOUPDATER
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
autoUpdates: false
- 실행 중에는 플러그인이 멈췄다는 경고 대신 디버그 로그
Plugin autoupdate: skipped (auto-updater disabled)
만 남음
- CLI를 고정하고 플러그인을 유지하는 설정은 다음과 같음
{
"env": {
"DISABLE_AUTOUPDATER": "1",
"FORCE_AUTOUPDATE_PLUGINS": "1"
}
}
FORCE_AUTOUPDATE_PLUGINS
, DISABLE_AUTOUPDATER
, DISABLE_UPDATES
는 1
, true
, yes
, on
을 대소문자 구분 없이 참으로 해석하고 0
은 거짓으로 처리함
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
는 값이 아니라 존재 여부만 검사해 =0
도 활성화하며, 이 경우 자동 업데이터와 플러그인 업데이트가 모두 멈춤
업데이트 설정의 추가 함정
- 개인정보 보호나 외부 통신 제한 목적으로
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
를 사용해도 CLI와 플러그인이 함께 고정됨
- 문서에 없는
autoUpdates: false
는 네이티브 설치에서 autoUpdatesProtectedForNative
가 활성화되면 무시될 수 있음
- 환경 변수는 이 설정보다 먼저 검사되고 조건 없이 적용됨
2.1.98
은 npm 설치에서 DISABLE_AUTOUPDATER
가 레지스트리 버전 확인과 심볼릭 링크 수정을 완전히 막지 못하던 문제를 수정함
- 자동 업데이터가
~/.local/bin/claude
의 사용자 지정 실행기나 심볼릭 링크를 릴리스마다 덮어쓰던 문제도 수정됐으며, 현재 /doctor
는 외부 관리 실행기를 표시함
- 네이티브 및 npm 설치는 기본적으로 자체 업데이트함
- Homebrew, WinGet, apt, dnf, apk는 기본 자체 업데이트 대상이 아님
- Homebrew와 WinGet은
CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1
로 옵트인할 수 있음
배포 과정에 남은 신뢰 문제
- 사람이 여러 에이전트를 동시에 감독하면 60초 안에 모든 질문을 확인하기 어렵고, 잘못된 선택 뒤 얼마나 많은 토큰이나 작업이 소비될지도 사전에 알 수 없음
- Anthropic이 기능의 작성, 검토, 승인, 병합, 문서화, 릴리스 비교 단계에서 어떤 사람과 절차를 거쳤는지는 공개 기록으로 확인할 수 없음
- 기능은 약 이틀 만에 적절한 옵트인 형태로 수정됐지만, 일일 출시 주기와 기본 자동 업데이트를 통해 예상 밖의 기능이 변경 로그 없이 배포될 수 있음이 드러남
- 실행 파일 분석은 실제 배포 내용을 검증하는 유효한 우회 수단이지만,
정확하고 잘 편집된 변경 로그를 대체하지 못함 - 악의를 전제할 근거는 없으며, 같은 종류의 일이 반복되는지가 이 배포 과정에서 무엇이 개선됐는지를 판단할 근거가 됨
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기