원문 캡처 · github.com
원문 캡처 · github.com

Epoptes는 Claude Code 또는 Codex를 이용한 장시간 자율 작업을 실행하고, 진행 상황을 확인하거나 방향을 조정할 수 있게 하는 도구다. 목표를 채팅으로 설명하면 에이전트가 질문을 통해 실행 계획을 만들고, 대시보드에서 작업을 지켜보며 피드백을 줄 수 있다.

Epoptes라는 이름은 모든 것을 지켜보는 제우스와 헬리오스의 칭호인 그리스어 ἐπόπτης에서 왔다. 이 도구는 밤샘 빌드, 연구 조사, 문서 묶음 처리, 데이터 정리처럼 오래 걸리는 작업을 대상으로 한다. 각 작업은 매번 새 컨텍스트에서 시작하는 반복 주기로 진행하며, 목표를 달성하거나 정해진 시간이 끝날 때까지 실행된다. 대시보드는 실행 중 상태를 보여주고, 완료되면 보고서를 만든다.

이 프로젝트는 12시간 동안 자율적으로 게임을 만든 경험에서 출발했다. 장시간 실행의 비용을 낮추고 작업이 목표에서 벗어나지 않도록 매 주기마다 새 컨텍스트를 사용하고, 크기 제한이 있는 작은 상태 파일을 두며, 기계적인 작업에는 저렴한 모델을 사용하고, 주기마다 시간과 반복 횟수의 상한을 둔다.

현재 상태는 초기 단계인 0.3이다. 일상적으로 사용하며 개선한 개인용 도구이며, 파일 형식은 계속 바뀔 수 있다. 자세한 내용은 ROADMAP.md를 참고하면 된다.

설치와 시작

Node.js 22.18 이상이 필요하다. Claude Code 또는 Codex CLI를 설치하고 로그인해야 하며, Linux, macOS 또는 WSL2에서 실행할 수 있다. Epoptes는 사용자가 이미 로그인한 CLI를 실행하며 로그인 정보나 키를 직접 다루지 않는다.

전역 설치 명령은 다음과 같다.

sh
npm install -g @ramigbcom/epoptes
epoptes --version

패키지는 npm의 @ramigbcom/epoptes에서 제공한다. 설치하지 않고 한 번 실행하려면 npx @ramigbcom/epoptes <command>를 사용할 수 있다.

저장소에서 개발하려면 다음 명령을 실행한다.

sh
git clone https://github.com/ramigb/epoptes.git && cd epoptes
npm install
npm link # puts `epoptes` on your PATH; runs the source directly, so no build step

WSL2에서는 가능하면 저장소를 /mnt/c나 /mnt/d가 아니라 ~/… 같은 Linux 쪽에 둔다. Windows 드라이브에서 node_modules를 불러오면 느리기 때문이다.

Claude Code에서 시작할 때는 먼저 Epoptes 스킬을 설치한다.

sh
epoptes skill install # links the skill into ~/.claude/skills (all projects)

이 명령은 전역 설치본이나 체크아웃한 저장소에서 실행해야 한다. npx로 실행하면 npm 임시 캐시에서 동작해 캐시가 지워질 때 링크가 끊긴다. 한 세션에서만 시험하려면 claude --plugin-dir "$(epoptes skill path)/../.."를 실행한다.

작업을 수행할 폴더에서 Claude Code에 목표를 설명한다. 예를 들어 내부 API를 설명하는 20쪽 현장 안내서를 만들고 싶다면, Epoptes 스킬을 사용해 그 작업을 위한 하네스를 만들라고 요청한다. Claude는 결과물과 완료 여부를 확인할 기준, 제외할 작업과 시간 제한, 팀의 역할·모델·투입량, 중간 점검과 반드시 승인이 필요한 항목, 결과물의 저장 위치, 피드백 방법을 묻는다. 과거 하네스에서 얻은 교훈이 담긴 brain도 읽고, 적용한 교훈을 포함한 한 화면 요약을 승인받는다. 이후 .epoptes/를 만들고 epoptes run --dry-run을 실행한 뒤 epoptes add로 목표를 등록한다.

대시보드를 열고 작업을 시작한다.

sh
epoptes ui # http://127.0.0.1:4747

