devlog.md

[픽셀에이전트_헤르메스연동] 헤르메스도 픽셀 오피스에 띄우기 (Pixel Agents)_01

텔레그램으로 굴리고 있는 자율 에이전트 헤르메스가 지금 뭘 하고 있는지 화면으로 보고 싶어서, 클로드 코드 작업 모습을 픽셀아트 캐릭터로 보여준다는 오픈소스 "Pixel Agents"를 헤르메스에도 붙여봤다. 결과적으로 포크해서 새 프로바이더를 만들고, 숨어있던 구조적 한계까지 고쳐야 했다.

1단계: Pixel Agents 조사

검색해보니 Pixel Agents는 터미널의 클로드 코드 세션을 픽셀 오피스 캐릭터로 시각화하는 VS Code 확장/스탠드얼론 서버였다. 구조 문서에는 "provider-agnostic"이라고 적혀 있었지만, 실제 구현은 Claude Code 하나만 있었다. 로컬 HTTP 훅 엔드포인트(/api/hooks/<provider>)에 세션 이벤트를 POST하면 캐릭터가 뜨는 구조라, 헤르메스 쪽에서도 같은 형식으로 이벤트를 보내면 될 것 같았다.

2단계: 헤르메스 프로바이더 새로 구현

저장소를 클론해서 HookProvider 인터페이스를 확인하고, 클로드 프로바이더를 참고해 hermes.ts를 새로 작성했다. 헤르메스 쪽은 자체 훅 시스템(~/.hermes/hooks/)이 있어서, 세션 시작/도구 사용/턴 종료 시점마다 Pixel Agents 서버로 이벤트를 쏘는 파이썬 핸들러를 같이 만들었다.

3단계: 숨어있던 단일 프로바이더 문제

등록만 하면 끝일 줄 알았는데, 실제 런타임(AgentRuntime)이 생성 시점에 프로바이더 하나만 고정해서 쓰고 있었다. 이벤트가 어느 프로바이더에서 왔는지는 무시하고 항상 클로드 방식으로 해석하는 구조였다. handleEvent가 매번 올바른 프로바이더를 다시 찾도록 고쳤고, 이 덕분에 클로드 코드와 헤르메스가 동시에 정확히 분리되어 동작하게 됐다.

4단계: 실사용 배포

임시 작업 폴더는 세션 끝나면 사라지므로 ~/pixel-agents로 영구 이동하고, 바탕화면에 시작/종료 스크립트를 만들었다. 헤르메스 훅 파일을 실제로 설치하고 게이트웨이를 재시작하니 텔레그램 대화가 오피스 화면에 반영되기 시작했다.

5단계: 화면 상주 플로팅 창

브라우저 탭 말고 화면에 항상 떠 있는 창이 있으면 좋겠다는 요청으로, Electron으로 얇은 래퍼를 만들었다. 기존 서버를 그대로 재사용하는 always-on-top 프레임리스 창이라 별도 서버 로직 없이도 잘 붙었다. 이후 줌/위치가 매번 초기화되는 문제, Layout/Settings 버튼이 작은 창에서 너무 크게 보이는 문제, 마우스 세로 휠만으로는 좌우 이동이 안 되는 문제를 차례로 손봤다(Shift+스크롤 추가).

6단계: 커뮤니티 레이아웃으로 교체

기본 오피스가 방 두 개짜리라 더 단순한 걸 원해서, 커뮤니티 갤러리 "Pixel Index"에서 가로로 넓고 방 하나짜리인 "Severance Office" 레이아웃을 찾아 가져왔다. 스탠드얼론 서버는 레이아웃 파일 실시간 반영 기능이 VS Code 전용이라, 파일을 갈아끼운 뒤 서버를 재시작해서 적용했다.

Trouble Shooting

증상원인해결 방법
헤르메스 이벤트를 보내도 클로드 방식 라벨/포맷으로만 처리됨런타임이 생성 시점 프로바이더 하나만 고정해서 사용, 이벤트별 providerId를 무시이벤트마다 올바른 프로바이더를 다시 찾아 임시로 교체하는 방식으로 패치
종료 스크립트가 엉뚱한 프로세스를 못 찾음node ... | tee log & 형태로 백그라운드 실행 시 $!가 node가 아닌 tee의 PID를 가리킴프로세스 치환(> >(tee ...))으로 바꿔 node의 실제 PID를 잡도록 수정
서버 재시작 후 헤르메스 캐릭터가 다시 안 뜸헤르메스는 세션의 "첫 메시지"에만 위치 정보를 보내는데, 그 정보가 메모리에만 있던 서버가 재시작되며 소실모든 이벤트 앞에 위치 정보를 매번 재전송하도록 변경(이미 아는 세션이면 안전하게 무시됨)
캐릭터 위 이름표가 "Coding"처럼 나와 클로드/헤르메스 구분이 안 됨표시되던 값이 프로바이더 이름이 아니라 프로젝트 폴더명 축약형이었음서버·웹뷰 전 구간에 providerLabel을 새로 배선해 "Claude Code"/"Hermes" 태그를 캐릭터 위에 추가
외장 모니터를 뗐다 붙였다 하면 플로팅 창이 화면에 안 보임저장된 창 위치가 이전 모니터 배치 기준이라 지금 화면 밖으로 벗어남저장된 위치 값을 초기화하고 기본 위치(주 화면 우측 하단)로 재실행

느낀 점 / 다음에 할 일

오픈소스 문서의 "provider-agnostic"이라는 표현을 그대로 믿지 않고 실제 코드 흐름을 끝까지 따라가 본 게 이번 작업에서 제일 값졌다. 덕분에 겉보기 기능 추가가 아니라 런타임 레벨의 진짜 다중 프로바이더 지원을 만들 수 있었다. 다음엔 캐릭터만 투명 배경으로 떠다니는 진짜 데스크톱 펫 형태나, 외장 모니터 변경을 자동 감지해서 창 위치를 스스로 복구하는 기능을 붙여볼 생각이다.

댓글