엉클 밥과 에이전트 Part 4: ub-mode
이 글은 Claude Opus 5.5 를 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.
No coverage data for gildedrose/gildedrose.go; its sites are uncovered. Pass --no-coverage to run them anyway.
Codex 가 mutator 를 처음 돌렸을 때 받은 첫 줄입니다. 그 아래로 돌연변이 후보 15개가 모두 “커버되지 않음” 으로 집계됐고, 명령은 exit 0 으로 끝났습니다. 3편에서 제가 직접 따라가 원인을 찾았던 바로 그 버그입니다. 그때는 이걸 모르고 검사 스크립트에 넣었다면 아무것도 검사하지 않는 관문이 됐을 거라고 썼습니다. 이번에는 아무도 알려 주지 않았는데 Codex 가 이 한 줄을 읽고 --no-coverage 를 붙여 다시 돌렸고, 돌연변이 15개를 모두 죽인 걸 확인한 뒤에야 다음 일로 넘어갔습니다. Claude Code 도 같은 안내문을 보고 같은 선택을 했습니다.
두 에이전트에게 준 건 엉클 밥이 사흘 전에 공개한 152줄짜리 skill 파일 하나였습니다.
10월 25일#
그날 엉클 밥은 X 에 글 두 개를 올렸습니다. 하나는 이 문장입니다. “I am transitioning away from using CLI agents for development. On my last project I transitioned to using grokbots.” 다른 하나는 새 저장소 ub-mode 를 소개하며 쓴 “I composed this skill and have had pretty good luck with it. My grokbots use it when writing code.” 입니다.
방향 자체는 새롭지 않습니다. 9월 11일에 그는 에이전트를 묶어 두는 하네스를 몇 주 다듬는 사이에 에이전트가 훨씬 좋아졌다고 썼고, 10월 16일 Agentic Discipline 7화 소개문에서는 swarm-forge 하네스에서 물러나 에이전트 하나를 규율 있게 쓰는 방법을 보자고 했습니다. ub-mode 는 그 “규율 있게” 의 내용을 공개 저장소에 글로 내놓은 것입니다. 저장소는 그날 16시 무렵(UTC) 4분 사이에 커밋 네 개로 만들어졌고, 사흘 만인 10월 28일에 별 2,867개를 받았습니다.
152줄의 내용#
SKILL.md 는 740단어 남짓입니다. swarm-forge 의 역할 하나가 읽는 헌법이 2천 단어를 넘었던 것과 비교하면 짧고, 3편에서 제가 쓴 60단어짜리 규칙보다는 훨씬 깁니다. README 는 이 파일이 @poteto 의 규칙집(poteto-mode, pstack) 일부를 줄여 그의 검사 도구와 짝지은 것이라고 밝힙니다.
뼈대는 오래된 격언 그대로입니다. “First Make it Work”, “Then Make it Right”, 그리고 “Practice”. 첫 단계에는 TDD 와 함께 조금 낯선 항목들이 들어 있습니다. 새 요구사항을 옛 설계에 덧대지 말고 처음부터 있었다면 무엇을 지었을지 생각하라는 “Redesign From First Principles”, 무언가를 더하기 전에 복잡도부터 빼라는 “Subtract Before You Add”, 같은 전제를 공유하는 수정이 같은 관문에서 두 번 실패하면 그 전제를 한 문장으로 적어 보라는 “Attack the Premise” 같은 것들입니다. 두 번째 단계에서 crapper(CRAP 10 미만), dryer(유사도 0.8 이상 제거), mutator 가 나옵니다. mutator 항목은 네 줄뿐입니다. “Use the mutator tool”, “Cover the uncovered.”, “Kill the survivors.”, “Delete dead code.”
가장 엉클 밥다운 문장은 테스트 항목에 있었습니다. “If the test would still pass when every function returned nothing, throw it out.” 마지막 Practice 단계는 모든 행동과 이유를 기록해 끝에 보고하고, 작은 커밋으로 자주 커밋하고, 끝나면 main 에 push 하라고 합니다.
저장소에는 라이선스가 없습니다. 함께 쓰는 검사 도구 세 개는 0BSD 지만 skill 본문은 그렇지 않아서, 회사 저장소에 그대로 복사해 넣기는 애매합니다. 10월 27일에 올라온 이슈 2번은 두 규칙을 짚었습니다. 사람이 diff 를 보지 않은 채 main 에 push 하라는 규칙과, 지워도 안전한 것을 에이전트가 판단해 디스크를 정리하라는 규칙입니다. 앞의 것은 브랜치에 push 하고 PR 을 열게, 뒤의 것은 지울 목록을 제안하고 확인을 기다리게 바꾸자는 제안이었습니다.
같은 과제에 넣어 보면#
과제와 측정은 3편과 같습니다. Go 로 된 Gilded Rose 카타에 Conjured 아이템을 추가하는 일이고, 요청 문장도 같습니다. 달라진 건 맨 앞에 skill 호출을 붙인 것뿐입니다(Claude Code 는 /ub-mode, Codex 는 $ub-mode). skill 은 Claude Code 는 .claude/skills/ub-mode/, Codex 는 .agents/skills/ub-mode/ 에 넣었고, 엉클 밥의 환경처럼 세 도구를 PATH 에 올려 두었습니다. 조건은 둘입니다. skill 만 둔 경우, 그리고 3편의 “게이트만” 조건에 skill 을 더한 경우입니다. 뒤의 것은 에이전트가 끝내려 할 때마다 Stop 훅이 gauntlet.sh(단위 테스트, CRAP 8 이하, 살아남은 돌연변이 0, 중복 0)를 돌려 실패하면 끝내지 못하게 합니다.
| 조건 | 도구 | 시간 | 입력 토큰 | 함수 / 코드 줄 | 최대 복잡도 | 뮤테이션 효율 |
|---|---|---|---|---|---|---|
| ub-mode | Claude Code | 313초 | 181만 | 8 / 90 | 5 | 79% |
| ub-mode | Codex | 248초 | 34만 | 5 / 58 | 5 | 100% |
| ub-mode + 게이트 | Claude Code | 203초 | 68만 | 11 / 73 | 5 | 100% |
| ub-mode + 게이트 | Codex | 350초 | 47만 | 5 / 57 | 5 | 100% |
| 규칙 없음 (3편) | Claude Code | 94초 | 36만 | 7 / 79 | 5 | 78% |
| 규칙 없음 (3편) | Codex | 118초 | 14만 | 1 / 67 | 23 | 98% |
| 짧은 규칙 + 게이트 (3편) | Claude Code | 118초 | 49만 | 7 / 71 | 5 | 100% |
| 짧은 규칙 + 게이트 (3편) | Codex | 114초 | 17만 | 8 / 67 | 4 | 100% |
네 실행 모두 숨은 인수 테스트를 통과했습니다. 게이트를 건 두 실행은 첫 번째 훅 검사에서 바로 통과했습니다.
도구를 돌렸고, 안내문을 읽었다#
3편에서는 도구가 있다는 사실을 규칙 파일이나 검사 스크립트로 알려 줘야 에이전트가 썼습니다. 이번에는 아무도 도구를 알려 주지 않았는데, 둘 다 skill 을 읽자마자 세 도구가 설치돼 있는지부터 찾고 도움말을 읽었습니다. 도움말을 뺀 실행 횟수로 Claude Code 는 crapper 4번, dryer 2번, mutator 9번, Codex 는 각각 2번, 1번, 2번이었습니다. 훅도 규칙 파일도 없이 skill 의 “Use the crapper tool” 한 줄이 이만큼을 시켰습니다.
더 인상 깊었던 건 그 전에 한 일입니다. 네 실행 모두 코드를 건드리기 전에 기존 동작부터 붙잡았습니다. Claude Code 는 원래 UpdateQuality 를 따로 떼어 둔 사본과 새 코드를 45,864개 입력으로 비교했고, 게이트가 있는 실행에서는 7,225개 경우의 결과를 골든 파일로 녹화한 뒤 시작했습니다. Codex 는 원본과 388,440번의 갱신 결과를 대조했습니다. Claude Code 는 3편에서도 규칙을 받은 실행에서 기존 출력을 녹화해 두고 비교한 적이 있지만, Codex 가 원본과 대조한 건 이번이 처음입니다. skill 의 Refactoring 항목 첫 줄이 “Pin what the code does.” 입니다.
구조도 바뀌었습니다. 3편에서 규칙 없는 Codex 는 원래의 if 덩어리에 Conjured 분기만 끼워 복잡도 23 짜리 함수를 남겼습니다. 이번에는 네 번 모두 아이템 종류별 규칙을 작은 함수로 나눴고, 최대 복잡도는 모두 5였습니다. Claude Code 는 구조부터 다시 짠 뒤 Conjured 를 넣었고, skill 만 둔 Codex 는 Conjured 를 먼저 최소한으로 넣었다가 crapper 가 원래 함수의 CRAP 19 를 지적하자 그때 나눴습니다. 실패하는 Conjured 테스트를 먼저 쓰고 “예상대로 일반 아이템 속도로 떨어져서 실패한다” 를 확인한 기록도 네 실행에 다 남아 있습니다.
다만 이건 skill 의 문장이 지켜졌다는 이야기이지, 지켜진다는 보증은 아닙니다. 3편에서 1,307단어짜리 긴 규칙도 꽤 잘 지켜졌습니다. 같은 실험을 다시 돌리면 어느 줄이 빠질지는 모릅니다.
죽지 않는 돌연변이#
Claude Code 가 skill 만으로 끝낸 실행은 돌연변이 4개를 남겼습니다. 품질 값을 0과 50 사이에 묶는 두 함수 raise, lower 의 비교 연산자를 바꾼 돌연변이인데, 에이전트는 이것들이 결과를 바꾸지 못하는 등가 돌연변이라 어떤 테스트로도 잡을 수 없다고 보고했습니다. 코드를 직접 따라가 보니 맞는 말이었습니다. quality >= 50 을 quality > 50 으로 바꿔도 50 인 경우는 다음 줄이 똑같이 50 을 돌려줍니다. 에이전트는 내장 min/max 를 쓰면 이 돌연변이가 사라지지만 go.mod 의 Go 버전을 1.18 에서 1.21 로 올려야 해서 하지 않았다고 덧붙였습니다. “Kill the survivors.” 라는 문장을 그대로 따르지 않고 판단해서 멈춘 셈입니다. 별도 측정 도구인 gremlins 가 이 결과물에서 효율 79% 를 낸 것도 같은 4개 때문입니다.
게이트를 건 실행에서는 같은 Claude 가 반대로 갔습니다. 살아남은 돌연변이가 0개여야 통과하는 관문 앞에서, 손으로 짠 비교 함수를 두면 등가 돌연변이가 남는다는 이유로 go.mod 를 1.21 로 올리고 내장 함수를 썼습니다. 보고서에는 1.18 을 유지해야 하면 알려 달라는 단서를 달았습니다. 요청 범위 밖의 변경이고, 사람이 봤다면 한 번은 물어봤을 결정입니다. 판단을 막은 건 skill 이 아니라 게이트였습니다. 3편에서 문턱이 코드의 모양을 바꾼다고 썼는데, 이번에는 문턱이 프로젝트 설정까지 바꿨습니다.
Practice 가 만난 환경#
마지막 단계의 규칙들은 환경에 따라 결과가 갈렸습니다. Claude Code 는 두 실행 모두 커밋 세 개를 남겼습니다. 기존 동작을 고정하는 테스트, 구조 변경, Conjured 추가 순서이고, 메시지마다 왜 했는지와 무엇이 바뀌었는지, 어떻게 확인했는지를 적었습니다. Codex 는 sandbox 가 .git 을 읽기 전용으로 두는 바람에 커밋을 하지 못했고, 대신 WORK_LOG.md 라는 파일에 단계별 기록을 남겼습니다. 원격 저장소가 없어서 넷 모두 push 는 하지 못했고, 넷 다 그 사실을 보고했습니다.
원격이 있었다면 어땠을지 생각하면 이슈 2번의 지적이 무겁게 읽힙니다. Claude Code 의 허용 목록에 git * 를 넣어 둔 상태였으니, 원격만 있었다면 사람이 diff 를 보기 전에 main 에 push 했을 가능성이 높습니다. 엉클 밥의 방식에서는 그게 맞습니다. 그는 코드를 읽지 않고 관문을 믿기 때문입니다. 팀 저장소라면 이 줄은 지우고 쓰는 게 맞다고 봅니다.
값#
skill 만 둔 Claude Code 실행이 이 시리즈의 단일 에이전트 실행 가운데 가장 비쌌습니다. 입력 토큰 181만, 정가 환산 1.36달러로, 3편의 긴 규칙 조건(108만)보다도 많았습니다. 도구 세 개의 사용법을 스스로 알아내고, 기존 동작을 비교하는 임시 테스트를 만들었다 지우고, mutator 를 아홉 번 돌린 값입니다. 같은 skill 에 게이트를 더하자 68만 토큰, 0.78달러로 떨어졌습니다. 에이전트가 저장소를 둘러보다 gauntlet.sh 를 찾아내고는 도구 세 개를 따로 부르는 대신 그 스크립트 하나로 검사를 끝냈기 때문입니다. Codex 는 두 조건 모두 34만~47만 토큰으로, 3편의 짧은 규칙과 게이트 조건(17만)의 두세 배였습니다.
결과물의 품질로 보면 3편의 짧은 규칙과 게이트 조건과 큰 차이가 없습니다. 차이는 과정에 있었습니다. 기존 동작을 먼저 고정하고, 구조를 먼저 고치고, 기록을 남기는 습관은 짧은 규칙에는 없던 것이고, 이번 과제처럼 작은 일에서는 그 습관이 토큰으로 계산됐습니다.
grokbot 은 무엇인가#
엉클 밥은 grokbot 이 정확히 무엇인지 설명하지 않았습니다. 정황으로 보면 xAI 가 8월 11일 베타로 낸 Grok Bot 일 가능성이 높습니다. 10월 7일에 그는 “grokbots are just plain amazing. I’m getting all my bills and finances organized to a level I never thought possible.” 이라고 썼는데, 청구서와 재무를 정리하는 건 코딩 에이전트보다 Grok Bot 같은 범용 비서에 어울리는 일입니다. ub-mode README 가 설치 경로로 홈 디렉터리의 .grok/skills 와 .cursor/skills 를 함께 드는 것도 같은 쪽을 가리킵니다.
공식 문서가 설명하는 Grok Bot 은 이름 붙인 Bot 여러 개가 클라우드 컴퓨터 한 대(브라우저, 터미널, 파일)를 함께 쓰는 구조입니다. 노트북을 닫아도 일이 계속되고, 데스크톱과 휴대폰 앱, X Chat, Slack 에서 말을 걸 수 있습니다. Bot 2~6개를 한 그룹 채팅에 넣거나 Bot 끼리 일을 넘기게 할 수도 있고, 정해진 시간이나 Slack·GitHub 같은 이벤트에 맞춰 일을 돌리는 routine 도 있습니다. 문서는 Bot 들이 컴퓨터와 로그인을 공유하니 Bot 을 나누는 걸 보안 경계로 쓰지 말라고 분명히 적어 둡니다. 플랜은 X 의 유료 구독(Premium 이상)이나 Cursor 유료 플랜에 묶여 있고, 사용량은 Grok·Cursor 와 같은 주간 한도에서 나갑니다.
코딩에 관해서는 공식 가이드의 문장이 흥미롭습니다. “Grok Bot is not writing the code.” Bot 은 Slack 이나 문서에서 맥락을 모아 프롬프트를 쓰고, 실제 구현은 Cursor 의 클라우드 에이전트에게 넘긴 뒤 결과를 받아 PR 을 엽니다. 모델은 고를 수 없습니다. FAQ 는 “there is no model picker.” 라고 하고, 어떤 모델이 쓰였는지도 보여 주지 않습니다. 자기 API 키를 연결하거나 로컬 모델을 쓰는 방법은 문서에 없습니다.
Discord 에 붙여 쓰는 봇과는 여기서 갈립니다. 대표적인 예인 OpenClaw 는 MIT 라이선스의 오픈소스이고, 내 컴퓨터에서 돌면서 Discord·Telegram·Slack·iMessage 같은 메신저로 말을 걸게 하고, Claude·Codex·로컬 모델을 플러그인처럼 바꿔 끼웁니다. 상태와 자격 증명도 내 장비에 남습니다. Grok Bot 은 그 반대편에 있습니다. 업체가 운영하는 컴퓨터에서 돌고, 메신저는 X Chat 과 Slack 정도이고, 공식 문서에 Discord 와 Telegram 은 나오지 않으며, 모델은 서비스가 고릅니다. 대신 설치할 것이 없습니다.
엉클 밥의 grokbot 이 ub-mode 를 어떻게 읽는지는 확인하지 못했습니다. Grok Bot 문서는 skill 을 모든 Bot 이 함께 쓰는 비공개 라이브러리로 설명할 뿐 파일 형식이나 경로를 말하지 않습니다. 홈 디렉터리의 .grok/skills 를 읽는다고 문서에 적힌 건 xAI 의 터미널 에이전트 Grok Build 쪽입니다. 저는 Grok Bot 을 써 보지 않았고, CLI 에이전트를 떠날 이유가 있는지도 아직 판단하지 못했습니다. 다만 하나는 분명해 보입니다. 엉클 밥이 CLI 를 떠나면서도 들고 간 건 하네스가 아니라 skill 한 장과 검사 도구 세 개였습니다.
따라 해 볼 때#
Claude Code 라면 SKILL.md 를 홈 디렉터리나 저장소의 .claude/skills/ub-mode/ 에 두고 /ub-mode 로 부릅니다. Codex 는 저장소의 .agents/skills/ 와 .codex/skills/ 를 모두 읽었고, $ub-mode 로 부르면 됩니다. 검사 도구는 각 저장소에서 받아 PATH 에 올려 둡니다. skill 은 도구 이름만 말하고 경로는 말하지 않으니, PATH 에 없으면 에이전트가 그 단계를 어떻게 처리할지 알 수 없습니다.
이번 결과로 보면 skill 은 습관을 주고, 게이트는 보증을 줍니다. 둘을 같이 쓰되, 3편에서 쓴 것처럼 게이트가 실패해야 할 때 실패하는지는 먼저 확인합니다. 이번 Go 저장소에서는 mutator 에 --no-coverage 를 붙이지 않으면 아무것도 검사하지 않은 채 exit 0 으로 끝났습니다. 이번 에이전트들은 안내문을 읽고 피해 갔지만, 스크립트는 안내문을 읽지 않습니다.
팀 저장소에 들인다면 Practice 의 두 줄은 고쳐 씁니다. main 에 push 하라는 줄은 브랜치에 push 하고 PR 을 열라는 줄로, 디스크를 정리하라는 줄은 지울 목록을 보고하라는 줄로 바꿉니다. 게이트를 건다면 등가 돌연변이를 어떻게 다룰지도 정해 둡니다. 0개를 강제하면 이번처럼 에이전트가 언어 버전을 올려서라도 맞추려 들 수 있으니, 의존성이나 설정 파일을 바꿀 때는 멈추고 묻게 하는 줄 하나가 필요해 보입니다. 라이선스가 없는 파일이라 회사 저장소에 넣을 때는 원문을 복사하기보다 링크하고 팀의 규칙으로 다시 쓰는 편이 안전합니다.
자료에 대해#
엉클 밥의 10월 25일 게시물 두 개는 X 페이지를 직접 열지 못해 검색 결과에 나온 본문으로 옮겼고, 첫 게시물이 실제로 있다는 것은 블로그 주인이 직접 확인했습니다. 그 스레드의 댓글은 찾지 못했습니다. 같은 날 elvis(@omarsar0)가 CLI 에이전트는 더 이상 최선의 인터페이스가 아니라는 글을 올렸는데, 게시물 ID 로 계산하면 엉클 밥의 글보다 5시간 44분 늦어서 엉클 밥이 그 글에 답한 것은 아닙니다. grokbot 이 Grok Bot 이라는 건 위에 적은 정황에 기댄 추정입니다. Grok Bot 에 관한 내용은 docs.x.ai 와 x.ai 의 공식 문서를 10월 28일에 읽은 것이고 가격은 공식 문서에서 확인하지 못했습니다. 실험은 10월 28일 제 노트북(macOS)에서 Claude Code 2.1.311(Claude Opus 5.5)과 Codex CLI 0.160.0(gpt-6-astra, reasoning high)으로 조건마다 한 번씩, 실행마다 10분 상한을 두고 돌렸습니다. Codex 의 skill 만 둔 첫 실행은 도중에 “Selected model is at capacity” 오류로 끊겨 같은 조건으로 다시 돌린 결과를 실었습니다. 두 도구 모두 제 전역 설정이 실린 상태였고, 3편의 수치는 10월 24일에 Claude Code 2.1.287 로 잰 것이라 버전이 다릅니다. 입력 토큰은 캐시에서 읽은 토큰을 포함하고, 정가 환산은 Claude Code 가 보고한 값입니다. 도구 실행 횟수는 세션 기록에서 명령을 세어 낸 값입니다.
| 편 | 주제 |
|---|---|
| Part 1 | 코드를 읽지 않는 이유 |
| Part 2 | swarm-forge |
| Part 3 | 규칙 파일 대신 게이트 |
| Part 4 (이 글) | ub-mode |
References#
최신 자료 (2026)
- Robert C. Martin, X 게시물 2114402750851330268 (2026-10-25) · 2107939810975314068 (2026-10-07) · 2098432570887217520 (2026-09-11) · 2111161176831021418 (2026-10-16) [본인 발언]
- Robert C. Martin, ub-mode (2026-10-25 생성, 라이선스 없음, 조회 2026-10-28) · 이슈 #2 (2026-10-27) [본인 저장소·이용자 제안]
- Robert C. Martin, crapper
6fd92c4· mutatora5a0cb8· dryer66ff6d2(0BSD, 조회 2026-10-28) [본인 저장소] - Justin Martin · Robert C. Martin, 「Clean AI: Agentic Discipline, Episode 7」, cleancoders.com (2026-10-16) [본인 영상 소개]
- xAI, 「Introducing Grok Bot」 (2026-08-11) · 「Grok Bot 101」 (2026-09-11) [공식 발표·가이드]
- xAI, Grok Bot 문서 FAQ · Chat and collaboration · Skills, routines, and automations · The X Subscription: Grok Bot · Grok Build Skills, plugins, and marketplaces (조회 2026-10-28) [문서]
- OpenClaw, openclaw/openclaw README (MIT, 조회 2026-10-28) [저장소]
- elvis (@omarsar0), X 게시물 2114489246434173180 (2026-10-25) [제3자 발언]
- 직접 실험: Claude Code 2.1.311(Claude Opus 5.5)·Codex CLI 0.160.0(gpt-6-astra), Gilded Rose Go, ub-mode 두 조건 × 두 도구, 숨은 인수 테스트·gocyclo 0.6.0·gremlins 0.6.0 (2026-10-28)
비교·배경 자료
- Emily Bache, GildedRose-Refactoring-Kata Go 판 (MIT) [저장소]