대시보드에서 Start를 누르거나 epoptes start <goal>을 실행한다. 실시간 진행 표시를 보면서 피드백을 줄 수 있고, 언제든 일시 중지하거나 멈출 수 있다. 완료 후에는 대시보드의 Report 버튼이나 epoptes report <goal>로 보고서를 확인한다.

자신의 목표를 만들기 전에 15분짜리 예제를 실행해 작은 용어집을 작성해 볼 수 있다. 원문은 API 사용량에 상응하는 비용이 1달러보다 훨씬 적다고 설명한다.

sh
cp -r examples/glossary /tmp/glossary && epoptes add /tmp/glossary && epoptes start glossary

Codex 사용

Codex에 같은 스킬을 설치하려면 다음을 실행한다.

sh
epoptes skill install --agent codex # links into ~/.agents/skills

이후 Codex에 use the epoptes skill to build a Codex harness for라고 요청한다. 스킬 링크는 Claude Code와 마찬가지로 전역 설치본이나 체크아웃에서 설치해야 한다. Epoptes와 Codex CLI는 Linux, macOS 또는 WSL2에서 실행해야 하며, Windows 네이티브 실행 환경은 지원하지 않는다.

.epoptes/goal.json에서 다음과 같이 설정한다.

json
"adapter": {
 "type": "codex",
 "model": "",
 "effort": "high",
 "permission_mode": "workspace-write"
}

모델을 빈 문자열로 두면 Codex CLI 설정을 사용하며, Codex 모델 ID를 직접 지정할 수도 있다. 각 주기는 새 codex exec --json을 실행하고 loop.md를 표준 입력으로 전달하며 저장된 CLI 인증을 사용한다. 승인 프롬프트는 비활성화되어 있어 권한 상승이 필요한 명령은 실패한다. Git 저장소가 아닌 디렉터리에서도 동작한다.

Codex는 자체 샌드박스와 설정, 규칙을 사용한다. .epoptes/settings.json은 Claude 전용이므로 Codex 목표에는 넣지 않는다. 스킬은 loop.md를 순차적으로 작업하고 확인하도록 조정한다. 역할 파일은 참고 지침이며, Claude 모델·도구 목록·턴 제한은 Codex의 네이티브 서브에이전트 설정으로 변환되지 않는다. 기존 Claude 루프를 Codex로 바꾸기 전에 먼저 조정해야 한다.

대시보드와 보고서는 Codex 명령, 파일 변경, 메시지, 토큰 사용량을 보여준다. Codex JSONL에는 달러 비용이나 제한 초기화 시각이 없어 비용은 알 수 없음으로 표시된다. 요청 제한에는 설정된 대기 시간이 적용되며, cycle.max_budget_usd는 null이어야 한다. 모델을 지정하지 않으면 스트림에서 실제 모델을 식별할 수 없어 토큰 사용량에 codex-configured라고 표시한다. 자세한 내용은 OpenAI의 비대화형 모드 문서와 스킬 위치 안내를 참고하면 된다.

실행 구조와 감독 방식

목표 하나는 디렉터리 하나에 해당한다. 모든 파일은 <project>/.epoptes/에 저장된다. goal.json에는 목표, 완료 확인 기준, 시간 제한, 모델을 적고, loop.md에는 오케스트레이터가 각 주기에서 따를 지침을 둔다. agents/에는 역할 파일, state/에는 메모리가 들어간다. 이벤트·피드백·주기 로그도 이곳에 기록한다. 파일 형식이 구성 요소 사이의 계약이므로 CLI, 실행기, 대시보드, 스킬은 이 파일을 읽고 쓴다. 자세한 형식은 docs/spec.md에 있다.

실행은 목표마다 분리된 백그라운드 프로세스 하나로 이뤄진다. 실행기는 loop.md를 전달해 claude -p 또는 codex exec를 주기마다 시작한다. 각 주기는 상태 파일을 확인하고 작업 일부를 수행하며, 설정에 따라 서브에이전트를 사용하고, 결과를 검증하고 기록한 뒤 종료한다. 주기 사이에는 실행기가 시간 제한, 사용자 조작, 요청 제한, 오류를 확인한다. 대시보드나 터미널을 닫아도 작업은 멈추지 않는다.

