cerber 🐕
npm
CI
license
AI 코드 리뷰 코크핏. Claude가 로컬 아티팩트로 여러분의 풀 리퀘스트(pull requests)를 검토합니다. 여기에는 요약, 변경 사항에 대한 챕터별 설명, 초안 인라인 댓글, 그리고 신뢰도 점수와 함께하는 판결문이 포함됩니다. 여러분은 이를 로컬 웹 코크핏에서 읽고, 각 댓글을 유지하거나 다시 작성하거나 삭제한 다음, 동의할 때 'Send' 버튼을 누릅니다.
명시적으로 지시하지 않는 한 아무것도 GitHub에 도달하지 않습니다. 검토 과정은 100% 로컬이며 읽기 전용입니다. 세 가지 것만이 쓸 수 있습니다: 'Send' 버튼, 사용자가 직접 켜는 옵트인 데몬 자동 전송 기능, 그리고 다른 사람에게 리뷰를 넘기는 행위. 리뷰는 오직 여러분의 계정으로만 나갑니다. 왜냐하면 여러분이 그렇게 하도록 결정했기 때문입니다. Send는 여러분이 보증한 내용을 게시하고, handoff는 여러분이 함께 보내라는 상자를 체크했을 경우에만 초안을 게시하며, 항상 댓글 형태로 이루어집니다.
그 게이트가 핵심이며, 이것이 다른 리뷰 봇과 다른 이유입니다:
AI 모델로 풀 리퀘스트를 검토하는 것은 특정한 위험을 만듭니다: 의견을 초안 작성할 수도 있고 GitHub 자격 증명(credentials)을 보유할 수도 있는 시스템은 결국 인간이 그렇게 하도록 결정하지 않았는데도 게시할 수 있게 됩니다.
게이트키퍼인 케르베로스(Cerberus)에서 이름을 따서, cerber는 병합되는 것을 감시합니다.
왜 이것이 존재하며, 제가 처음 시도해 본 네 가지 것:
AI가 리뷰 초안 작성. 저는 무엇을 보낼지 결정합니다.
전체 루프를 17초 만에 — 앉았을 때 이미 다섯 개의 PR이 초안 작성되어 있고, 승인(approval)이 아닌 것은 바로 블로커(blocker)로 연결되며, 리뷰어와 논쟁하여 스스로 수정한 내용을 얻고, 동의하지 않는 댓글을 삭제하며, 남은 것을 여러분의 리뷰로 전송합니다:
The cockpit: an inbox of five drafted reviews; opening the one with a blocker; jumping to the finding through the walkthrough rail; asking the reviewer whether the bug is real and watching it revise its own comment; dropping a second comment; then sending the review to GitHub.
읽는 동안 초안 작성된 리뷰 — PR 제목 옆에 판결문과 신뢰도 점수가 표시되고, 왼쪽에 워크스루(walkthrough) 트랙이 있으며, diff를 읽지 않은 사람을 위해 작성된 요약본이 있습니다:
A review opened in the cockpit: the verdict pill by the PR title, a walkthrough rail listing chapters and their comments on the left, and a summary written in sections — problem first, then the fix, then details.
그리고 도착하는 큐 — cerber serve는 검토를 기다리는 GitHub PR을 폴링(poll)하고 각각에 대한 초안을 작성합니다. 따라서 사용자가 도착할 때쯤이면 이미 작성되어 있습니다:**
The queue: three drafted reviews, each with a verdict and confidence in its row; under the cursor, a strip quotes the selected review's own reasoning so it can be judged without opening it.
이 README의 모든 스크린샷은 cerber가 자체 풀 리퀘스트를 검토하는 모습입니다.
빠른 시작 (Quick start)
Node 20+ 버전, 인증된 gh, git, 그리고 로그인된 claude CLI가 필요합니다. API 키도, 설정 파일도, 데이터베이스도 없습니다. 이 코크핏은 2024년 이후의 브라우저(Chrome/Edge 123, Safari 17.5, Firefox 120)를 요구합니다.
Claude Code는 필수이며 유료입니다. Cerber는 사용자가 claude를 실행하는 방식으로 검토 초안을 작성합니다. 이는 기존 Claude Code 로그인을 이용하며 해당 플랜의 사용 한도를 활용하므로, Claude Code가 포함된 Claude 구독이 필요합니다. ANTHROPIC_API_KEY 경로는 없습니다 — 대체용으로도, 아예도 없습니다. GitHub만 지원하며, GitLab이나 Bitbucket은 지원하지 않습니다. 알림 기능은 macOS와 Linux에서 제공됩니다.
먼저 cerber doctor를 실행하세요. 이 명령어는 세 가지 도구를 모두 확인하고, 나중에 로그인 누락이 빈 코크핏으로 이어지는 것을 막기 위해 어떤 부분을 수정해야 하는지 알려줍니다.
npx @fullstackhouse/cerber serve
...
serve는 기본적으로 전체 루프(discover → draft → wait for you)를 수행합니다. 전송은 사람이 직접 클릭해야 합니다. --no-auto-review(검토 대기 PR 목록 표시, 클릭 시 검토) 또는 --no-poll(GitHub 폴링을 아예 안 함)로 제어하거나, 코크핏의 설정(Settings)에서 해당 스위치를 변경할 수 있습니다. 이 설정은 ~/.cerber/config.json에 저장되며 다음 폴링 때 적용됩니다.
목차 (Contents)
리뷰가 어떻게 보이는지
각 리뷰는 ~/.cerber/reviews/ (환경 변수 CERBER_HOME으로 재정의 가능)에 있는 일반 JSON 아티팩트이며, 다음 내용을 포함합니다:
- 요약(Summary) — PR이 실제로 무엇을 하는지 그리고 그 이유를 위에서 아래로 작성한 내용
- 챕터(Chapters) — 변경된 파일들을 논리적인 순서로 묶어 구성하며, 각 챕터는 제목, 설명, 해당 diff의 일부를 가집니다.
- 초안 코멘트(Draft comments) — 파일/라인에 고정되어 인라인으로 표시되며, 인간의 시간을 들일 가치가 있는 내용만 포함합니다. 발견된 사항은 blocker / minor / nit로 등급이 매겨지는데, 이 단어들은 어디서든 같은 의미를 가지며, 오직 blocker만이 PR과 승인 사이에 장애물 역할을 합니다. 질문이나 메모는 어떠한 등급도 부여되지 않습니다.
- 판정(Verdict) — approve / comment / request changes 중 하나이며, 0–100의 신뢰 점수와 가장 심각하게 남아있는 발견 사항을 명시하는 추론을 포함합니다.
- 실행 메타데이터(Run metadata) — 모델 정보, 소스 코드를 읽었는지 아니면 diff만 읽었는지 여부, 그리고 API 비율과 동등한 토큰 사용량을 나타냅니다.
콕핏(cerber serve)은 시스템에 맞춰 큐와 PR별 워크스루를 diff와 함께 라이트 또는 다크 모드로 렌더링합니다 (설정에서 브라우저별로 고정 가능). 초안 코멘트는 해당 라인에 고정되어 diff 내 인라인으로 위치하며, 각각 사용자가 유지할지, 다시 작성할지, 아니면 삭제할지 기다립니다:
A chapter of the walkthrough: the diff with a draft comment card anchored under the line it discusses, explaining the finding in plain words.
변경 사항(diff)의 모든 줄은 클릭 한 번 거리에 논의될 수 있습니다. 해당 줄에 마우스를 가져가면 GitHub에서처럼 구역(gutter)에 + 표시가 나타납니다. 열리는 것은 두 가지 출구(exit)를 가진 하나의 상자입니다. 직접 댓글을 작성하거나, 검토자에게 해당 줄에 대해 질문하고 아래 대화창에서 답변을 받을 수 있습니다. PR이 제거하는 줄도 질문할 수 있으며, 한 줄에 대한 댓글은 파일에 게시됩니다. 이는 GitHub가 diff의 새로운 측면에 대해서만 인라인(inline) 댓글을 허용하기 때문입니다.
PR이 추가하는 마크다운 파일은 수많은 + ## Heading 행으로 열리지 않고 문서 자체로 열립니다. 왜냐하면 새 스펙을 검토한다는 것은 그것을 읽는 것을 의미하며, 모든 줄이 추가된 것이라는 것은 diff의 표시자가 아무것도 말해주지 않기 때문입니다. 여전히 검토 과정입니다: 초안 댓글은 해당 단락 아래에 위치하며, 모든 단락은 그 자리에 댓글이나 질문을 가질 수 있습니다. PR이 단순히 편집만 하는 마크다운 파일은 여전히 diff로 유지됩니다. 이 경우 변경 사항 자체가 핵심이며, 본문(prose)으로 보고 싶을 때는 헤더에서
리뷰를 확정하는 것은 GitHub의 결정이 아니라 당신의 결정입니다. PR을 건너뛰거나, 보내지 않고 리뷰 완료로 표시해도 GitHub는 여전히 해당 리뷰 요청을 열어둡니다. 왜냐하면 그 결정 중 어느 것도 GitHub에 전달되지 않기 때문입니다. (유일하게 전달되는 결정은 다른 사람에게 리뷰를 넘기는 것이며, 이는 요청을 남겨두는 대신 이동시킵니다.) 해당 행들은 제자리에 표시된 채로 남아있으며, 속한 탭에서 카운트되고, 빈 받은 편지함 대신 이름이 붙습니다. cerber는 아무것도 기다리지 않는다고 말하지 않습니다. 그저 보고서일 뿐입니다. 여기서 당신이 결정한 내용은 유지되며, GitHub가 당신으로부터 소식을 듣는 순간 표시가 사라집니다.
GitHub에서 리뷰했을 때를 제외하고
수동으로 확정할 필요가 없는 한 가지가 있습니다. PR을 일반적인 방식으로 검토하세요. 즉, cerber의 개입 없이 GitHub 자체의 리뷰 버튼을 사용하면 리뷰 요청은 사라지지만, 여기서는 아무도 그것에 대해 알지 못합니다. 해당 PR을 위해 cerber가 작성한 초안은 마치 여전히 당신에게 기다리는 작업인 것처럼 받은 편지함에 그대로 남아있어, PR이 작성자에게 돌아간 지 며칠이 지나도 그렇습니다. 그래서 이 폴(poll)은 다른 질문도 합니다. GitHub가 더 이상 당신의 리뷰를 요청하지 않고 이미 당신의 리뷰 중 하나를 보유하고 있을 때, 초안은 '확정됨'으로 분류되고 제출된 날짜와 함께 GitHub에서 검토됨 태그가 붙습니다. 그 외에는 아무 일도 일어나지 않습니다. 그것은 전송된 적이 없으며, 여전히 당신이 열거나 재검토하거나 보낼 수 있는 것입니다. 이 방식이 그대로 두는 유일한 초안은 해당 리뷰 후에 요청한 것, 즉 당신이 요청하여 얻은 두 번째 의견입니다. 이는 큐가 닫는 것을 잊어버린 행이 아닙니다.
누구의 차례인가
오픈 요청이 곧 당신 차례라는 의미는 아닙니다. PR 대화에서 모든 것을 논했지만 GitHub의 리뷰 버튼을 누르지 않은 경우도 있을 수 있으며, 이는 아무것도 막힌 것이 없는 상태로 요청을 열어둡니다. 그래서 cerber는 대화를 읽고 누가 움직여야 하는지 알려줍니다: 당신이 답하지 않았습니다 (상대방이 기다리는 중), 그들이 기다리고 있습니다 (당신이 마지막 말을 했음), 또는 그들이 마지막으로 답했습니다 (다시 당신에게 돌아옴). 봇은 답변으로 간주되지 않으며, 수다스러운 CI는 모든 PR을 다시 당신에게 돌릴 수 있습니다. 대화를 읽을 수 없으면 GitHub에서 답변 없음이라고 표시하고 더 이상 아무것도 주장하지 않습니다 — 실제로 답변한 사람에게 '당신이 답하지 않았다'고 추측하는 것이 설계상 방지해야 할 실수입니다.
어깨를 톡톡 두드립니다
PR이 당신을 기다릴 준비가 되면, 이름을 언급하는 데스크톱 알림을 받게 되며, 여러 개가 한 번에 도착할 경우 하나의 팝업으로 접힙니다. '준비됨'이라는 것은 읽어야 할 무언가가 있다는 의미입니다: cerber가 자체적으로 리뷰 초안을 작성하므로, 이 알림은 단순히 '아직 실행 없음'이라고 표시된 행으로 돌아가는 대신,
macOS에서는 그것을 클릭하면 코크핏(cockpit)에서 해당 리뷰가 열립니다. 이는 cerber라는 작은 앱이 ~/.cerber 아래에 한 번 구축하는 것입니다. 첫 번째 알림은 "Cerber"로부터의 알림을 허용하도록 요청하는데, 그 이유는 알림은 자신이 게시한 앱만 열 수 있고, 일반적인 방식으로 게시된 것은 원래 클릭이 착지할 곳인 Script Editor에 속하기 때문입니다. 리눅스에서 notify-send 알림은 PR(Pull Request)을 공지하지만 클릭으로 연결되는 기능은 없습니다.