Claude Code가 실시간으로 무엇을 보고 있는지 지도로 구현한 claude-gaze
요약
본 글은 Claude Code가 어떤 파일, URL, 명령어를 접촉했는지 시각적으로 추적하는 로컬 툴 'claude-gaze'를 소개합니다. 이 툴은 터미널 스크롤의 불편함을 해소하고, 특히 서브 에이전트의 활동 내역을 지도 형태로 한눈에 파악할 수 있게 합니다.
핵심 포인트
- Claude Code Hooks만 사용하며 외부 데이터 전송 없음 (로컬 보안 유지)
- 접촉한 파일/URL/명령어를 브라우저 지도로 시각화하여 추적
- 메인 및 서브 에이전트의 활동을 색상으로 구분하고, 공유 파일을 강조 표시
Claude Code가 도구를 호출할 때마다 접촉한 파일, URL, 검색, 명령어를 브라우저상의 지도에 그려나가는 로컬 툴을 만들었습니다. 메인과 서브 에이전트는 색상으로 구분합니다. Claude Code의 Hooks만 사용하여 작동하며, 외부로 데이터는 전송하지 않습니다.
리포지토리:
저는 Claude Code를 CLI(Command Line Interface)에서 사용하면서, 명세 주도 개발(SDD: Specification Driven Development) 흐름에 따라 AI에게 구현을 진행시키는 경우가 많습니다. 이 방식으로는 터미널이 오랫동안 계속 움직입니다. 작업이 끝난 후에 '결국 어디를 보고 무엇을 했는지' 알고 싶을 때, 터미널을 길게 스크롤하여 Read나 Grep의 줄을 일일이 찾아내야만 했습니다. 이것이 번거로워서, 문자열의 나열이 아닌 그림으로 파악하고 싶었습니다.
또 하나 불편했던 점은 서브 에이전트였습니다. 서브 에이전트 이름은 사람마다 달라서, 제 환경에서는 Explore와 general-purpose라는 두 개를 만들어 사용합니다. 서브 에이전트에게 작업을 맡기면, 그 안에서의 파일 읽기는 메인 터미널에 거의 표시되지 않습니다. '무언가를 조사하고 있는 것 같다'는 것은 알 수 있어도, 실제로 어떤 파일을 읽어 다녔는지는 보이지 않는 상태였습니다.
이 두 가지 문제를 해결하기 위해, '지금 무엇을 보고 있는지'를 지도 형태로 계속 그려나가는 툴을 만들어보았습니다. 디버깅용의 정밀한 추적기가 아니라, 작업 중에 옆에 두고 볼 수 있는 용도입니다.
왼쪽에는 웹 도메인과 검색 쿼리가, 중앙에는 주체(메인 및 서브 에이전트)가, 오른쪽에는 디렉토리별 파일들이 나열됩니다. 주체 노드의 두 번째 줄에는 최신 동작(Read src/app.ts 등)이 표시되며, 각 주체의 가장 최근 활동만 선을 굵게 그립니다. 오래된 선은 가늘어질 뿐 사라지지는 않습니다.
파일을 클릭하면, 어떤 주체가 몇 번, 어떤 도구를 사용해 접촉했는지 오른쪽 상단에 나타납니다. 여러 주체가 같은 파일을 건드리면 노드가 조개껍데기 모양으로 색칠됩니다. 위의 이미지에서는 orders.ts를 서브 에이전트의 Explore와 메인 모두가 읽고 있습니다.
WebSearch 쿼리는 마름모꼴이며, 클릭하면 결과 URL이 도메인별 영역에 펼쳐집니다. 주체에서 선이 그어진 원은 WebFetch로 실제로 읽은 URL이고, 선이 없는 연한 원은 검색으로만 나온 것입니다.
존재하지 않는 파일을 Read하려고 시도한 호출은 회색 점선으로 남깁니다. '보러 갔지만 없었다'는 것 역시 어디를 찾고 있었는지에 대한 정보이기 때문입니다. 같은 디렉토리에 점선이 이어져 있다면, 없는 파일을 억측하여 읽으려고 했다는 의미입니다.
오른쪽 패널에서 보고 싶은 주체 탭을 누르면, 이벤트 목록은 해당 주체만 표시되고, 지도에서는 다른 주체가 회색으로 처리됩니다. 동기(動機)에 적었던 '서브 에이전트가 무엇을 읽었는지'는 여기서 알 수 있습니다.
페이지 하단의 '표시' 부분에서 '2D 주체별'로 전환하면, 주체별 영역으로 나뉩니다. 같은 파일은 영역 전체에 표시되며, ◈2처럼 공유하는 주체의 수를 나타냅니다.
디렉토리나 도메인 영역은 클릭하여 접을 수 있습니다. 요소가 늘어나서 세로로 길어졌을 때 사용합니다.
3D 표시도 추가했습니다. 페이지 하단의 '표시' 부분에서 '3D'로 전환하면, 디렉토리가 회색 허브가 되고 파일들이 매달려 덩어리를 이룹니다. 보여주는 용도로 적합하며, 라이브러리는 3D를 선택했을 때만 로드됩니다.
이 외에도 cat이나 grep처럼 쉘을 통해 접촉한 파일도 Bash의 명령어 문자열로부터 추정하여 점선으로 그립니다. MCP 도구와 Skill 호출도 노드가 됩니다.
Claude Code ──(Hooks 8 이벤트)──▶ curl ──▶ Node 서버 127.0.0.1:4820 ──(SSE)──▶ 브라우저(Cytoscape)
Claude Code는 도구를 사용할 때마다 Hooks에 등록된 명령어에 JSON을 표준 입력으로 전달합니다. PostToolUse의 경우 tool_name, tool_input, tool_response, agent_id 등이 포함되어 있습니다. claude-gaze가 Hooks에 등록하는 것은 어떤 이벤트에서도 동일한 이 한 줄입니다.
curl -s -m 1 -X POST http://127.0.0.1:4820/hook -H 'content-type: application/json' --data-binary @- >/dev/null 2>&1 || true
async: true
으로 등록하고, -m 1로 1초 만에 포기하기 때문에 서버가 작동하지 않아도 Claude Code는 멈추지 않습니다. 서버는 받은 JSON을 세션별로 메모리에 저장하고 Server-Sent Events를 통해 브라우저로 전송합니다. 브라우저 측에서는 순수 함수인 events.js가 Hooks의 JSON을 '노드를 추가하기', '선을 긋기'와 같은 그래프 조작으로 변환하여 Cytoscape(2D) 또는 3d-force-graph(3D)로 그립니다.
프레임워크를 사용하지 않고 순수 ES Modules로, 의존성은 Cytoscape와 three 계열만 사용합니다. 서버는 Node.js 23.6 이상 버전의 TypeScript 직접 실행으로 구동하고 있습니다. 데이터는 메모리에만 가지고 있기 때문에, 서버를 중지하면 사라집니다.
개발하는 과정에서 Hooks에 대해 확인한 사실들입니다. Hooks를 사용하는 분들의 참고가 될 것이라 생각하여, 이 부분이 기사의 핵심 내용입니다. 측정은 2026-10-12, Claude Code 2.1.296, Linux 환경에서 진행했습니다.
실패한 도구 호출은 공식 문서와 같지만, 존재하지 않는 파일의 Read를 실제 기기에서 시도했을 때 PostToolUse로 전달되지 않습니다. PostToolUse에는 아무것도 도착하지 않음을 확인했습니다. 실패를 포착하려면 PostToolUseFailure를 별도로 구독해야 합니다. -
서브 에이전트 내 호출은 메인 호출에 이것이 없기 때문에, 유무에 따라 주체를 나누고, agent_id와 agent_type가 붙습니다. agent_type (서브 에이전트의 이름. 이 기사의 예시에서는 Explore 또는 general-purpose)을 표시명으로 사용할 수 있습니다. 출현과 종료는 SubagentStart/SubagentStop으로 가져올 수 있습니다. -
WebSearch의 tool_response는 구조화된 JSON입니다. { query, results: [{ content: [{ title, url }] }] } 형태로 도착합니다. 반면, 세션 로그의 JSONL에는 Links: [...]라는 텍스트 형식으로 남아있습니다. 같은 결과라도 경로에 따라 형태가 다르기 때문에, 두 가지 모두 대응했습니다. -
세션 로그에 기록된 async: true Hook은 Claude Code의 진행을 막지 않습니다. tool_result의 시간과 서버 수신 시간의 차이를 측정했을 때, Read와 Bash는 4 ms, WebFetch는 5 ms였습니다. -
도구 호출의 과반은 Bash입니다. 제가 가진 실제 세션 로그(3.2 MB)에서는 Bash가 45회에 비해 Read는 14회였습니다. 파일 접근을 추적하려면, Bash의 명령어 문자열을 읽지 않으면 대부분 놓치게 됩니다. -
Hooks의 JSON 형식은 내부 사양입니다. 공식 문서는 세션 로그의 JSONL에 대해
비슷한 외관의 툴로 mindwalk와 graphify가 있습니다. 둘 다 뛰어난 툴이지만, 그리고 그리는 대상이 다릅니다.
-
mindwalk:
-
graphify:
| claude-gaze | mindwalk | graphify |
|---|---|---|
| 그리는 것 | 에이전트가 현재 접촉하고 있는 것 | 에이전트가 과거에 접촉했던 것 |
| 시점 | 실시간 (작업 중 옆에서 관찰) | 사후 (완료된 세션 재생) |
| 데이터 소스 | Hooks (툴 호출별 JSON) | 세션 로그 (JSONL) |
| 대상 | 파일・URL・검색・MCP・커맨드 | 리포지토리 내의 파일 |
| ... | ||
| mindwalk와 차이점은 '언제 보느냐'입니다. mindwalk는 세션 로그를 읽어, 리포지토리 전체를 밤의 지도처럼 그린 후, 에이전트의 발자국을 빛으로 재생합니다. 전체적으로 어디를 둘러봤는지 알 수 있으며, 서브 에이전트별 재생이나 세션 평가 기능도 있습니다. 반면, 로그를 읽는 구조이기 때문에 작업 중에 옆에서 관찰하는 것과 파일 외(URL・검색・MCP・커맨드)를 추적하는 것은 대상에서 제외됩니다. claude-gaze는 그 반대로, 접촉한 것만 실시간으로 그리고 전체적인 조망은 갖추지 않습니다. 작업 중에는 claude-gaze를, 끝난 후에 전체 그림 속에서 되돌아볼 때는 mindwalk를 사용한다고 생각합니다. |
graphify와 차이점은 '무엇을 그리느냐'입니다. graphify는 코드베이스나 문서를 분석하여 함수・클래스・개념의 관계를 지식 그래프로 만듭니다. 그려지는 것은 프로젝트가 어떤 구조인지이지, 에이전트가 무엇을 했는지가 아닙니다. 목적 또한 에이전트가 코드를 이해하기 위한 토큰 절감에 있으며, 관찰 툴은 아닙니다. claude-gaze는 프로젝트의 구조에는 관여하지 않고, 에이전트의 움직임만을 그립니다.
- 색상으로 구분 가능한 주체는 최대 6개까지이며, 7번째부터는 색상이 순환합니다.
- Bash로부터의 추정은 문자열 기반이므로 누락되거나 오탐지될 수 있습니다.
- 데이터는 메모리에만 저장되며, 서버를 재시작하면 사라집니다. 본문에 적힌 '끝난 후에 되돌아보기' 기능은 서버를 멈추기 전까지만 가능합니다.
- Hooks의 JSON 형식이 변경되면 결과 URL 추출 등이 작동하지 않을 부분이 있습니다.
Agent
툴 호출 자체는 로그에 나타나지 않습니다. 서브 에이전트의 시작은 SubagentStart로 그립니다 - Windows는 미검증입니다. Hooks의 커맨드가 sh 구문이므로 WSL을 상정하고 있습니다.
요구 사항은 Node.js 23.6 이상, curl, Claude Code입니다.
git clone https://github.com/NeoSolleil/claude-gaze.git && cd claude-gaze
npm install
npm run hooks:install # ~/.claude/settings.json에 Hooks를 추가합니다 (원본 파일은 settings.json.bak에 남겨둡니다)
...
이후 새로 Claude Code를 실행하여 작업을 시키면, 브라우저 왼쪽에 세션이 나타납니다. Hooks는 시작할 때 읽히기 때문에 이미 열려 있는 세션에는 적용되지 않습니다. 중지할 때는 npm run hooks:remove로 claude-gaze에서 파생된 Hooks만 제거합니다.
설정 파일을 직접 관리하고 싶은 사람은 npm run hooks:print로 추가할 JSON을 볼 수 있습니다. 프로젝트 단위로 넣는 --project, 별도의 포트로 받는 --port도 있습니다.
Hooks만으로 '지금 무엇을 보고 있는지'는 충분히 파악할 수 있었습니다. 터미널을 거슬러 올라가지 않아도, 작업이 끝난 시점의 지도를 보면 어느 디렉토리를 돌아다녔고, 무엇을 검색했으며, 서브 에이전트가 백그라운드에서 무엇을 읽었는지 알 수 있습니다.
향후에는 claude plugin install로 설치할 수 있게 하는 플러그인화와, 과거 세션의 JSONL을 읽어 재생하는 기능을 구상하고 있습니다.
이 도구 자체도 Claude Code와 함께 만들었습니다. Hooks의 동작을 실기에서 확인하면서 진행했기 때문에, 제4절 내용은 그때 기록한 것이기도 합니다.
리포지토리:
- 아직 이 글을 쓰고 있을 때는 큰 리포지토리를 구동한 것은 아니거든요.
- 그래서 건드려야 할 파일이 너무 많을 때 어떻게 되는지가 핵심이 될 것 같습니다.
- 물론 지금 상태로 완성된 것은 아니지만, 정리와 향후에 작성할 내용은 제외하고 앞으로는 어떻게 해야 할까요?
- 차라리 이 브라우저에서 Claude에게 지시를 보낼 수 있다면 좋을 것 같은데.
- 만들고 난 후에 생각한 건데, 개인적으로 이미지의 오른쪽 페인 쪽에 제가 이상적인 무언가가 있는 것 같습니다.
- 무엇을 하고 있는지 파악하고 싶다는 것이 근본이니까요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기