시계는 실제 실행 시간만 센다. 일시 중지·중단 시간과 기본 설정에서 요청 제한으로 기다리는 시간은 포함하지 않는다. 종료가 가까워지면 목표는 마무리 단계로 전환되며, 이때 기능 추가를 동결한다. 이후 초과 근무 단계에 들어가고 마지막에는 정지한다.

시간 제한은 목표 시간이 아니라 상한이다. 완료 확인 기준을 통과하면 일찍 끝나며, 각 마일스톤도 목표 시각까지 기다리지 않고 완료되는 대로 다음 단계로 넘어간다. 하네스는 남은 시간을 채우려고 일을 만들어내지 않는다. 완료 기준, 마일스톤 또는 사용자 피드백이 요구하는 작업만 백로그에 들어간다. 실질적인 작업이 남지 않으면 아이디어를 사용자에게 넘길 인계 내용에 적고, 다음 주기에 완료 여부를 확인해 마무리하도록 한다. 대시보드는 지금까지의 마일스톤 속도를 바탕으로 예상 종료 시각을 보여준다. 예를 들어 2시간 마일스톤을 30분 만에 끝내면 10시간 계획은 약 2시간 30분에 끝날 속도로 표시된다.

사용자가 계속 지켜보지 않아도 승인 목록에 있는 작업은 사용자가 승인하거나 거절할 때까지 대기한다. 실행은 그동안 다른 작업을 이어간다. 더 진행할 작업이 없으면 이유를 표시하고 사용자의 답변을 기다린다. 오케스트레이터는 다음 주기가 처리해야 할 조사 결과 같은 에이전트 메모를 남길 수도 있으며, 사용자는 이를 수정하거나 삭제할 수 있다.

각 하네스는 다음 하네스를 개선하는 데 쓰인다. 오케스트레이터는 마무리 단계에서 하네스에 관한 교훈을 기록한다. 실행이 끝나면 Epoptes는 그 교훈과 목표별 수치, 잦은 시간 초과·늦은 마일스톤·반복적인 방향 수정 같은 자동 신호를 모아 로컬 brain인 ~/.epoptes/brain/INDEX.md에 저장한다. 이 과정에는 토큰이 들지 않는다. 스킬은 새 하네스를 설계하기 전에 brain을 읽는다. distill the brain이라고 요청하면 짧게 선별한 NOTES.md를 만들 수 있다.

실시간 진행 표시는 CLI의 JSON 스트림을 바탕으로 하며, 실행한 도구와 바뀐 파일을 보여준다. Claude Code에서는 에이전트 활동도 표시한다. 오케스트레이터는 CLI를 통해 마일스톤·차단·완료 같은 의미 단위 이벤트도 기록한다. 관측 기능에는 토큰이 들지 않는다.

일상적인 조작

