
Claude Code의 Statusline을 직접 제작하여 비용 및 컨텍스트 잔량을 시각화하는 구현 — stdin JSON 파싱과 렌더링 지연
요약
Claude Code의 statusLine 설정을 활용하여 모델 정보, 컨텍스트 잔량, 비용 등을 터미널 하단에 시각화하는 방법을 설명합니다. stdin으로 전달되는 JSON 데이터를 파싱하여 사용자 정의 상태 표시줄을 구현하는 가이드를 제공합니다.
핵심 포인트
- statusLine 설정을 통해 외부 스크립트로 커스텀 상태 표시줄 구현 가능
- Claude Code가 stdin으로 세션 정보를 JSON 형태로 자동 전달
- 스크립트 실행 지연 및 ANSI 컬러 처리 시 주의 필요
- Python 및 Bash를 이용한 구현 샘플 및 디버깅 방법 제시
Claude Code를 매일 터미널에서 사용하면서, "지금 어떤 모델을 사용 중인가", "컨텍스트 윈도우(Context Window)가 얼마나 남아 있는가", "이 세션에서 비용이 얼마나 청구되었는가"를 화면 구석에서 항상 보고 싶다고 생각한 적은 없으신가요?
Claude Code에는 statusLine이라는 설정 항목이 있어, 임의의 외부 스크립트를 등록하면 터미널 하단에 1줄의 상태 표시줄(Status Bar)을 상시 표시할 수 있습니다. tmux의 상태 표시줄이나 vim의 airline과 같은 것을 Claude Code용으로 직접 만드는 이미지입니다.
이 기사의 대상 독자는 다음과 같습니다.
- Claude Code를 일상적으로 사용하며, 비용 관리나 컨텍스트 잔량을 의식하고 싶은 사람
- 쉘 스크립트(Shell Script)나 Python으로 간단한 파서(Parser)를 작성할 수 있는 사람
~/.claude/settings.json을 편집해 본 적이 있거나(또는 거부감이 없는) 사람
전제 버전
-
Claude Code v2.x 계열 (
statusLine기능을 안정적으로 사용할 수 있는 버전) -
Python 3.13 / bash 5.x (둘 다 구현 가능하며, 본 기사에는 양쪽 샘플을 모두 수록)
-
macOS(iTerm2 / Terminal.app)에서의 검증. Linux에서도 동작 원리는 동일
-
settings.json에statusLine.command로 외부 명령어를 하나 등록하는 것만으로, Claude Code는 해당 명령어를 매 턴(정확히는 렌더링이 필요할 때마다) 실행하며, stdin에 현재 세션 정보를 JSON으로 전달합니다. -
스크립트 측은 stdin을 읽어 JSON을 파싱하고, 표준 출력(Standard Output)에 1줄의 텍스트를 반환하기만 하면 됩니다 (ANSI 컬러 코드도 사용 가능).
-
구현 시 주의할 점(ハマりどころ)은 주로 3가지입니다: ① 스크립트가 무거우면 표시가 멈춤(타임아웃 있음) ② git 정보를 매번 쉘 아웃(Shell out)하여 가져오면 체감될 정도의 지연이 발생 ③ ANSI 이스케이프(Escape) 처리 방식이 터미널에 따라 미묘하게 다름
~/.claude/settings.json (프로젝트 단위라면 .claude/settings.json)에 다음을 추가합니다.
{
"statusLine": {
"type": "command",
...
type: "command"는 "외부 명령어의 표준 출력을 그대로 상태 표시줄로 사용한다"는 의미입니다. padding은 상태 표시줄의 좌우 여백 조정용이며, 0으로 설정하면 터미널 너비 전체를 사용할 수 있습니다.
먼저 파싱하기 전에, 실제로 어떤 JSON이 날아오는지 확인하는 것이 가장 빠릅니다. 디버그용으로 받은 JSON을 그대로 파일에 쓰는 스크립트를 임시로 준비합니다.
#!/bin/bash
cat > /tmp/statusline-debug.json
echo "debug"
이를 command로 지정하고 Claude Code를 몇 턴 실행하면, /tmp/statusline-debug.json에 다음과 같은 구조의 JSON이 쌓입니다 (필드명은 버전에 따라 변경될 가능성이 있으므로 반드시 본인의 환경에서 확인하십시오).
{
"model": { "display_name": "Claude Sonnet 5" },
"workspace": { "current_dir": "/Users/you/project" },
...
포인트는 모델명, cwd, 청구 비용, 컨텍스트 사용량이 단 한 번의 호출로 모두 모아서 전달된다는 점입니다. 개별적으로 API를 호출할 필요는 없습니다.
#!/usr/bin/env python3
import json
import sys
...
컨텍스트 사용률에 따라 상태 색상을 녹색→황색→적색으로 바꾸는 단순한 로직이지만, 이것만으로도 "슬슬 /compact를 해야 할까"를 판단하는 자료가 됩니다. Python 실행 오버헤드가 신경 쓰인다면, 동일한 로직을 jq + awk로 다시 작성하면 체감 지연을 더욱 줄일 수 있습니다.
증상: git log나 git status --porcelain과 같은 무거운 명령어를 매번 호출하면, 리포지토리가 큰 프로젝트에서 키 입력부터 렌더링까지의 지연이 명확하게 증가했습니다.
원인: statusLine 명령어는 렌더링이 필요할 때마다 고빈도로 실행됩니다. 1회당 수십~100ms 정도라 하더라도, 이것이 쌓이면 UI 전체가 버벅거리게 됩니다.
회피책: git 정보는 파일의 mtime (수정 시간) 기반으로 간이 캐싱합니다 (위의 코드 참조). 반드시 무거운 처리를 해야 한다면, 백그라운드에서 정기적으로 파일에 써두고, statusline 스크립트 자체는 "파일을 읽기만" 하도록 만듭니다. subprocess.run(..., timeout=0.3)와 같이 타임아웃 설정도 필수이며, git이 행(hang) 상태에 빠지더라도 statusline 전체가 멈추지 않도록 합니다.
증상: context.used_tokens가 존재하지 않는(0으로 취급되는) 경우가 있어, KeyError는 발생하지 않는데 항상 ctx 0%라고 표시되었습니다.
원인: 세션 시작 직후 등 특정 타이밍에는 context 객체 자체가 생략되어 전달되는 경우가 있습니다. .get() 체이닝으로 예외는 방지할 수 있지만, 값이 누락되었다는 사실을 알아차리기 어렵다는 점이 까다로웠습니다.
회피책: 모든 필드를 dict.get(key, default)로 방어적으로 가져오되, max_tokens가 0 등 명백히 비정상적인 값일 때는 "ctx --"와 같은 플레이스홀더(placeholder)를 출력하여, "가져오기 실패"와 "실제로 0%"를 시각적으로 구분할 수 있도록 했습니다.
증상: iTerm2에서는 색상이 깔끔하게 나오는데, tmux를 통해 접속한 다른 터미널 에뮬레이터에서는 색상 코드(color code)가 그대로 문자로 표시되는 경우가 있었습니다.
원인: tmux 버전이나 TERM 환경 변수에 따라 256색 ANSI 이스케이프(escape) 해석이 제각각이었습니다. tmux를 거치면서 외부 터미널의 색상 대응이 제대로 전파되지 않는 경우도 있었습니다.
회피책: 색상은 8색의 기본 ANSI(\033[31m 등)로 제한하고, 256색 지정(\033[38;5;208m과 같은 형식)은 피합니다. os.environ.get("TERM", "")를 확인하여 screen이나 tmux를 포함하는 경우, 색상 적용을 포기하고 일반 텍스트(plain text)로 폴백(fallback)하는 분기문을 넣으면 안정적이었습니다.
statusline은 "JSON을 받아서 한 줄의 문자열을 반환할 뿐"인 단순한 설계이므로, bash, Python, Node.js 등 원하는 언어로 구현할 수 있습니다. 다만 고빈도로 호출된다는 전제가 있으므로 주의해야 하며, 외부 API를 호출하는 것과 같은 무거운 처리를 직접 넣는 것은 안티 패턴(anti-pattern)입니다. 무거운 처리는 별도 프로세스로 넘기고, statusline 본체는 "캐시된 값을 읽어서 정형화하는 것"에만 집중하는 것이 안정적인 운영의 핵심이었습니다.
- Claude Code의
statusLine은settings.json에 명령어 하나를 등록하는 것만으로, stdin을 통해 들어오는 세션 JSON을 자유롭게 가공하여 상태 표시줄에 표시할 수 있다. 구현은 Python으로도, bash + jq로도 가능하다. 실행 오버헤드가 걱정된다면 jq 버전이 유리하다. - 주의할 점은 "무거운 처리에 의한 지연", "JSON 필드 누락", "ANSI 컬러 호환성"의 3가지이며, 모두 캐싱, 방어적 취득, 컬러 폴백을 통해 회피할 수 있다.
- 컨텍스트 잔량이나 비용을 상시 시각화해 두면,
/compact를 실행할 타이밍을 판단하거나 비용을 파악하기 쉬워져, 사소해 보이지만 일상적인 작업 효율에 큰 도움이 된다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기