이제 Claude Code 세션이 VSCode 탭 제목을 스스로 업데이트합니다 (blocked / verifying / done)
요약
Claude Code 세션의 상태(blocked, verifying, done 등)를 VSCode 탭 제목에 자동으로 반영하도록 설정하는 팁을 공유합니다. 환경 변수 설정과 훅(hooks)을 활용하여 여러 세션을 병렬로 실행할 때 작업 상태를 직관적으로 파악할 수 있습니다.
핵심 포인트
- Claude Code의 터미널 제목 업데이트 기능을 제어하는 환경 변수 활용법
- VSCode 설정 변경을 통한 OSC 제목 이스케이프 활성화 방법
- 상태 목록을 정의한 폐쇄형 목록(closed list)을 통한 일관된 탭 제목 관리
- 셸 환경에서 제어 문자를 안전하게 전달하기 위한 훅(hooks) 활용 기술
저는 VSCode에서 3~4개의 Claude Code 세션을 병렬로 실행하는데, 모든 탭을 일일이 클릭해 보지 않고서는 어떤 탭이 실제로 저를 기다리고 있는지 알 수가 없었습니다. 자동 생성된 제목은 시작 시 한 번 설정된 후 업데이트되지 않아서, 제 경우에는 오후 4시에도 여전히 아침 작업 내용이 표시되곤 했습니다. 그래서 Claude가 스스로 제목을 업데이트하도록 만들었습니다. 예를 들어, 작업 중일 때는 'proj-42 - verifying'으로, 제 도움이 필요할 때는 'proj-42 - blocked'와 같이 표시되도록 말이죠.
진행 과정에서 배운 점들은 다음과 같습니다:
- Claude Code는 매 렌더링마다 터미널 제목을 다시 씁니다. 단순히 OSC 제목 이스케이프(OSC title escape)를 작성하면 즉시 원래대로 되돌아갑니다.
CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1이라는 문서화된 환경 변수가 있어 이 기능을 끌 수 있습니다.- VSCode는 "terminal.integrated.tabs.title": "${sequence}"를 설정하지 않으면 제목 이스케이프를 무시합니다.
- 훅(hooks)은 JSON 출력에서
terminalSequence필드를 반환할 수 있으며, Claude Code 자체도 이를 방출합니다. 따라서 Stop 훅은 Claude가 턴 중간에 업데이트를 잊어버리더라도 매 턴이 끝난 후 제목을 다시 확정합니다. - 허용 목록(allowlist)에는 데스크톱 알림인 OSC 9/777도 포함되어 있습니다. 아직 시도해보지는 않았지만 재미있을 것 같네요.
- 재미있는 점 하나는, Claude가 bash 명령에 ESC 바이트를 직접 입력할 수 없다는 것입니다 (harness가 제어 문자를 거부합니다). 그래서 훅이 런타임에
printf '\033'을 사용하여 바이트를 생성하고,--arg를 통해jq로 전달하는 방식을 사용합니다. - 셸(shells)은 TTY를 소유하지 않습니다. 설정을 수행하는 조상 프로세스에 도달할 때까지 프로세스 트리를 거슬러 올라가야 합니다.
-
VSCode 워크스페이스 설정 (변경 후 여는 터미널에만 적용):
JSON: "terminal.integrated.tabs.title": "${sequence}", "terminal.integrated.env.osx": { "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1" } -
~/.claude/tab-states.conf에 정의된 상태 목록:
investigating, fixing, verifying, blocked, waiting-review, done
이 폐쇄형 목록(closed list)이 중요합니다. 모델이 상태를 자유롭게 작성하게 두면 "verifying" / "checking" / "testing" 등이 섞여 나와 탭을 한눈에 훑어보기 어려워집니다. 헬퍼(helper)는 파일에 없는 것은 모두 거부하므로, 경로를 벗어난 에이전트는 신뢰받는 대신 도구에 의해 교정됩니다.
helper는 상태 전환 시 claude가 호출하는 파일입니다. ~/.claude/bin/cc-title: sh !/usr/bin/env sh cc-title "<name> - <state>" - validated against ~/.claude/tab-states.conf conf="$HOME/.claude/tab-states.conf" title="$ " [ -f "$conf" ] || { echo "missing $conf" >&2; exit 2; } allowed=$(grep -v ' [[:space:]] #' "$conf" | tr -s '[:space:]' ' ') case "$title" in ' - ' ) state="${title##* - }" ;; *) echo "need '<name> - <state>'; allowed:$allowed" >&2; exit 2 ;; esac ok=0; for s in $allowed; do [ "$state" = "$s" ] && ok=1 && break; done [ "$ok" -eq 1 ] || { echo "'$state' not allowed:$allowed" >&2; exit 2; } find the first ancestor that owns a tty (claudes tool shells dont) pid=$$ while [ "$pid" -gt 1 ] 2>/dev/null; do t=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ') case "$t" in ''|'??'|'-') pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ') ;; *) printf '%s' "$title" > "$HOME/.claude/tab-state/$(printf '%s' "$t" | tr '/' '_')" printf '\033]0;%s extbackslash007' "$title" > "/dev/$t" 2>/dev/null && exit 0 || exit 1 ;; esac done exit 1 4. ~/.claude/settings.json에 있는 Stop hook으로, 동일한 방식으로 tty까지 올라가서 ~/.claude/tab-state/<tty>를 읽고 이를 terminalSequence json으로 방출하여 claude가 턴을 마칠 때마다 제목이 올바른 상태로 돌아오게 합니다. 5. CLAUDE.md에 한 줄 추가 / 메모: 세션 시작 시와 실제 상태 변경 시 cc-title "<name> - <state>"를 호출합니다. claude -n "proj-42"로 실행하고, claude가 라이브 상태를 붙입니다. btw /rename은 이미 터미널 제목을 실시간으로 업데이트하므로, 수동 버전만 원한다면 (설정은 terminalTitleFromRename) 이것이 좋습니다. 네이티브하게 원한다면 기능 요청(feature request)이 있습니다: https://github.com/anthropics/claude-code/issues/78128 한 달 전의 거의 동일한 요청(#67858)은 자동 레이블링되어 중복 및 비활성으로 처리되었고, 인간의 응답 없이 0으로 끝났으므로, 업보트(upvotes)가 유일하게 계산되는 신호인 것 같습니다 :D /u/FortuneWeird1121에 의해 제출됨 [링크] [댓글]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/ClaudeAI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기