대시보드와 CLI에서 상태 확인, 시작·재개, 안전한 일시 중지, 즉시 중단, 시간 연장, 피드백 입력, 방향 전환, 승인 답변, 새 작업 생성, 완료 목표 후속 처리, 결과물 열기, 진행 속도 확인, 과거 실행에서 얻은 교훈 확인, 보고서 작성 등을 할 수 있다. CLI 명령은 Claude Code나 Codex 채팅에서도 사용할 수 있다.

  • 진행 상태 확인: 대시보드의 목표 카드나 페이지, 또는 epoptes status <goal>을 사용한다.
  • 시작하거나 재개: 대시보드에서 Start / Resume을 누르거나 epoptes start <goal>을 실행한다.
  • 안전하게 일시 중지: Pause after cycle을 선택하거나 epoptes pause <goal>을 실행한다. 현재 주기가 끝난 뒤 멈춘다.
  • 즉시 중단: Stop now를 선택하거나 epoptes stop <goal>을 실행한다. 다음 시작 때 중단된 작업을 복구한다.
  • 시간 연장: 대시보드에서 +30m, +1h, +2h를 선택하거나 epoptes extend <goal> 2h를 실행한다.
  • 피드백 제공: 대시보드 Feedback 상자를 이용하거나 epoptes feedback <goal> "the intro is too long"을 실행한다. .epoptes/FEEDBACK.md에 불릿을 추가해도 된다.
  • 즉시 방향 전환: 대시보드에서 ⚡ Steer now를 선택하거나 epoptes feedback <goal> "use SQLite instead" --steer를 실행한다. 현재 주기를 중단하고 다음 주기에서 전체 백로그를 새 방향에 맞춰 다시 계획한다.
  • 승인 답변: 대시보드의 Approve / Disapprove를 사용하거나 epoptes feedback F-4 approve "test mode only"를 실행한다. 거절하려면 reject를 쓴다.
  • 프로젝트에서 새 기능 시작: 스킬에 a new epoptes job: …이라고 요청하거나 epoptes job new "<title>"을 실행한다. 이후 goal.json, loop.md, 백로그를 갱신한다. 스킬이 이 과정을 대신한다.
  • 완료한 목표 조정: 대시보드에서 피드백 항목을 후속 처리하거나 epoptes start <goal> --follow-up을 실행한다. 시간 제한 없이 미처리 피드백만 다루며, 사소한 항목은 그 자리에서 고치고 큰 항목은 새 실행이 필요하다고 표시한다.
  • 결과물 열기: goal.json의 output을 설정하거나 epoptes event output <path or URL>을 사용한다.
  • 시간 사용 확인: 대시보드의 “Where the time went” 패널에서 실행·요청 제한·사용자 대기·일시 중지에 쓴 시간, 역할별 시간, 도구별 시간을 본다. 이 정보는 대시보드에만 제공된다.
  • 조기 완료 예상 확인: 대시보드 시계의 마일스톤 표시와 점선 예상 완료 표식을 보거나 epoptes status의 pace 줄을 확인한다.
  • 과거 실행에서 얻은 교훈 확인: 대시보드의 Brain을 열거나 epoptes brain을 실행한다. 이 명령은 ~/.epoptes/brain/INDEX.md를 작성한다.
  • 실행 결과 확인: 대시보드 Report 버튼이나 epoptes report <goal>을 사용한다. 보고서는 Markdown과 HTML로 제공된다.

피드백 항목에는 F-3 같은 ID가 붙으며 new → seen → in progress → done | blocked | won't do 상태를 거친다. 상태가 바뀔 때마다 해당 주기와 메모가 기록되고, 대시보드에는 읽지 않은 항목 표시와 함께 실시간으로 나타난다. 승인 요청은 “waiting for you” 상태로 시작한다. 오케스트레이터가 다음 주기를 위해 남긴 메모에는 “agent note” 표시가 붙는다. 바탕 화면 알림은 선택 사항이며 🔔 버튼으로 설정한다.

백로그 막대는 마일스톤마다 한 구간으로 나뉜다. 시계 막대에는 각 마일스톤의 목표 시각과 실제 도달 시각이 표시되며, 일정 준수·지연·기한 초과 여부를 확인할 수 있다.

목표가 끝난 뒤 피드백을 처리하면 시간 제한 없이 열린 피드백만 다루는 후속 실행이 시작된다. 색상·크기·문구 같은 사소한 항목은 에이전트가 직접 고친다. 재시작이나 새 버전이 필요한 항목은 “needs a new run”으로 표시해 사용자가 결정하도록 하며, 항목별 처리 방식은 변경할 수 있다. Start new run…을 선택하면 새 시간 제한으로 실행을 시작한다. 새 실행에는 토큰이 들기 때문에 Epoptes는 먼저 확인을 요청한다.

하나의 하네스로 여러 작업을 처리할 수 있다. 같은 프로젝트에 새 기능이 필요하면 두 번째 하네스를 만들지 말고 스킬에 새 작업을 요청한다. 스킬은 바뀌는 내용만 질문하고 epoptes job new "<title>"을 실행한다. 이 명령은 완료한 작업의 백로그·인계 내용·진행 상황을 .epoptes/state/archive/에 보관하고, 역할·권한·교훈·결정은 유지하며 시계를 초기화한다. 목표 페이지와 epoptes status, 보고서는 현재 작업을 보여주며 전체 작업 목록으로 전환할 수 있다. epoptes report --job all은 모든 작업의 보고서를 만들고, epoptes job은 작업 목록을 표시한다.

