KainosPeople Archive
  • 인물
  • 인사이트
  • 프로젝트
  • 발견
  • 소개
인물인사이트프로젝트발견소개
AD
Kainos

시대를 초월한 거장들의 삶과 작품을 기록하고 탐구하는 인물 아카이브.

분야
화가 · Painters음악가 · Musicians과학자 · Scientists철학자 · Philosophers작가 · Writers감독 · Directors
콘텐츠
인사이트전체 인물프로젝트발견
Kainos
소개문의
© 2025 Kainos · People Archive. All rights reserved.
이용약관개인정보처리방침
Vibe Coding

Statusline 커스터마이징 가이드

브랜치, 모델, 컨텍스트, 사용률, 비용을 실시간으로 표시합니다

by Kainos·2026.04.09·8분 읽기

5분
설정 시간
settings.json + bash 스크립트
₩0
추가 비용
Claude Code 기본 기능
8개+
표시 항목
브랜치, 모델, 컨텍스트, 사용률 등

왜 필요한가

Claude Code는 기본적으로 간단한 상태 정보만 표시합니다. 장시간 작업 시 컨텍스트 윈도우가 얼마나 사용되었는지, API 사용률은 얼마인지, 비용은 얼마나 발생했는지 확인하기 어렵습니다.

커스텀 statusline으로 이 모든 정보를 터미널에 실시간으로 표시할 수 있습니다.

완성 모습

statusline 출력 예시
🌿 브랜치 : develop 🤖 모델 : Opus 4.6 / v2.1.97 / default
🧠 Context : 13% [=---------] 1M 📈 사용 : 13% [=---------] (-0h 7m) / 42% [====------] (-1d 0h)
💰 비용 : $7.84 ($2.44/h) 📊 토큰 : 84,833 (440/min) 🕐 세션 : 3h 34m

표시 항목

account_tree
브랜치
현재 Git 브랜치명
smart_toy
모델 / 버전 / 스타일
사용 중인 Claude 모델, Claude Code 버전, 출력 스타일
memory
Context
컨텍스트 윈도우 사용률과 프로그레스 바. 윈도우 크기(200K/1M) 표시
speed
사용률 (5h / 7d)
5시간, 7일 단위 API 사용률과 리셋까지 남은 시간. 100% 도달 시 속도 제한
payments
비용
세션 총 비용과 시간당 비용
data_usage
토큰
총 사용 토큰 수와 분당 처리 속도
timer
세션 경과
현재 세션이 시작된 후 경과 시간

1단계: settings.json 설정

Claude Code의 설정 파일에 statusLine 항목을 추가합니다. 실행할 스크립트 경로를 지정하면 됩니다.

~/.claude/settings.json
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}

statusLine 설정은 Claude Code가 주기적으로 스크립트를 실행하고, 표준 출력(stdout)을 statusline 영역에 렌더링합니다. 스크립트에는 JSON 데이터가 stdin으로 전달됩니다.

2단계: statusline.sh 작성

아래 스크립트는 stdin으로 전달되는 JSON 데이터를 파싱하여 3줄로 정리된 statusline을 출력합니다.

