본문으로 건너뛰기
뒤로가기

[LLM Workbench] Hooklusion: 에이전트 상태를 작은 신호로 보기

TL;DR — 에이전트에게 작업을 맡길 때 사용자는 결과뿐 아니라 현재 상태도 알고 싶어 합니다. Hooklusion은 Claude Code / Codex hook event를 작은 desktop character animation으로 바꿔, 터미널 로그를 계속 보지 않아도 prompt, thinking, tool, done 상태를 파악하게 만든 실험입니다.

Table of contents

Open Table of contents

들어가며

LLM 에이전트에게 일을 맡겨도 작업 상태가 보이지 않으면 사용자는 계속 터미널을 확인하게 됩니다. 이 글은 hook event를 이용해 에이전트 상태를 시각적 신호로 바꾸는 Hooklusion의 구조를 정리합니다.

이 글에서 다루는 내용:

사전 지식: Claude Code 또는 Codex CLI의 hook 개념, Electron desktop app의 기본 구조를 전제로 합니다.


1. 문제: 상태가 보이지 않으면 계속 확인하게 됩니다

LLM 에이전트에게 작업을 맡길 때 불편했던 점은 결과를 기다리는 시간 자체가 아니었습니다. 지금 입력을 받았는지, 도구를 사용 중인지, 작업이 끝났는지 알기 어려운 점이 더 컸습니다.

터미널 로그를 계속 확인하면 에이전트에게 일을 맡긴 의미가 줄어듭니다. 사용자는 작업을 위임했지만, 동시에 작업 상태를 감시하게 됩니다.

Hooklusion은 이 피로를 줄이기 위해 만든 desktop utility입니다. 목표는 에이전트의 모든 작업 내용을 보여주는 것이 아니라, 지금 상태를 작은 시각적 신호로 알려주는 것입니다.


2. 방향: 기존 CLI workflow는 유지합니다

Hooklusion은 Claude Code / Codex CLI의 작업 흐름을 대체하지 않습니다. 사용자는 기존처럼 CLI에서 작업하고, Hooklusion은 프로젝트에 설치된 local hook을 통해 event만 수신합니다.

flowchart TD
    A["Claude Code / Codex CLI"] -->|"hook event"| B["Project Local Hook"]
    B -->|"POST /event"| C["Hooklusion Local Server"]
    C -->|"raw event log"| D["events.jsonl"]
    D -->|"새 라인 확인"| E["Event Normalizer"]
    E --> F["Character State Machine"]
    F --> G["Desktop Character Animation"]

hook config는 Claude / Codex 설정에 local server로 event를 보내는 명령을 추가하는 방식입니다. 기존 hook을 보존하면서 marker 기반으로 설치 / 제거할 수 있도록 구성했습니다.

초기 구현에서는 events.jsonl에 raw event를 남기고, app이 마지막으로 읽은 위치 이후의 새 라인을 확인해 상태를 갱신했습니다. 이 방식은 단순하고, app을 재시작해도 raw log를 replay할 수 있으며, debugging에도 유용합니다.


3. 정규화: provider event를 공통 상태로 바꿉니다

Claude Code와 Codex는 hook payload 형태가 다릅니다. Hooklusion은 provider별 normalizer를 두고, raw event를 공통 CharacterEvent로 바꿉니다. CharacterEventprovider, sessionId, turnId, event, canonicalStateHint, providerState 필드를 가집니다.

flowchart TD
    A["Raw Hook Event"] --> N1["Claude normalizer"]
    A --> N2["Codex normalizer"]
    N1 --> C["CharacterEvent"]
    N2 --> C

대표적인 mapping은 다음과 같습니다.

Hook EventCharacter State의미
SessionStartsession_start세션 시작
UserPromptSubmitprompt_received사용자 입력 수신
PreToolUsetool_active도구 사용 시작
PostToolUsethinking도구 사용 후 다시 사고 중
Stopdone작업 완료

도구 사용 event는 가능한 경우 더 세부적인 providerState를 붙입니다. Codex의 Bash 명령은 패턴 기반으로 build, test, git 작업 등을 추정하고, non-Bash tool은 tool name 기반으로 tool:read, tool:search, tool:build, tool:test, tool:vcs_read 같은 상태를 붙입니다.

이렇게 provider별 event를 그대로 노출하지 않고 작은 공통 상태 모델로 압축하면, UI는 특정 provider 구현에 덜 의존하게 됩니다.


4. 상태 관리: session과 turn을 분리합니다

Hooklusion은 단순히 마지막 event 하나만 보여주지 않습니다. session / turn 단위로 상태를 관리합니다.

Character State Machine

sessionId
  |
  +-- activeTurnId
  +-- currentState
  +-- providerState
  +-- timer / transition control

이렇게 나눈 이유는 여러 session이나 여러 turn의 event가 섞일 수 있기 때문입니다. 예를 들어 이전 turn의 PostToolUse event가 늦게 도착하면, 이미 새로운 prompt가 시작된 화면을 과거 상태로 되돌릴 수 있습니다.

Hooklusion은 다음 기준으로 event를 처리합니다.

flowchart LR
    A["Incoming Event"] --> B["Session Registry"]
    B --> C["State Machine"]
    C --> D["Renderer"]

이 구조 덕분에 Hooklusion은 raw log viewer가 아니라, provider event를 사용자가 이해하기 쉬운 상태 신호로 바꾸는 도구가 됩니다.


5. Animation Studio: event와 연출 사이를 조정합니다

hook event는 상태 변화의 기준점으로는 유용하지만, event timing에만 의존하면 애니메이션이 부자연스럽게 끊기거나 너무 빨리 전환될 수 있습니다.

그래서 Hooklusion에는 상태별 animation을 간단히 조정할 수 있는 Animation Studio를 추가했습니다. 복잡한 제작 툴이 아니라, hook event와 실제 시각 연출 사이의 간격을 조정하기 위한 보조 도구입니다.

Animation Studio에서 조정하는 항목은 다음과 같습니다.

핵심은 “event를 받았다”에서 끝나지 않는 것입니다. 사람이 보기 편한 상태 표현이 되려면, 어떤 animation으로 보여줄지, 얼마나 유지할지, 다음 상태로 어떻게 넘어갈지도 함께 조정해야 합니다.


정리하며

핵심 요약:

참고 자료


이 게시물은 학습한 내용을 바탕으로 초안을 작성한 뒤, LLM의 도움을 받아 내용을 검수하고 다듬어 완성되었습니다.


공유하기:

이전 글
[LLM Workbench] btwin Orchestration: 에이전트 작업 흐름을 작게 제어하기
다음 글
[Emberlit] Quaternion 곱 순서: 같은 회전이 왼쪽·오른쪽에 따라 월드·로컬이 되는 이유