대시보드 탭 아이콘도 상태를 나타낸다. 주기가 실행 중이면 호가 회전하고, 실행에 사용자의 조치가 필요하면 표시등이 깜박이며, 오류가 발생하면 빨간색으로 바뀐다.

CLI 명령

[goal]에는 등록된 ID나 경로를 넣는다. 목표 폴더 안에서 실행할 때는 생략할 수 있다.

  • epoptes add [dir]: 목표를 등록하고 .epoptes/goal.json을 검증한다.
  • epoptes list: 모든 목표를 나열한다.
  • epoptes status [goal]: 상태, 시계, 진행 속도, 주기, 백로그, 피드백, 결과물, 마지막 주기, 인계 내용을 한 화면에 표시한다.
  • epoptes run [goal] --dry-run: 설정과 안전장치를 확인하고 다음 주기의 명령을 출력한다. 시계는 시작하지 않는다.
  • epoptes start [goal] [--new-run]: 시작하거나 재개한다. --new-run은 완료 상태이거나 시간 제한이 끝난 뒤 새로 실행할 때 쓴다.
  • epoptes start [goal] --follow-up: 완료 뒤 열린 피드백만 시간 제한 없이 처리한다.
  • epoptes pause [goal] 및 epoptes stop [goal]: 현재 주기 뒤 일시 중지하거나 즉시 중단한다.
  • epoptes extend [goal] <dur>: 시간을 연장한다. 예: 2h, 30m.
  • epoptes reset-clock [goal]: 다음 시작을 새 실행으로 처리한다.
  • epoptes feedback [goal] "<text>": 피드백을 추가한다.
  • epoptes feedback [goal] [--open]: 피드백 목록을 표시한다.
  • epoptes feedback [goal] "<text>" --steer: 실행 중인 주기를 중단하고 새 방향에 맞춰 다시 계획한다.
  • epoptes feedback F-3 <status> [note]: 피드백 상태를 new, seen, in_progress, done, blocked, wont_do 중 하나로 바꾼다.
  • epoptes feedback F-3 approve|reject [note]: 승인 요청에 답한다. 답변을 기다리는 실행은 재개된다.
  • epoptes feedback F-3 edit "<text>": 항목을 수정한다. 예를 들어 에이전트 메모를 고칠 수 있다. 후속 처리 범위는 auto|tweak|new_run으로 지정한다.
  • epoptes event <type> "<text>": 오케스트레이터가 milestone, blocked, note, artifact, output, round, wrapup, done 이벤트를 기록한다.
  • epoptes approval "<what>" [--ref T]: 오케스트레이터가 먼저 사용자 승인을 요청한다. wait-for-human "<what>"은 사용자가 답할 때까지 일시 중지한다.
  • epoptes lesson "<rule>" [--topic t]: 마무리 단계에서 오케스트레이터가 brain에 넣을 교훈을 기록한다.
  • epoptes brain [lessons [--kind k]]: 모든 목표의 정보를 모아 ~/.epoptes/brain/INDEX.md를 만들고 교훈을 출력한다.
  • epoptes job [goal]: 하네스의 작업을 표시한다. job new "<title>"은 기록을 보관하고 메모리를 유지한 채 시계를 초기화해 다음 작업을 시작한다.
  • epoptes clock: 남은 시간과 현재 마일스톤 목표를 한 줄로 표시한다. 오케스트레이터가 사용한다.
  • epoptes report [goal] [--all] [--job <id>|all]: Markdown과 HTML 보고서를 만든다. 기본값은 현재 작업이다.
  • epoptes import-runsh <project>: 예전 run.sh 하네스(dress2impress 방식)를 가져온다.
  • epoptes ui [--port N] [--lan]: 대시보드를 연다. 결과물은 다음 포트에서 제공한다.
  • epoptes skill install [--agent codex]: 스킬을 설치한다. 기본값은 Claude Code다.
  • epoptes skill path: Claude Code와 Codex가 공유하는 스킬 디렉터리 경로를 출력한다.

0.2에서 업그레이드

0.3 이전에 생성한 하네스도 계속 작동한다. 일부 새 기능은 실행기에 포함되어 있어 기존 하네스에서도 바로 사용할 수 있다.

  • 방향 전환
  • 완료 뒤 후속 처리
  • 백로그가 비었을 때 다음 작업을 촉구하는 기능
  • 대시보드 기능

