Zeude로 본 AI CLI 운영 모델
목차

처음에는 Zeude를 “Claude Code에 OpenTelemetry를 붙인 dashboard” 정도로 봤다. 실행해보면 웹 화면이 있고, ClickHouse가 있고, OTel Collector가 있고, 각 CLI를 감싸는 wrapper가 있다. 겉으로만 보면 익숙한 observability stack이다.
그런데 실제로 생각이 바뀐 지점은 dashboard가 아니었다. Codex 로그를 확인하던 순간이었다.
~/.codex/config.toml에 OTEL endpoint를 직접 적고 원본 codex를 실행하자 로그는 ClickHouse에 들어왔다. 여기까지만 보면 “Codex는 이미 OTEL을 지원하니 wrapper가 꼭 필요한가?”라는 생각이 든다. 그런데 row를 들여다보니 zeude.user.id가 없었다. Codex가 보낸 로그는 있었지만, Zeude가 관리하는 사용자로 해석되지는 않았다.
다시 Zeude wrapper를 거쳐 codex를 실행하자 같은 종류의 OTEL 로그에 zeude.user.id, zeude.user.email, zeude.team이 붙었다. 그때 질문이 바뀌었다.
로그를 받을 수 있느냐가 아니었다. 이 실행을 누구의, 어떤 팀의, 어떤 관리 경로의 사용으로 해석할 수 있느냐가 문제였다.
그 순간부터 Zeude는 단순 telemetry 수집기가 아니라 AI CLI 실행 경로를 관리하는 운영 모델로 보였다.
Zeude가 나온 배경
Zeude의 원본은 zep-us/zeude다. README는 이 프로젝트를 Claude Code를 위한 enterprise monitoring, team harness로 설명한다. 사용량 그래프만 보여주는 도구라기보다, Claude Code 사용 현황을 측정하고, skill/MCP/hook 설정을 중앙에서 배포하며, 팀 단위로 사용 패턴을 관리하려는 도구에 가깝다.
공개 당시의 맥락은 Reddit 글에 남아 있다. ZEP 팀은 Claude Code와 custom skill을 배포했지만 실제 skill 사용률이 6% 근처에 머물렀고, 이 문제를 “Intention-Action Gap”이라고 불렀다. 그래서 사용 현황을 측정하고, skill/hook/MCP 설정을 자동 배포하고, prompt 시점에 적절한 skill을 제안하는 내부 시스템을 만들었다. 결과적으로 skill 사용률이 2주 정도에 6%에서 18%로 늘었고, 이 시스템을 Zeude로 공개했다고 설명했다. (Reddit 글)
이재규 님의 공개 LinkedIn 포스트도 같은 맥락을 설명한다. 그는 ZEP의 Zeude 공개 글을 작성했고, GitHub README에도 enterprise sales contact로 [email protected]가 남아 있다. 글에서 그는 Zeude를 오픈소스로 내놓은 이유를 이렇게 풀었다. AI 도구 도입에서 막히는 지점은 도구 자체보다 팀이 배운 사용법을 서로에게 전달하는 구조였고, 여러 팀이 같은 시행착오를 반복하는 비용을 줄이기 위해 ZEP에서 쓰던 운영 도구를 공개했다는 것이다. (LinkedIn 글)
이 배경을 알고 나면 Zeude의 구조도 조금 다르게 읽힌다. 목적은 “로그 수집”이 아니라 “팀이 실제로 AI CLI를 쓰게 만들고, 그 사용을 해석 가능한 형태로 남기는 것”이다.
Wrapper가 하는 일
Zeude의 기본 방식은 원본 CLI 이름을 wrapper가 먼저 받는 구조다. 사용자는 평소처럼 claude, codex, copilot을 실행한다. 다만 PATH 앞쪽에 같은 이름의 Zeude wrapper가 있고, wrapper는 원본 binary 경로를 기억해두었다가 필요한 설정을 주입한 뒤 원본 CLI를 실행한다.
여기서 wrapper는 shell alias나 단순 shell script가 아니다. Zeude 소스에는 cmd/claude, cmd/codex, cmd/copilot, cmd/opencode처럼 CLI별 Go entrypoint가 있고, release 과정에서 이것들이 OS/architecture별 실행 파일로 컴파일된다. 설치 과정은 이 Go binary를 사용자의 실행 경로 앞쪽에 두고, 원본 CLI의 실제 위치는 ~/.zeude/real_*_path 같은 파일에 남긴다.
그래서 구조를 정확히 말하면 “원본을 고친다”가 아니라 “같은 명령 이름으로 먼저 잡히는 작은 Go 프로그램을 앞에 둔다”에 가깝다. 이 Go wrapper가 Zeude credentials와 dashboard config를 읽고, identity와 OTEL 설정을 붙인 다음, 저장해둔 원본 binary로 제어를 넘긴다.
이 방식은 원본 프로그램을 수정하지 않는다. 하지만 실행 경로는 바꾼다. claude와 codex처럼 원본이 telemetry 경로를 갖고 있는 도구는 wrapper가 welcome message와 정책을 받은 뒤 syscall.Exec로 원본 binary에 갈아탄다. 반대로 copilot과 opencode처럼 wrapper가 세션 파일이나 SQLite를 나중에 읽어야 하는 경우에는 parent wrapper가 남아 있고, 원본 CLI를 child process로 실행한다. 이때 child의 stdin, stdout, stderr는 터미널에 직접 연결된다.
그래서 Zeude wrapper는 모든 도구에서 같은 모양으로 동작하지 않는다. 공통점은 원본 CLI 앞에서 실행 경로를 잡는다는 것이고, 차이는 원본으로 완전히 갈아타는지, 아니면 parent로 남아 수집 작업을 계속하는지에 있다. 그래서 장점과 불편함이 같이 온다.
장점은 명확하다. 개발자는 기존 명령을 그대로 쓰고, Zeude는 그 경로에서 identity와 설정을 붙일 수 있다. 별도 교육이나 매번 수동 설정을 요구하지 않아도 된다.
불편함도 명확하다. 문제가 생기면 지금 실행한 claude가 원본인지 wrapper인지부터 확인해야 한다. 원본 CLI의 인자 처리, 업데이트 방식, 로컬 파일 구조가 바뀌면 wrapper도 영향을 받는다. 투명하게 감싸는 구조일수록 원본 프로그램에 대한 의존성은 커진다.
도구마다 관측면이 다르다
Claude Code와 Codex는 비교적 깔끔하다. 둘 다 원본 도구가 telemetry를 내보내는 경로를 갖고 있고, Zeude wrapper는 그 경로를 켜거나 설정을 남기는 역할을 한다.
Copilot과 OpenCode는 다르다. Zeude가 원하는 형태의 token usage를 native OTEL로 안정적으로 주지 않는다고 보고, wrapper가 로컬에 남은 흔적을 읽어 직접 OTLP log를 만든다.
여기서 중요한 차이가 하나 있다. Claude와 Codex는 원본 CLI가 telemetry를 보내고, Zeude는 그 telemetry가 조직의 사용자 모델 안에서 해석되도록 환경을 깔아준다. 반면 Copilot과 OpenCode는 Zeude wrapper가 세션 파일이나 SQLite를 읽어 별도의 usage event를 만들어야 한다.
이 둘은 안정성이 다르다. 공식 OTEL 경로는 비교적 예측 가능하다. 반면 events.jsonl이나 SQLite schema는 원본 도구의 내부 구현에 더 가깝다. Copilot의 session event 포맷이나 OpenCode DB schema가 바뀌면 수집이 깨질 수 있다. 그래서 이 방식은 “통신”이라기보다 local artifact scraping에 가깝다.
ClickHouse는 로그 저장소라기보다 분석 저장소였다
Zeude는 OTel Collector가 받은 log signal을 ClickHouse에 넣는다. 처음에는 이 선택이 조금 어색했다. OTEL이면 보통 Loki, Tempo, Mimir 같은 구성을 먼저 떠올리기 때문이다.
그런데 Zeude가 저장하는 데이터는 일반적인 운영 로그와 다르다. prompt, session id, model, input token, output token, cache token, cost, user, team, project path, source가 한 이벤트 안에 들어간다.
이건 log이면서 동시에 분석 이벤트다. “지난 7일 동안 팀별 비용”, “프로젝트별 Codex 사용량”, “source별 token usage”, “prompt 길이와 retry pattern” 같은 질문을 던지고 싶어진다. 이런 wide event 분석은 Loki보다 ClickHouse가 자연스럽다.
다만 여러 저장소로 동시에 흘리거나 일시 장애를 버텨야 한다면 staging 계층은 따로 보는 편이 낫다. Kafka, Redpanda, S3, Collector persistent queue가 맡을 일은 buffer와 replay이고, ClickHouse가 맡을 일은 prompt, token, cost를 빠르게 분석하는 것이다.
이 기준으로 보면 Zeude가 ClickHouse를 쓰는 이유는 납득된다. Zeude가 보고 싶은 것은 단순 로그 검색이 아니라 팀별 사용량, 비용, 모델, prompt pattern이다. 운영 로그 저장소라기보다 AI CLI 사용 분석 warehouse에 가깝다.
Wrapper는 고품질 신호를 만들고, proxy는 우회를 본다
Zeude wrapper만으로 중앙 통제가 될까. 여기서는 생각이 조금 갈린다.
Wrapper는 협조적인 개발 환경에서는 좋은 수단이다. 사용자 identity를 붙이고, 팀별 config를 내려주고, prompt/token/cost를 ClickHouse에 넣는다. 이 신호는 품질이 높다. 단순 네트워크 로그보다 “누가 어떤 프로젝트에서 어떤 CLI를 어떤 비용으로 썼는지”에 훨씬 가깝다.
하지만 조금 아는 사용자는 원본 codex나 copilot을 직접 실행할 수 있다. PATH를 바꿀 수도 있고, ~/.zeude 설정을 지울 수도 있다. wrapper는 실행 경로를 관리하지만, 그 자체가 강제 통제 장치는 아니다.
여기서 transparent proxy 같은 네트워크 레벨 관측이 필요해진다. proxy는 prompt/token/cost를 예쁘게 알기 어렵지만, wrapper를 우회한 네트워크 사용을 볼 수 있다. 반대로 Zeude는 의미 있는 사용량 이벤트를 만들지만, wrapper 밖에서 발생한 트래픽은 모른다.
현실적인 운영은 둘을 대조하는 쪽이다.
| 대조 대상 | 관찰 | 해석 |
|---|---|---|
| Proxy 로그 | user A 단말에서 GitHub Copilot endpoint traffic 발생 | AI CLI 사용 흔적은 있음 |
| Zeude 로그 | user A의 Zeude telemetry 없음 | wrapper를 거치지 않았을 가능성 |
| 운영 판단 | 두 신호가 불일치 | 원본 CLI 직접 실행, wrapper 미설치, 비관리 경로 사용 가능성 |
반대로 Zeude에는 codex telemetry가 있는데 proxy에는 관련 AI endpoint가 없다면, 네트워크 레벨 관측 경로에서 빠진 구간이 있을 수 있다. 둘은 대체재가 아니라 서로를 검증하는 관계다.
운영 모델로 가져가려면
Zeude를 보면서 좋았던 점은 AI CLI 사용을 측정 가능한 운영 대상으로 끌어냈다는 것이다. Claude Code, Codex, Copilot, OpenCode처럼 서로 다른 CLI를 한 가지 방식으로 억지로 맞추지 않고, 각 도구가 실제로 남기는 신호를 따라 수집면을 다르게 잡았다.
그 과정에서 wrapper 방식의 장점도 분명했다. 실행 경로를 먼저 잡으면 사용자 identity를 붙일 수 있고, 팀별 config를 내려줄 수 있고, token/cost/prompt 단위의 사용량을 중앙에서 볼 수 있다. AI CLI를 그냥 개인 도구로 방치하지 않고, 관리된 실행 경로 안으로 넣는 모델이다.
하지만 이 모델을 그대로 운영 표준으로 가져가려면 아쉬운 지점도 같이 봐야 한다. wrapper는 원본 CLI의 실행 방식과 업데이트 방식에 의존한다. Copilot이나 OpenCode처럼 local artifact를 읽는 방식은 events.jsonl이나 SQLite schema가 바뀌면 깨질 수 있다. 사용자가 원본 CLI를 직접 실행하면 wrapper 신호는 비어 있고, 이때는 transparent proxy 같은 네트워크 레벨 관측과 대조해야 한다.
저장 방식도 마찬가지다. ClickHouse는 prompt, token, cost, user, team 같은 wide event를 분석하기에는 좋다. 대신 장애 완충이나 재전송을 맡길 곳은 아니다. 그런 역할이 필요하면 Kafka, Redpanda, S3, Collector persistent queue 같은 staging 계층을 별도로 두고, 운영 로그와 trace, metric은 각자 맞는 저장소로 나누는 편이 자연스럽다.
그래서 Zeude는 완성된 정답이라기보다 좋은 출발점에 가깝다. AI CLI를 어떻게 측정할지, 어떻게 중앙에서 관리할지, wrapper를 어디까지 신뢰할지, network-level 관측과 어떻게 대조할지, prompt와 비용 데이터를 어디에 얼마나 보관할지를 생각하게 만든다.
결국 남는 질문은 하나다. “무슨 로그를 모을 것인가”가 아니라 “어떤 실행을 관리된 사용으로 인정하고, 그 밖의 사용을 어떻게 발견할 것인가.” Zeude를 분석하면서 내가 가져간 것은 이 질문이었다.