~/.claude/statusline.sh
#!/bin/bash
# Claude Code Status Line — Kainos Compact (3 lines)
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
input=$(cat)
# --- Progress bar [====------] ---
bar() {
local pct=${1:-0} width=10
local filled=$(( pct * width / 100 ))
local empty=$(( width - filled ))
printf "["
for ((i=0; i<filled; i++)); do printf "="; done
for ((i=0; i<empty; i++)); do printf "-"; done
printf "]"
}
# --- Comma formatting ---
fmt_num() { printf "%d" "$1" | rev | sed 's/.\{3\}/&,/g' | sed 's/,$//' | rev; }
# --- Extract data ---
model_name=$(echo "$input" | jq -r '.model.display_name // "Claude"')
model_id=$(echo "$input" | jq -r '.model.id // ""')
version=$(echo "$input" | jq -r '.version // ""')
style=$(echo "$input" | jq -r '.output_style.name // "default"')
context_used=$(echo "$input" | jq -r '.context_window.used_percentage // 0')
context_size=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
rate_5h=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
reset_5h_at=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
rate_7d=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
reset_7d_at=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
total_cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
total_duration=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
total_input=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
total_output=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
transcript=$(echo "$input" | jq -r '.transcript_path // empty')
# Git branch
git_branch=""
if git rev-parse --git-dir >/dev/null 2>&1; then
git_branch=$(git --no-optional-locks branch --show-current 2>/dev/null)
fi
# Model version (claude-opus-4-6 -> 4.6)
model_ver=""
if [[ "$model_id" =~ ([0-9]+)-([0-9]+)$ ]]; then
model_ver=" ${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
fi
# Session timing
session_elapsed=""
if [ -n "$transcript" ] && [ -f "$transcript" ]; then
session_start=$(stat -f %B "$transcript" 2>/dev/null)
if [ -n "$session_start" ]; then
elapsed=$(($(date +%s) - session_start))
hours=$((elapsed / 3600))
minutes=$(((elapsed % 3600) / 60))
[ $hours -gt 0 ] && session_elapsed="${hours}h${minutes}m" || session_elapsed="${minutes}m"
fi
fi
# Reset time (5h)
reset_5h_ttl=""
if [ -n "$reset_5h_at" ]; then
remaining_sec=$((reset_5h_at - $(date +%s)))
if [ $remaining_sec -gt 0 ]; then
reset_5h_ttl="$((remaining_sec/3600))h$(((remaining_sec%3600)/60))m"
fi
fi
# Reset time (7d)
reset_7d_ttl=""
if [ -n "$reset_7d_at" ]; then
remaining_sec=$((reset_7d_at - $(date +%s)))
if [ $remaining_sec -gt 0 ]; then
rd=$((remaining_sec/86400))
rh=$(((remaining_sec%86400)/3600))
reset_7d_ttl="${rd}d${rh}h"
fi
fi
# Computed values
total_tokens=$((total_input + total_output))
cost_per_hour="0.00"
tokens_per_min=0
if [ "$total_duration" -gt 0 ]; then
cost_per_hour=$(awk "BEGIN { printf \"%.2f\", $total_cost / ($total_duration / 3600000) }")
tokens_per_min=$(awk "BEGIN { printf \"%.0f\", $total_tokens / ($total_duration / 60000) }")
fi
ctx_pct=$(printf "%.0f" "$context_used")
rate_5h_pct=0
[ -n "$rate_5h" ] && rate_5h_pct=$(printf "%.0f" "$rate_5h")
rate_7d_pct=0
[ -n "$rate_7d" ] && rate_7d_pct=$(printf "%.0f" "$rate_7d")
ctx_label="200K"
[ "$context_size" -ge 1000000 ] && ctx_label="1M"
total_cost_fmt=$(printf "%.2f" "$total_cost")
# --- Build 3 lines with aligned columns ---
# All labels: 14 terminal columns (emoji=2 + spaces + Korean/text + spaces + colon + space)
# Content after label is ASCII, so ${#} = terminal width
# Widest content is line 2: "100% [==========] 200K" = 22 chars
# PAD = 22 (content area), right column starts at terminal col 14+22 = 36
PAD=22
mkpad() {
local n=$(( PAD - ${#1} ))
[ "$n" -lt 2 ] && n=2
printf "%*s" "$n" ""
}
branch="${git_branch:-detached}"
ctx_bar=$(bar "$ctx_pct")
# Left content (ASCII only)
C1="${branch}"
C2="${ctx_pct}% ${ctx_bar} ${ctx_label}"
C3="\$${total_cost_fmt} (\$${cost_per_hour}/h)"
# Right content
R1="🤖 모델 : ${model_name}${model_ver} / v${version} / ${style}"
R2=""
if [ -n "$rate_5h" ]; then
r5_bar=$(bar "$rate_5h_pct")
R2="📈 사용 : ${rate_5h_pct}% ${r5_bar}"
[ -n "$reset_5h_ttl" ] && R2="${R2} (-${reset_5h_ttl})"
fi
if [ -n "$rate_7d" ]; then
r7_bar=$(bar "$rate_7d_pct")
[ -n "$R2" ] && R2="${R2} / ${rate_7d_pct}% ${r7_bar}"
[ -n "$reset_7d_ttl" ] && R2="${R2} (-${reset_7d_ttl})"
fi
R3="📊 토큰 : $(fmt_num $total_tokens) ($(fmt_num $tokens_per_min)/min)"
[ -n "$session_elapsed" ] && R3="${R3} 🕐 세션 : ${session_elapsed}"
# --- Output ---
echo "🌿 브랜치 : ${C1}$(mkpad "$C1")${R1}"
echo "🧠 Context : ${C2}$(mkpad "$C2")${R2}"
echo "💰 비용 : ${C3}$(mkpad "$C3")${R3}"

chmod +x ~/.claude/statusline.sh 를 실행하여 실행 권한을 부여합니다.

사용 가능한 JSON 필드

스크립트의 stdin으로 전달되는 JSON 객체에서 사용할 수 있는 주요 필드입니다.

smart_toy
.model.display_name / .model.id
모델명과 모델 ID (예: Opus, claude-opus-4-6)
memory
.context_window.used_percentage
컨텍스트 윈도우 사용률 (0-100)
speed
.rate_limits.five_hour / .seven_day
5시간/7일 사용률(.used_percentage)과 리셋 시각(.resets_at)
payments
.cost.total_cost_usd / .total_duration_ms
세션 총 비용(USD)과 경과 시간(밀리초)
data_usage
.context_window.total_input_tokens / total_output_tokens
누적 입력/출력 토큰 수
info
.version / .output_style.name / .transcript_path
Claude Code 버전, 출력 스타일, 트랜스크립트 파일 경로

커스터마이징 팁

tune
줄 수 조절
5줄은 렌더링 글리치가 발생할 수 있습니다. 3줄 이하를 권장합니다.
palette
ANSI 색상
터미널에 따라 ANSI 이스케이프 코드가 글자를 깨뜨릴 수 있습니다. 깨짐이 발생하면 색상 코드를 제거하세요.
width
줄 길이
이모지와 한글은 터미널에서 2칸을 차지합니다. 줄이 너무 길면 줄바꿈으로 인해 다음 줄과 겹칠 수 있습니다.
format_list_numbered
천단위 콤마
macOS의 printf는 %'d를 지원하지 않습니다. rev | sed 파이프라인으로 직접 포맷하세요.

5줄 버전 (대안)

더 자세한 정보를 원한다면 5줄 버전을 사용할 수 있습니다. 5h와 7d 사용률이 각각 별도의 줄에 표시되고, 리셋 시각과 남은 시간도 따로 보여줍니다.

5줄 버전 출력 예시
🌿 브랜치 : develop 🤖 모델 : Opus 4.6 / v2.1.97 / default
🧠 Context : 13% [=---------] 1M 🕐 시작 : 09:42 (+3h 10m)
📈 사용(5h) : 13% [=---------] ⌛ 리셋 : 13:00 (-0h 9m)
📈 사용(7d) : 42% [====------] ⌛ 리셋 : 04/10 13:00 (-1d 0h)
💰 비용 : $7.84 ($2.44/h) 📊 토큰 : 84,833 (440 tok/min)

주의: 5줄 버전은 터미널 statusline 영역이 넓어지면서 렌더링 글리치가 발생할 수 있습니다. 아래 UI 요소의 글자가 statusline 영역에 번지는 현상이 간헐적으로 나타납니다. 안정성을 원한다면 3줄 버전을 권장합니다.

관련 도구

Claude CodeAny-Buddy하네스 설정

참고: 이 가이드의 statusline 스크립트는 kainos.kr 개발 환경에서 실제로 사용 중입니다. macOS 환경 기준이며, Linux에서는 stat 명령어 등을 수정해야 합니다.

← 이전콘텐츠 자동화 파이프라인목록다음 →Slack 승인 배포 자동화