나머지 기능은 루프 템플릿에 포함된다. 승인 요청, “waiting for you” 상태, 하네스 교훈, 결과물 이벤트, 범위 규칙, 마일스톤별 조기 완료를 사용하려면 스킬로 하네스를 다시 생성하거나 Claude에 현재 템플릿을 기준으로 해당 목표의 .epoptes/loop.md를 갱신해 달라고 요청한다. 기존 goal.json에 "output"을 직접 추가할 수도 있다.

비용과 사용 제한

대시보드와 보고서는 모델별 토큰 수, 캐시 읽기 비중, 주기별 비용을 보여주며 중앙값의 두 배를 넘는 비용이 든 주기를 표시한다. Claude 구독을 사용할 때 표시되는 비용은 실제 청구액이 아니라 API 가격에 상응하는 추정치이며 항상 ≈와 함께 나온다.

계정과 사용 한도는 사용자가 관리해야 한다. Claude Code가 요청 제한을 알리면 Epoptes는 한도가 초기화될 때까지 기다린 뒤 작업을 이어간다. 그동안 시계는 멈춘다. 한도를 우회하거나 계정을 바꾸지는 않는다. Claude Code에서 주기별 비용 상한을 두려면 goal.json의 cycle.max_budget_usd를 설정한다. Codex에는 이 값이 null이어야 하며, 달러 비용 추정 없이 토큰 사용량을 보고한다.

안전과 개인정보

대시보드는 기본적으로 127.0.0.1에만 연결된다. DNS 리바인딩과 교차 사이트 요청 위조(CSRF)를 막기 위해 다른 호스트의 요청과 교차 사이트 쓰기를 거부한다. 피드백이 에이전트 프롬프트에 들어가기 때문이다. --lan은 경고와 함께 명시적으로 선택할 수 있지만 로그인 기능은 없다.

텔레메트리와 계정은 없으며, Epoptes가 키를 처리하지도 않는다. 이미 로그인한 claude 또는 codex를 실행하고, 해당 CLI 자체의 데이터 설정을 따른다. 대화 기록과 로그는 사용자 컴퓨터의 .epoptes/cycles/와 .epoptes/run/에 저장되며 Git에서 제외된다. brain도 ~/.epoptes/brain/에 로컬로 저장된다.

결과물은 대시보드 포트보다 1 높은 별도 로컬 출처에서 읽기 전용으로 제공된다. 에이전트가 만든 페이지는 정상적으로 실행되지만 대시보드 조작 기능에는 접근할 수 없다. 등록된 프로젝트 안의 파일만 제공하고 .env, .epoptes/ 같은 숨김 파일은 제공하지 않는다. --lan 모드에서는 결과물 서버가 꺼진다.

생성되는 모든 하네스에는 안전장치가 포함된다. Claude Code에서는 권한 허용·거부 목록을, Codex에서는 네이티브 샌드박스와 규칙을 사용한다. git push, Git 기록 덮어쓰기, 파괴적인 정리 명령은 금지한다. 비밀 정보는 목표 파일에 넣지 말고 1Password CLI 같은 비밀 관리자에서 관리한다. 오케스트레이터가 혼자 처리해서는 안 되는 승인 목록도 둔다. epoptes run --dry-run은 이러한 설정을 확인하고 자격 증명처럼 보이는 항목에 경고한다.

개발과 라이선스

개발 점검 명령은 다음과 같다.

sh
npm test # node --test: unit tests, runner tests with fake Claude/Codex CLIs, server and report tests
npm run typecheck
npm run build # dist/ for the npm package (the checkout runs src/ directly)

src/에는 CLI, 실행기, 어댑터, 대시보드 및 결과물 서버, 보고서, 가져오기 도구, 시간 사용 기능(timeuse.ts), brain(brain.ts)이 들어간다. ui/는 빌드 단계가 필요 없는 Preact와 htm 기반 대시보드다. plugin/에는 Claude Code와 Codex가 공유하는 스킬과 템플릿이 있고, docs/에는 명세, JSON 스키마, 설계 결정이 있다.

사용 메모는 NOTES.md에 기록하고 ROADMAP.md에서 검토한다. 라이선스는 MIT다.