상태줄 데몬이 render_worker를 두 개씩 돌리고 있었다
노트북이 자꾸 뜨거워서 프로세스를 뒤졌더니 상태줄 데몬이 워커를 이중으로 돌리고 있었다. 가볍게 다시 깔려다가 결국 처음부터 새로 짰다.
egg2분 읽기
노트북이 자꾸 뜨거웠다. 딱히 무거운 걸 켜둔 것도 아닌데 팬이 계속 돌았다.
ps로 뒤져봤다. 터미널 상태줄로 쓰던 claude-statusbar 데몬 밑에 render_worker가 두 개 붙어 있었다. 하나는 데몬이랑 같이 뜬 정상 워커고 다른 하나는 56분 뒤에 혼자 추가로 생긴 놈이었다. 초당 한 번 그리는 걸 이중으로 돌리고 있던 셈이다.
범인은 상태줄이었다
3일치 CPU 시간을 다 더해보니 HUD, 데몬, 워커 둘이 합쳐서 2시간 36분이었다. 한 번에 크게 먹는 게 아니라 매초 조금씩 걷어가는 식이라 눈치채기가 늦었다.
802 hud start 36:01
1386 daemon --render-interval 1.0 23:19
1391 render_worker 58:36
14070 render_worker 38:14 ← 중복
가볍게 다시 깔려다가
상태줄은 claude-code-usage-bar라는 오픈소스였다. 지우기 전에 라이선스부터 봤다. MIT, 2026년 9월 23일 기준 377 star (GitHub API로 확인). 포크해서 내 계정에 가볍게 다시 올려도 문제 될 게 없었다.
근데 막상 뭘 가볍게 할지 들여다보니 손댈 코드가 없었다. auto_upgrade: false, 데몬 대신 인라인 렌더, 새로고침 10초. 딱 설정값 세 개였고 코드는 한 줄도 안 바꾼 상태였다. 이거 하나 들고 다니려고 28MB짜리 파이썬 번들을 포크해서 업스트림 나올 때마다 리베이스하는 건 아무래도 배보다 배꼽이 큰 일 같았다.
stdin에 이미 다 있었다
Claude Code가 상태줄 명령에 매 틱마다 뭘 넘겨주는지부터 봤다. 캐시 파일을 열어보니 5시간·7일 쿼터 사용률과 리셋 시각, 컨텍스트 창 사용률, 세션 비용, 모델 이름까지 이미 다 들어 있더라. 트랜스크립트를 파싱할 것도, API를 호출할 것도, 뭘 캐시해둘 것도 없었다.
그래서 처음부터 새로 짰다. ccbar.py, 표준 라이브러리만 써서 163줄. 틱마다 한 번 떴다가 stdout 찍고 바로 끝난다.
상주 프로세스는 0개, 설치 용량은 5KB, 한 번 렌더에 22ms 걸린다. 원래 쓰던 데몬 방식은 상주 프로세스가 셋 이상이고 렌더 한 번에 86ms였다.
뺐다가 다시 넣은 것
원래 상태줄에는 →NN% 같은 예상치가 있었다. 지금 속도로 가면 창이 끝날 때 몇 %일지 보여주는 값인데, 처음 짤 때는 군더더기라고 생각해서 뺐다.
그런데 다시 보니 계산에 필요한 값이 stdin에 이미 다 있었다. 뺀 게 아니라 10줄을 빠뜨린 거였다.
def project(pct, resets_at, window, now=None):
if not resets_at or not pct:
return None
now = time.time() if now is None else now
elapsed = now - (resets_at - window)
frac = elapsed / window
if frac < 0.1 or frac > 1:
return None
return min(999, round(pct / frac))
Claude Code는 창이 언제 끝나는지는 주는데 언제 시작했는지는 안 준다. 그래서 시작 시각을 resets_at - window로 거꾸로 계산한다. 창이 열리고 얼마 안 됐을 때는 호출 한두 번만으로도 속도가 무한대처럼 튀어서 창의 10%가 지나기 전에는 이 값을 아예 숨긴다. 직선으로 쭉 그어서 추정하는 거라 마지막에 몰아 쓰면 실제보다 높게 나온다는 것도 README에 적어뒀다.
정리하고 보니
ccbar를 상태줄로 걸고 데몬은 공식 uninstall로 지웠다. 처음 ps에서 봤던 상주 프로세스 넷(HUD, 데몬, 워커 둘)이 0개가 됐다.
저장소는 github.com/egg-/ccbar, MIT. 다음에 또 뜨거워지면 그때는 다른 데를 봐야겠다.
Filed under 개발