Agent Profiler: 세션 시간이 어디로 가는지 보여 주는 Claude Code 프로파일러
Claude Code 세션의 시간이 모델 대기, 도구, 서브에이전트 중 어디에 쓰였는지 상태 표시줄에 실시간으로 보여 주고 OTLP 트레이스도 내보냅니다.
권한
- 파일 쓰기컴퓨터에 파일을 만들거나 덮어쓸 수 있습니다($.fs.write).
- 네트워크HTTP 요청을 보내거나 MCP 서버와 통신할 수 있습니다($.http.fetch / $.mcp.*).
- 도구 호출 가로채기Claude가 하는 모든 도구 호출을 볼 수 있고(tool.call / tool.check), 이를 차단하거나 변경할 수 있습니다.
- UI 변경Claude Code 화면에 밴드, 패널, 상태 텍스트, 토스트를 그립니다(ui.render / $.ui.*).
- 명령어/도구 추가사용자나 Claude가 호출할 수 있는 새 슬래시 명령어나 도구를 등록합니다($.command.register / $.tool.register).
- 테스트 버전
- v2.1.303
- 마지막 테스트
- 필요 버전
- Claude Code ≥ 2.1.287
- 표시 위치
- 상태 표시줄, 패널, 토스트
Claude Code 안에서 설치:
/plugin install agent-profiler --marketplace YeonwooSung/my-claude-code-mods이 모드는 무엇을 하나요?
Agent Profiler는 YeonwooSung이 만든 Claude Code 프로파일러로, my-claude-code-mods 모음의 일부입니다. 답해 주는 질문은 하나입니다. 세션이 느리게 느껴질 때 시간은 어디로 갔을까요? 각 턴의 시간을 모델 응답 대기, 도구 실행, 차단형 서브에이전트, 엔진 오버헤드로 나누고 결과를 세 곳에 보여 줍니다.
- 상태 표시줄: Claude가 작업하는 동안 실시간으로 갱신됩니다. 예:
model 100% · tools 0% · ▶ model claude-haiku-5-5 12.5s. /profile: 세션 전체의 텍스트 보고서이며,/profile turn은 마지막 턴만 보여 줍니다. 시간 범주, 첫 토큰까지의 시간, 토큰 수, 느린 도구, 반복해서 읽은 파일, 서브에이전트, 짧은 발견 사항 목록이 들어 있습니다./profile-pane: 진행 중인 요청과 도구를 보여 주는 실시간 패널입니다./profile-export는 세션을 OTLP JSON으로 기록합니다.
이 모드는 주장에 신중합니다. "추론 시간"은 보고하지 않습니다. 모든 수치에는 등급이 붙습니다. measured(도구 소요 시간처럼 Claude Code가 넘겨준 값), observed(모드가 이벤트 경계에서 직접 잰 값), reported(API가 보고한 토큰 사용량), inferred(나머지로 계산한 값)입니다. 작성자의 README는 Claude Code 2.1.287 이상을 요구합니다.
데모
녹화에서는 작은 데모 프로젝트에서 이 모드를 불러온 Claude Code를 실행하고, Claude에게 README.md를 읽고 프로젝트를 한 문장으로 설명해 달라고 요청합니다. 턴이 진행되는 동안 하단 위의 상태 표시줄이 실시간으로 올라갑니다. 처음에는 model 92% · tools 0%, 이어서 model 100%와 진행 중인 요청 ▶ model claude-haiku-5-5, 그리고 경과 시간이 표시됩니다. 턴이 끝나면 /profile을 실행합니다. 보고서에는 모델 응답 대기 29.0초, 도구 5ms, 첫 토큰까지의 시간, 입력 토큰 82.3k, Read 호출 1회, 그리고 "모델을 기다린 시간이 에이전트 시간의 100%"라는 발견 사항이 나옵니다.
설치
설치 블록의 어떤 방법을 써도 됩니다. 모두 작성자 본인의 마켓플레이스에서 바로 설치합니다. 이 마켓플레이스에는 여러 플러그인이 있으므로 agent-profiler를 고르세요. 상태 표시줄과 명령은 다음 세션을 시작할 때 나타납니다.
$ install agent-profiler
Claude Code 2.1.287 이상 필요
작성자의 마켓플레이스에서 설치: YeonwooSung/my-claude-code-mods
1.Claude Code 안에서 한 줄로
/plugin install agent-profiler --marketplace YeonwooSung/my-claude-code-mods실행 중인 세션(v2.1.275 이상)에 붙여 넣으세요. Claude Code가 먼저 마켓플레이스 추가 여부를 묻습니다.
2.셸에서 설치
claude plugin marketplace add YeonwooSung/my-claude-code-mods claude plugin install agent-profiler@my-claude-code-mods그런 다음 이미 열려 있는 세션에서 /reload-plugins를 실행하세요.
3.설치하지 않고 사용해 보기
git clone https://github.com/YeonwooSung/my-claude-code-mods claude --plugin-dir ./my-claude-code-mods/agent-profiler한 세션에서만 모드를 불러옵니다. 설정에는 아무것도 추가되지 않습니다.
작동 방식
모듈 hooks/register.tsx는 메모리에 Profiler 객체를 두고 이벤트 경계에서 데이터를 넣어 줍니다. turn.start와 turn.complete, turn.step을 통한 모델 호출, tool.call을 통한 각 도구, 그리고 classic.PostToolUse로 전달되는 Claude Code 자체의 도구 소요 시간입니다. tool.call 훅은 관찰만 합니다. await next(e)로 도구가 끝나기를 기다리고 결과를 그대로 반환합니다. hooks/register.tsx에서:
on('tool.call', async ($, e, next) => {
anonymous += 1
const id = e.tool_use_id ?? `anonymous-${anonymous}`
const tool = String(e.tool)
safe(() => profiler.toolStart(Date.now(), { id, tool, agentId: e.agentId, input: summarizeInput(tool, e as unknown as Record<string, unknown>) }))
paint($)
try {
const answer = await next(e)
safe(() => profiler.toolEnd(Date.now(), id, toolOutcome(answer)))
return answer
} // ...
}).catch(($, e, next) => next(e))기록의 모든 단계는 safe()를 거치므로 프로파일러 자체의 오류는 세션을 망가뜨리지 않고 버려집니다. 상태 표시줄은 초당 최대 두 번 다시 그려집니다. 각 턴이 끝나면 모드는 새로 끝난 스팬을 <outputDir>/<sessionId>/<loadId>-<seq>.otlp.json에 쓰고, 세션이 끝날 때 나머지와 세션 루트 스팬을 씁니다. 스팬 이름은 GenAI 규약(chat <model>, execute_tool <tool>, invoke_agent <type>)을 따릅니다. 스팬 ID와 트레이스 ID는 결정적이므로 같은 세션을 두 번 보내도 같은 스팬이 됩니다. 메모리에는 요청과 도구 호출을 최대 20,000개까지 두며, 넘으면 끝난 턴 중 가장 오래된 것부터 버립니다.
사용자 지정
옵션 세 가지가 /plugin 설정 메뉴나 pluginConfigs에 있습니다.
| 옵션 | 기본값 | 의미 |
|---|---|---|
otlpEndpoint |
비어 있음 | OTLP/HTTP 수집기의 기본 URL. 예: http://localhost:4318. 비어 있으면 파일만 씁니다. |
outputDir |
~/.claude/agent-profiler |
트레이스 파일을 쓰는 위치이며 세션마다 폴더가 하나입니다. |
exportCommandText |
false |
턴 프롬프트, Bash 명령줄, 검색 패턴을 내보내기에 포함하며, 눈에 띄는 비밀 값은 가립니다. |
Jaeger에서 트레이스를 보려면 저장소의 examples/jaeger/docker-compose.yml을 실행하고, otlpEndpoint를 http://localhost:4318로 설정한 뒤 http://localhost:16686을 엽니다. Grafana Tempo도 같은 OTLP/HTTP 엔드포인트를 받습니다.
권한 및 안전
실행하기 전에 플러그인이 실행할 수 있는 파일을 읽었습니다. .claude-plugin/plugin.json, hooks/hooks.json, 그리고 hooks/register.tsx와 Jaeger compose 파일은 전체를 읽었습니다. hooks/core/의 모듈 11개 중 export.ts, otlp.ts, redact.ts와 profiler.ts의 입력 요약 부분은 전체를 읽었고, 모든 모듈에서 네트워크, 프로세스, 파일, eval, import(), 환경 변수 호출을 검색했습니다(검색에 걸린 것은 register.tsx뿐입니다). 테스트 파일은 목록만 확인했고 읽지는 않았습니다. package.json, 설치 스크립트, 바이너리, 번들되거나 압축된 코드, eval, 동적 import()는 없습니다. hooks/ 소스에는 폭이 없는 문자나 숨은 문자가 없으며, ASCII가 아닌 문자는 █, ░, ·, ⏱ 같은 화면에 보이는 상태 및 보고서 기호뿐입니다. 이 모드는 프롬프트나 도구 결과에 텍스트를 주입하지 않습니다.
주목할 만한 발견 사항:
- 기본적으로 파일을 씁니다. 매 턴 이후와 세션 종료 시
$.fs.write를 호출해outputDir을 설정하지 않으면~/.claude/agent-profiler/<sessionId>/에 씁니다. 플러그인 자신의 폴더이고settings.json이나 셸 파일은 아니지만, 묻지 않고 기록됩니다. 파일에는 소요 시간, 토큰 수, 모델 이름, 도구 이름,Read/Edit/Write의 파일 경로, 각 Bash 명령의 범주(test, build 등)가 들어 있습니다. 파일 경로는 항상 내보내집니다. 프롬프트, Bash 명령, 검색 패턴은exportCommandText를 켰을 때만 내보내집니다. - 네트워크는 직접 선택했을 때만.
$.http.fetch는otlpEndpoint가 비어 있지 않을 때만 호출되며, 같은 트레이스 JSON을<endpoint>/v1/traces로 POST할 뿐입니다. 호스트는 입력한 그대로입니다. 원격 수집기를 지정하면 파일 경로와,exportCommandText를 켰다면 가려진 명령이 내 컴퓨터 밖으로 나갑니다. README는 가리기가 최선을 다하는 수준이라고 경고합니다. - 환경 변수 하나,
HOME을 읽습니다.outputDir의~를 펼치기 위해서입니다. - 도구 호출을 가로채지만 바꾸지는 않습니다.
tool.call과tool.check는 관찰만 하고 그대로 통과시키며, 둘 다.catch보호가 있습니다. 거부하거나 고쳐 쓰는 일은 없습니다.claude plugin validate는classic.*훅도.catch없는 게이팅 훅으로 나열하지만, 실제로는next(e)를 반환하는 관찰용입니다. validate에 따르면 조직이 Claude Code를 관리하는 환경에서는classic.*훅이 실행되지 않으므로, 그곳에서는 보고서가 불완전할 수 있습니다. - 프로세스, 데몬, 모델 호출이 없습니다. 명령을 실행하지 않고 백그라운드 서비스도 없습니다. 쓰는 것은 세션 안의 타이머뿐입니다.
- 선택적 외부 서비스. Jaeger나 Tempo는 트레이스를 볼 때만 필요합니다. compose 파일은
jaegertracing/all-in-one:latest를 가져오며, 모드가 직접 실행하지는 않습니다. - 라이선스. Apache-2.0(저장소 루트의
LICENSE).
claude plugin validate는 오류와 경고 없이 위의 참고 사항만 보고했습니다. 작성자의 11개 파일, 67개 테스트는 Claude Code 2.1.303에서 claude plugin test로 모두 통과했습니다.
- 파일 쓰기
- 컴퓨터에 파일을 만들거나 덮어쓸 수 있습니다($.fs.write).
- 네트워크
- HTTP 요청을 보내거나 MCP 서버와 통신할 수 있습니다($.http.fetch / $.mcp.*).
- 도구 호출 가로채기
- Claude가 하는 모든 도구 호출을 볼 수 있고(tool.call / tool.check), 이를 차단하거나 변경할 수 있습니다.
- UI 변경
- Claude Code 화면에 밴드, 패널, 상태 텍스트, 토스트를 그립니다(ui.render / $.ui.*).
- 명령어/도구 추가
- 사용자나 Claude가 호출할 수 있는 새 슬래시 명령어나 도구를 등록합니다($.command.register / $.tool.register).
호환성 및 문제 해결
macOS의 Claude Code 2.1.303에서 validate, 작성자의 테스트, 데모 녹화를 확인했습니다. README에 따르면 작성자 본인의 엔드 투 엔드 검증은 2.1.280에서 이루어졌고, 이벤트 형태는 2.1.292 타입 선언을 따릅니다. 패널과 상태 표시줄은 터미널과 데스크톱 Code 탭에서 그려지지만 VS Code 채팅 패널과 claude -p에서는 그려지지 않습니다. /profile 텍스트는 어디서나 동작합니다.
- 상태 표시줄이나 명령이 없을 때.
claude --version이 2.1.287 이상인지 확인하고, 실행 중인 세션에 설치했다면/reload-plugins를 실행하세요. - 트레이스 파일이 없을 때. 세션 ID를 알기 전에는 아무것도 쓰지 않습니다. 쓰기에 실패하면 토스트가 한 번 표시되므로
outputDir에 쓸 수 있는지 확인하세요. - 핫 리로드 후 수치가 초기화될 때. 메모리의 상태는 처음부터 다시 시작하지만, 이미 쓰인 묶음은 이전 로드 ID 아래 디스크에 남습니다.
- Bash로 바뀐 파일. 반복 읽기 감지에는 보이지 않습니다.
- 모델 서버 내부의 시간(대기열, 프리필, 디코딩)은 어떤 클라이언트 쪽 도구로도 나눌 수 없습니다. 첫 토큰까지의 시간에 함께 들어 있습니다.
자주 묻는 질문
- Agent Profiler가 내 데이터를 어딘가로 보내나요?
- 기본적으로는 보내지 않습니다. 트레이스 파일을 내 컴퓨터의 폴더에 쓸 뿐입니다. otlpEndpoint 옵션을 설정한 경우에만 네트워크 요청을 보내며, 각 트레이스 묶음을 해당 URL의 /v1/traces로 POST합니다. 작성자에게는 아무것도 전송되지 않습니다.
- 트레이스 파일은 어디에 저장되나요?
- outputDir을 설정하지 않으면 ~/.claude/agent-profiler/<sessionId>/ 에 저장됩니다. 턴이 끝날 때마다, 그리고 세션이 끝날 때 한 번 더 기록됩니다. 파일에는 소요 시간, 토큰 수, 도구 이름, 파일 경로가 들어 있습니다.
- 프롬프트와 Bash 명령도 내보내나요?
- exportCommandText를 켜지 않으면 내보내지 않습니다. 꺼져 있으면 프롬프트, Bash 명령줄, 검색 패턴은 파일과 POST에 들어가지 않고 test, build 같은 명령 범주만 남습니다. 켜면 가능한 범위에서 비밀 값을 가린 뒤 내보냅니다.
- 모델이 계산한 시간을 측정하나요?
- 아니요. README에도 그렇게 적혀 있습니다. 측정하는 것은 클라이언트가 기다린 시간이며, 예를 들어 첫 토큰까지의 시간에는 네트워크, 대기열, 프리필이 섞여 있습니다. 모든 수치에는 observed, measured, reported, inferred 중 하나가 붙습니다.
- Jaeger 같은 다른 서비스가 필요한가요?
- 아니요. /profile과 상태 표시줄은 단독으로 동작합니다. 내보낸 OTLP 트레이스를 화면에서 보고 싶을 때만 Jaeger나 Grafana Tempo가 필요합니다. 저장소에는 작은 Jaeger docker-compose 파일이 들어 있습니다.
# 관련 모드
추천Agent Radar
실행 중인 서브에이전트마다 프롬프트 위에 한 줄씩: 경과 시간, 도구 수, 현재 작업. /radar 패널도 제공합니다.
- 프롬프트 위
- 패널
- 토스트
- 도구 호출 가로채기
- 프롬프트 읽기
- UI 변경
- 명령어/도구 추가
v2.1.291에서 테스트됨
추천Cache Clock
Claude Code 상태 표시줄 아래에 프롬프트 캐시의 남은 시간, 적중률, 식은 뒤 다시 캐시할 토큰 수를 보여 줍니다.
- 상태 표시줄
- 파일 읽기
- 파일 쓰기
- 명령어 실행
- 명령어/도구 추가
v2.1.296에서 테스트됨
추천도구 호출 카운터
Claude의 도구 호출을 턴별·세션별로 세어 스피너 옆에 표시하고, 상세 내역을 보는 /tally 명령을 추가합니다.
- 스피너
- 대화 기록
- 상태 표시줄
- 도구 호출 가로채기
- UI 변경
- 명령어/도구 추가
v2.1.310에서 테스트됨
더 보기: 타이머, 할 일, 스탠드업, 상태 표시줄 및 프롬프트 바, 패널 및 대시보드.