
transcript.jsonl을 직접 파싱하여 '무엇이 호출되었는지' 시각화하기
요약
Claude Code의 transcript.jsonl 파일을 직접 파싱하여 상세한 사용 현황을 시각화하는 방법을 소개합니다. /usage 명령어가 제공하지 않는 스킬, 에이전트, MCP 서버별 호출 횟수를 집계하여 비용 최적화와 환경 분석을 돕습니다.
핵심 포인트
- transcript.jsonl을 통해 상세한 툴 호출(tool_use) 내역 추출 가능
- 스킬, 서브 에이전트, MCP 서버별 호출 빈도 집계 방법 제시
- Bash와 Python을 결합한 usage-breakdown.sh 스크립트 활용
- 토큰 사용량의 품목별 분석을 통한 비용 최적화 지원
전작 「Agent 호출을 파일에 기록하여 Slack으로 전송하기」에서 툴 호출(tool call) 기록에 대해 작성했습니다. 이번에는 그 연장선상에서, 기록된 transcript.jsonl을 직접 파싱하여 「어떤 Skill이 몇 번·어떤 Agent가 몇 번·어떤 MCP 서버가 몇 번 호출되었는지」를 집계하는 스크립트에 관한 이야기입니다.
Claude Code의 /usage 명령은 비용($)과 잔량을 보여주지만, 「이번 주에 어떤 Skill을 가장 많이 사용했는지」, 「어떤 Agent가 무거운지」는 보이지 않습니다. transcript.jsonl에는 모든 tool_use 블록이 남아 있으므로, 이를 직접 읽으면 /usage가 알려주지 않는 레이어의 사용 현황을 파악할 수 있습니다.
/usage가 출력하는 것은 5시간 블록·7일 블록의 소비율과 세션 단위의 토큰 수입니다. 「이 AutoTrigger의 Skill이 사실 주 20회 호출되었다」, 「general-purpose Agent가 전체 Agent의 절반을 차지하고 있다」와 같은 품목별 내역은 나오지 않습니다.
비용 최적화나 환경의 건전성 체크를 하려면 「무엇에 토큰이 사용되고 있는가」에 대한 품목 정보가 필요합니다. transcript.jsonl은 그 정보원으로서 최적이며, ~/.claude/projects/ 이하에 모든 세션 분량이 축적되어 있습니다.
각 파일은 1행 1레코드의 JSONL 형식입니다. Claude Code가 송수신한 각 턴(turn)이 1개의 레코드가 됩니다.
{
"type": "assistant",
"uuid": "...",
...
집계에 필요한 것은 message.content[]의 type == "tool_use" 블록뿐입니다. name 필드가 툴 이름이며, input에 인자(argument)가 들어 있습니다.
| 툴 | 집계 키 | 추출 대상 |
|---|---|---|
Skill | input.skill | 스킬 이름 (plugin:name 형식으로 namespace 분리도 가능) |
Agent | input.subagent_type | 서브 에이전트(subagent) 종류 |
mcp__* | name의 두 번째 세그먼트 | MCP 서버 이름 (mcp__<server>__<tool>) |
~/.claude/scripts/usage-breakdown.sh는 Bash의 히어 도큐먼트(heredoc)로 Python을 내장하고 있습니다. Bash에서 디렉토리와 윈도우 기간을 받아 Python이 파일을 풀 스캔(full scan)합니다.
#!/usr/bin/env bash
ARG="${1:-7d}"
TR_DIR="$HOME/.claude/projects/-Users-matsubara"
...
윈도우 기간은 파일의 mtime으로 필터링합니다. --short 플래그가 들어오면 파싱(parse) 처리는 모두 동일하지만 출력만 한 줄로 제한합니다.
파싱 본체는 심플합니다:
for path in glob.glob(f"{tr_dir}/*.jsonl"):
mtime = os.path.getmtime(path)
if mtime < cutoff_ts: continue
...
Skill의 plugin:name 형식(예: hookify:configure)은 :로 split하여 namespace 집계도 별도로 수행합니다. 이를 통해 어떤 plugin 패키지가 무거운지, 개별 스킬 이름과는 다른 축에서 확인할 수 있습니다.
최근 7일간 실행하면 다음과 같이 출력됩니다.
$ usage-breakdown.sh 7d
=== usage breakdown (last 7d, 51 transcripts) ===
total tool_use: 4230
...
이번 주는 51개 세션·4,230개의 tool_use였으며, Bash가 전체의 61%(2,583회)를 차지했습니다. MCP는 claude-in-chrome이 압도적으로 많아 261회였습니다. Agent는 general-purpose가 가장 많은 20회, Explore가 7회였습니다.
Skill 호출이 총 2회뿐인 이유는, 이번 주에 Skill을 거의 수동으로 호출하지 않고 AutoTrigger(CLAUDE.md의 키워드 일치)로 동작하는 설정이 많았기 때문입니다. AutoTrigger는 트랜스크립트(transcript)에 Skill tool_use로 나타나야 하므로, 적은 수치가 정직하게 반영되었습니다.
subagent_type가 "?"로 되어 있는 Agent가 4회 있습니다. 이는 Agent 툴에 subagent_type을 지정하지 않았을 때(기본값인 general-purpose에 해당)의 호출이며, 스크립트가 inp.get("subagent_type", "?")로 폴백(fallback) 처리된 부분입니다. 실제 운영 시 "?"가 늘어난다면 '어느 세션(Session)인지'를 좁혀봄으로써 서브 에이전트 지정 누락을 발견하는 데 사용할 수 있습니다.
--short 옵션을 사용하면 한 줄 요약이 출력됩니다.
$ usage-breakdown.sh --short
4235 tool_use across 51 sessions (7d)
Claude Code의 상태 표시줄(status line) 커스텀 스크립트에 통합하여 사용하고 있습니다. 비용 범위(이전 작업물인 token-budget-advisor.sh 출력)와 함께 나열하면 '사용량과 잔량을 한눈에 볼 수 있는' 상태가 됩니다.
# statusline hook의 한 예
BUDGET=$(~/.claude/scripts/token-budget-advisor.sh --short)
USAGE=$(~/.claude/scripts/usage-breakdown.sh --short)
...
— 세션이 날짜를 넘기면, 오래된 턴(turn)도 '최근 파일'로서 집계에 포함됩니다. 엄밀하게 처리하려면 mtime 필터는 파일 단위이므로 정밀도가 떨어지므로, rec.get("timestamp")를 이용한 레코드(record) 레벨 필터가 필요하지만, 경향 파악 수준이라면 mtime으로도 충분했습니다. -
서브 디렉토리의 JSONL을 가져오지 않음—glob.glob(f"{tr_dir}/*.jsonl")은 평면적인 1계층만 확인합니다. 서브 에이전트의 트랜스크립트(transcript)는 <session-uuid>/subagents/agent-*.jsonl에 들어가기 때문에, 현재 구현으로는 집계에서 제외됩니다. **/*.jsonl로 변경하면 가져올 수 있지만, 무겁기 때문에 의도적으로 제외했습니다. -
—mcp__claude-in-chrome__computer와 같은 긴 MCP 툴 이름에서 split("__")의 두 번째 세그먼트를 가져오는 구현이므로, parts[1]만 남아 서버 이름을 정확하게 추출할 수 있습니다. 단, 서버 이름 자체에 __가 들어가는 경우에는 잘못 추출될 수 있습니다(현재까지는 발생 사례 없음). -
30일(30d) 윈도우는 몇 분이 소요됨—890개 이상의 파일을 전체 스캔하기 때문에, 일상적으로는 7d 또는 --short를 사용하고, 심층 분석 시에만 30d를 사용하는 것이 현실적입니다.
transcript.jsonl의 message.content[].type == "tool_use"만 추출하면 Skill, Agent, MCP 서버의 호출 횟수를 얻을 수 있습니다. - Python의 카운터(counter)로 most_common(10)을 출력하는 것만으로 '부하가 큰 항목'을 즉시 파악할 수 있습니다. -
mtime 기간 필터와 Python의 히어 도큐먼트(heredoc) 임베딩을 통해 Bash 스크립트 하나로 해결됩니다. -
--short로 한 줄 요약을 만들어 상태 표시줄에 상시 표시하면, 환경의 건전성을 비용과는 다른 축에서 모니터링할 수 있습니다.
/usage로 비용을 확인하고, 이 스크립트로 항목별 내역을 확인합니다. 이 두 가지를 결합하면 '무엇을 위해 몇 토큰을 사용했는지'에 대한 해상도가 높아집니다.
Lily(@bokuwalily)― 개인 개발자. Claude Code로 자동화 기반을 구축하며 iOS 앱과 웹 서비스를 양산하고 있습니다.
- 제작물 및 기사는 bokuwalily.com에 정리되어 있습니다 🖥️
- AI로 '잠자는 동안에도 돌아가는 시스템'을 만들어 월 120만 엔을 벌게 된 이야기는 note 유료 기사에 💰
- OSS: github.com/bokuwalily 🐙
- 최신 정보 및 문의는 X @bokuwalily 로 🌍
여러분의 ❤️와 공유가 큰 힘이 됩니다!
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기