.dmg로 따로 무료 배포되고, 이 저장소에 담긴 건 Claude Code·Codex·Cursor 같은 아무 에이전트 CLI든 그 브라우저를 조종하게 해주는 "오픈소스 연결 계층(harness) + 에이전트 스킬 패키지"다.
citrolabs/ego-lite · 코어 언어 TypeScript · npm 패키지 ego-browser-v2 0.1.0 · Node ≥ 22 · ESM · 런타임 의존성 acorn 딱 1개 · 빌드 esbuild + rollup · 라이선스 MIT · 저작권 CitroLabs (2026) · ★ 47(별점 아닌 모멘텀 순위) · 최신 커밋 2026-07-24 · shallow clone 소스 직접 분석)
요즘 "AI 브라우저"가 쏟아진다. OpenAI의 ChatGPT Atlas, Perplexity의 Comet, The Browser Company의 Dia… 대부분 브라우저 안에 자기네 AI를 박아넣은 형태다. ego lite는 여기서 방향을 튼다. ego lite의 핵심 주장은 "우리 AI가 똑똑하다"가 아니라, "당신이 이미 쓰는 에이전트(Claude Code, Codex…)에게 진짜 브라우저를 통째로 내어준다"이다.
저장소 ego-lite를 클론해도 "브라우저"는 없다. 개발 문서 AGENTS.md가 대놓고 말한다: "This repo contains the open-source harness and the agent skill package — not the browser itself." 진짜 브라우저는 cdn.ego.app에서 받는 클로즈드 소스 .dmg이고, 저장소엔 그 브라우저를 조종하는 도구(harness)와 에이전트 사용설명서(skill)만 있다.
진짜 자동차(브라우저 바이너리)는 회사가 따로 무료로 나눠준다. 이 저장소가 오픈소스로 공개한 건 "로봇 운전기사(=Claude Code 같은 에이전트)가 그 차를 몰 수 있게 해주는 운전대와 매뉴얼"이다. 그래서 운전기사(지능=LLM)는 저장소 안에 없다. 누구의 로봇 기사든 데려와서 이 운전대에 앉히면 된다는 게 핵심이다.
동작을 한 문장으로 압축하면 이렇다. 에이전트가 자바스크립트를 한 덩어리 짜서 ego-browser 명령의 표준입력으로 밀어넣으면 → 저장소의 하네스(harness)가 그 코드를 실행하며 page·browser·taskSpaces 같은 브라우저 조종 헬퍼를 주입하고 → 각 헬퍼는 CDP 메시지로 번역돼 클로즈드 브라우저에 전달된다. 결과(페이지 스냅샷·DOM·다운로드)는 console.log로만 에이전트에게 돌아온다.
Page.navigate, Runtime.evaluate, Input.dispatchMouseEvent 같은 메서드를 JSON으로 주고받는다. Playwright·Puppeteer도 내부적으로 이걸 쓰는데, ego lite는 그 래퍼 없이 CDP를 직접 부른다.ego lite가 트렌딩에 오른 건 별점 때문이 아니다. 분석 시점 기준 별 47개, 포크 0, 커밋 34개에 불과하다. TrendShift 상위 순위의 굵은 숫자는 별 수가 아니라 "지금 얼마나 빠르게 화제가 번지는가"(모멘텀)를 뜻한다(프로젝트 규칙에도 명시). ego lite는 두 개의 뜨거운 흐름이 겹치는 지점에 정확히 자리 잡아 모멘텀을 얻었다.
ego lite의 포지셔닝은 README의 정면 비교표로 요약된다. 기존 두 진영을 각각 저격한다.
| 진영 | 대표 주자 | 결정적 약점(ego의 주장) |
|---|---|---|
| 자동화 프레임워크 | Browser-Use, Vercel agent-browser | 에이전트 전용 브라우저를 따로 띄워야 하고 내 로그인 세션이 안 넘어간다. 게다가 에이전트와 내가 같은 탭을 두고 다툰다. |
| AI 내장 브라우저 | ChatGPT Atlas, Perplexity Comet | 브라우저에 박힌 자기네 내장 에이전트만 조종 가능. 내가 쓰는 Claude Code로는 못 몬다. |
| ego lite | ego lite (harness + skill) | (해법) 하나의 브라우저를 사람과 임의의 에이전트가 공유. Chrome 데이터 상속, 로컬 저장, 무료. |
기술적 후크도 있다. 저장소는 Vercel의 agent-browser와 비교해 복잡한 작업에서 최대 2.5배 빠르고 토큰도 크게 아낀다고 주장한다(docs/assets/ego-vs-agent-benchmark.png). 이 속도의 비결은 뒤(4장)에서 볼 "CLI를 여러 번 왕복하지 말고, 전 과정을 코드 한 덩어리로 짜서 한 번에 실행"이라는 설계에 있다. 왕복(round-trip)이 줄면 지연도, 토큰도 준다.
왜 "코드 한 덩어리"가 빠른가? 요리사(에이전트)에게 심부름을 시킨다고 하자. "냉장고 열어" → (보고) → "계란 꺼내" → (보고) → "깨" … 이렇게 한 동작마다 전화로 확인하면 느리고 통화료(토큰)도 많이 든다. 대신 "냉장고 열고 계란 3개 꺼내 깨서 볼에 담아, 껍질 들어가면 건져내"라고 레시피를 통째로 한 번에 주면, 요리사는 알아서 끝까지 하고 결과만 보고한다. ego lite의 "한 Bash 호출 = 한 브라우저 작업" 원칙이 바로 이 레시피 방식이다.
이 저장소를 처음 열면 "AI 브라우저치고 너무 가벼운데?"라는 인상을 받는다. 무거운 프레임워크가 없기 때문이다. 코어는 순수 TypeScript이고, 브라우저를 조종하는 데 Playwright도 Puppeteer도 쓰지 않으며, LLM 호출 코드도 MCP도 없다. 세 겹으로 나눠 지도를 그려보자.
package/ego-browser| 항목 | 값 (파일 기준) |
|---|---|
| npm 패키지명 | ego-browser-v2 · 버전 0.1.0 · bin은 ego-browser |
| 언어 | 코어 로직(src/**) 전부 TypeScript (소스 TS 33개, JS 7개는 사이트 스크립트·테스트) |
| 모듈 방식 | "type": "module" — ESM 전용, Node ≥ 22 요구 |
| 런타임 의존성 | 단 1개: acorn ^8.16.0 (그런데 브라우저 조종용이 아님 — 아래 설명) |
| 빌드 도구 | esbuild ^0.28(개별 트랜스파일) + rollup ^4.60(단일 파일 번들) |
| 타입/포맷 | TS target ES2024, lib: [ES2024, DOM] · prettier · lefthook(git hook) |
| 테스트 | Node 내장 러너(node --test) + node:assert/strict, 소스 옆에 *.test.mjs 코로케이트 |
help() 문서를 자동 생성하는 데 쓴다(scripts/extract-help-docs.mjs). 즉 "주석이 곧 사용자용 API 문서"라는 원칙을 코드로 강제하는 장치다. 브라우저 조종 자체는 순수 CDP라 외부 런타임 의존성이 사실상 0이다.ego lite.app
진짜 브라우저는 Chromium을 커널 수준까지 커스터마이즈한 클로즈드 소스 macOS 앱이다. "가장 강력한 스냅샷", "Task Space(격리 컨텍스트)", "로그인 세션 상속" 같은 해자(moat)에 해당하는 기능은 전부 이 바이너리 안에 있다. 하네스는 globalThis.ego.snapshot(), globalThis.ego.sendCDPMessage(), globalThis.ego.createTaskSpace() 같은 브리지 함수로 이 능력을 빌려 쓴다.
커널 수준 스냅샷·세션 상속처럼 따라 만들기 어려운 핵심은 클로즈드 바이너리에 숨기고, 에이전트가 닿는 접점(하네스 + 스킬)만 MIT로 공개했다. 생태계 확산(누구나 스킬을 만들고 붙임)과 독점성(핵심 기술은 못 베낌)을 동시에 노리는 영리한 구조다.
.github/, .claude-plugin/, skills/.claude-plugin/marketplace.json(Claude Code용), .codex-plugin/plugin.json(Codex용). 에이전트 CLI가 이 스킬을 "플러그인"으로 인식하게 하는 매니페스트..github/workflows/publish-ego-browser-skill.yml이 태그를 push하면 ClawHub·SkillHub 두 마켓에 동시 배포한다. 릴리스 아카이브에 토큰 유출 방지 grep(clh_|skh_|pt-)까지 넣어둔 실전 파이프라인.video-recorder.ts + driver/screencast.ts가 CDP 스크린캐스트를 받아 ffmpeg로 VP8 WebM을 만든다(선택 기능, ffmpeg 필요).ego lite = 사용자에게 보이는 브랜드/앱 이름. ego-browser = 에이전트가 치는 CLI 명령·스킬 이름. ego-browser-v2 = npm 패키지의 내부 이름(버전 0.1.0). 셋을 구분해 읽어야 문서가 헷갈리지 않는다.
이 프로젝트의 정체성이 담긴 5줄이다. 에이전트가 넘긴 코드 문자열을 비동기 함수로 감싸서, 브라우저 조종 헬퍼들을 함수 인자로 주입한 뒤 한 번에 실행한다(src/run.ts).
// src/run.ts — 에이전트 JS를 헬퍼 주입해 한 번에 실행
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
const names = Object.keys(context); // page, browser, taskSpaces, cdp, help ...
const values = Object.values(context);
const fn = new AsyncFunction(...names, `"use strict";\n${code}`);
await fn(...values); // 헬퍼가 지역변수처럼 보이는 채로 실행
헬퍼를 import하지 않는데도 에이전트 코드에서 page·browser가 전역처럼 보이는 이유가 바로 이것이다. 이름이 곧 API다. 그리고 "관찰→호출→관찰"을 CLI로 여러 번 왕복하는 대신, 예측 가능한 전 과정을 하나의 JS 블록에 담아 왕복을 없앤다 — 2장에서 본 속도·토큰 이득의 정체다. 스킬 문서(SKILL.md)는 이를 규범으로 못 박는다: "기본은 브라우저 작업 전체를 한 번의 Bash 호출로."
new Function("a","b","return a+b")처럼 문자열을 실제 함수로 만드는 자바스크립트 기능의 비동기 버전. ego lite는 이걸로 에이전트가 보낸 코드에 page 같은 헬퍼를 인자로 꽂아 실행한다. 강력하지만 위험한 기술이라(임의 코드 실행), 신뢰된 로컬 에이전트만 쓰는 이 맥락에서만 안전하다.
장시간 도는 런타임에서 CDP 세션은 자꾸 끊긴다(탭 전환·페이지 이동 등). browser-runtime.ts는 세션 id를 2초만 캐싱하고, "Session not found" 류 에러를 감지하면 조용히 재부착(re-attach) 후 1회 재시도한다. 에이전트는 끊김을 눈치채지 못한다.
// src/browser-runtime.ts — 세션 잃으면 재부착 후 재시도 (요약)
try {
return await rawCdp(method, params, session, timeoutMs);
} catch (error) {
const lost = SESSION_LOST.test(error?.message || "");
if (lost && !isBrowserLevel(method)) {
invalidateSession();
const fresh = await ensureSession(); // 새 sessionId 확보
return rawCdp(method, params, fresh, timeoutMs);
}
throw error;
}
에이전트는 픽셀 좌표로 클릭하지 않는다. 대신 snapshot()이 페이지를 텍스트로 요약하면서 클릭 가능한 요소마다 @21, @34 같은 ref 번호를 붙인다. 이 번호의 정체는 backendNodeId(브라우저 내부 DOM 노드 식별자)다. 스냅샷을 새로 뜰 때마다 ref 맵을 지우고 다시 만들기 때문에, ref는 "가장 최근 스냅샷 안에서만" 유효하다. 스냅샷 계산 자체는 커널 수준 커스텀 덕에 깊게 중첩된 iframe까지 네이티브 브라우저가 처리한다(driver/observe.ts → browserEgo().snapshot()).
README 태그라인의 "parallel"이 마케팅 수사가 아니라 코드로 존재한다. Task Space는 사용자 로그인 상태를 상속하는 격리 브라우징 컨텍스트(자체 탭을 가진다)이고, 각 Space에는 소유권(ownership)이 붙는다.
| 소유권 값 | 의미 |
|---|---|
agent | 에이전트가 소유·작업 중인 공간 |
user | 사람이 쓰는 공간 — 에이전트가 함부로 claim 못 함 |
agentDelegatedToUser | 에이전트가 잠시 사람에게 제어를 넘긴 상태(로그인·결제 등) |
에이전트는 자기 소유 Space에서만 일하고, 사람 소유 Space는 건드리지 않는다. 그래서 사람과 에이전트가 같은 브라우저를 쓰면서도 서로의 탭을 빼앗지 않는다. 로그인이 필요하면 handOffTaskSpace로 사람에게 넘기고, waitForAgentControl로 다시 받는다. 작업 완료(completeTaskSpace)는 브라우저 조작과 분리된 별도 Bash 호출로만 하도록 강제해, 미완 작업을 "다 됐다"고 착각하는 사고를 막는다.
구조를 읽는 핵심 감각: package/ego-browser는 "실행되는 코드"(당신이 npm run build로 만드는 CLI), skills/ego-browser는 "에이전트에게 주는 설명서 + 사이트 지식"이다. 빌드 시 build.mjs가 skills/ego-browser를 최종 산출물 안으로 복사해 하나로 묶는다. 즉 코드와 문서가 한 배포물로 함께 나간다.
x-com, google)에서 한 번 성공한 추출/조작 로직을 캡슐로 굳혀 재사용하는 폴더. manifest.json(도메인 매칭 + 툴 스키마) + notes/(마크다운 메모) + tools/(Node 실행) + browser-tools/(페이지 실행)로 구성. URL 진입 시 매칭되는 지식이 에이전트에 주입돼, "매번 처음부터 헤매지 않게" 한다. 에이전트가 경험을 축적하는 최소 단위다.| 주제 | 이 저장소에서 배울 수 있는 것 |
|---|---|
| CDP 직접 제어 | Playwright/Puppeteer 없이 순수 CDP로 page.locator·getByRole·waitForResponse 같은 고수준 API를 밑바닥부터 구현하는 법. "Playwright는 안에서 뭘 하나"를 배우는 최고의 레퍼런스. |
| 코드 주입 실행 모델 | new AsyncFunction으로 외부 코드에 의존성을 주입해 실행하는 패턴. 플러그인·샌드박스·DSL 런타임 설계에 그대로 응용 가능. |
| 자가 치유 세션 | TTL 캐시 + 에러 패턴 감지 + 투명 재시도로 끊기는 연결을 스스로 복구하는 법. 장수 데몬·소켓 클라이언트 설계의 정석. |
| 에러 택소노미 | 실패를 transient(재시도 가능) vs permanent(즉시 실패)로 분류해 wait 루프가 이에 따라 다르게 행동하게 하는 설계(element-resolver.ts). 무한 재시도/조기 포기를 동시에 막는다. |
| 에이전트 스킬 설계 | SKILL.md가 단순 사용법이 아니라 "에이전트를 신뢰성 있게 행동하게 만드는 규범집"이라는 점. 프롬프트 엔지니어링을 문서로 구조화하는 실전 사례. |
| 오픈/클로즈드 전략 | 핵심 해자는 감추고 접점만 여는 비즈니스-아키텍처 결합. 오픈소스로 생태계를 키우면서 수익성을 지키는 현실적 설계. |
클론 후 grep -ri "anthropic\|openai\|api.key\|chat/completions" src/를 돌려보라. 비교표 텍스트 몇 개 말고는 실제 API 호출이 없다는 걸 눈으로 확인하게 된다. "AI 제품"의 지능이 꼭 그 제품 안에 있으란 법은 없다는 감각을 얻는다.
helpers.ts의 page.goto() → driver/nav.ts → cdp-eval.ts → browser-runtime.ts의 sendCDPMessage까지, 한 동작이 프로토콜 메시지로 번역되는 전 과정을 손으로 짚어보면 "브라우저 자동화가 실제로 어떻게 동작하는가"가 손에 잡힌다.
| 구성 | 요구사항 |
|---|---|
| 브라우저 앱 | macOS 전용 (Apple Silicon arm64 / Intel x64 .dmg). Windows·Linux는 로드맵. |
| 하네스(CLI) | Node.js ≥ 22, ESM. 코어 조종 자체는 OS 독립적이지만 브라우저가 macOS라 실사용은 macOS. |
| 화면 녹화(선택) | ffmpeg 필요 (PATH 또는 EGO_BROWSER_FFMPEG_PATH). |
| 에이전트 | Claude Code · Codex · Cursor 등 로컬 코딩 에이전트 CLI 중 하나. |
# 스킬만 먼저 추가 — 첫 브라우저 작업 때 앱 설치를 유도한다
npx skills add citrolabs/ego-lite
# 또는 설치 스크립트로 DMG 자동 설치(+quarantine 제거+실행)
sh skills/ego-browser/scripts/install.sh
package/ego-browser/에서)npm run build # esbuild + rollup → dist/out/index.js 단일 파일
npm test # build → tsc --noEmit 타입체크 → node --test
npm run e2e # 실브라우저 Task Space e2e
# 로컬 실행 (실제 브라우저 작업엔 ego 런타임 필요)
node dist/out/index.js <<'JS'
await page.goto("https://example.com");
console.log(await page.title());
JS
node dist/out/index.js --doctor # 환경 진단
npm run build로 CLI는 만들 수 있지만, 실제 페이지 이동·클릭은 ego lite 브라우저 바이너리(globalThis.ego)가 있어야 동작한다. 바이너리 없이 실행하면 브리지 함수가 없어 브라우저 명령이 실패한다. 테스트는 FakeEgo 더블로 브라우저 없이 돌린다.
git clone --depth 1로 받아 AGENTS.md를 정독하고, grep -rc "sendCDPMessage" src/, grep -ri "mcp\|anthropic" src/로 "조종 코드는 많고 LLM 코드는 없다"를 숫자로 확인한다. 이 저장소의 정체를 스스로 규명하는 게 목표.
helpers.ts에서 에이전트가 부를 수 있는 헬퍼(page.*, browser.*, taskSpaces.*)를 전부 뽑아 기능별로 분류한 표를 만든다. 각 헬퍼가 어느 driver/*.ts로 내려가는지 화살표로 잇는다. "API 표면"을 읽는 훈련.
skills/ego-browser/learnings/x-com을 템플릿 삼아, 좋아하는 사이트(예: Hacker News)용 manifest.json + tools/를 작성한다. [data-testid] 대신 그 사이트의 안정적 셀렉터를 찾아 evaluateAll로 목록을 추출하는 함수를 짠다. 에이전트 지식을 캡슐화하는 감각을 익힌다.
Node + chrome --remote-debugging-port로 실제 크롬에 붙어, ego lite를 흉내 낸 초소형 하네스를 만든다. Target.attachToTarget으로 세션을 얻고 Runtime.evaluate로 document.title을 읽어 출력. ego의 browser-runtime.ts가 하는 일을 축소 재현하며 CDP를 체득한다.
Level 4의 미니 하네스에 2초 TTL 세션 캐시와 transient/permanent 에러 분류를 이식한다. 탭을 강제로 닫아 "Session not found"를 유발하고, 하네스가 조용히 재부착해 작업을 이어가는지 검증한다. 끊김에 강한 자동화의 원리를 손으로 확인.
Chrome DevTools Protocol 공식 문서에서 Target·Page·Runtime·Input·DOM 도메인을 훑는다. chrome --remote-debugging-port=9222로 띄우고 ws://에 직접 붙어 JSON-RPC를 주고받아 본다. 그다음 Puppeteer/Playwright 소스에서 CDPSession이 어떻게 이걸 감싸는지 비교하면, ego lite가 "왜 래퍼 없이 직접 갔는지"가 보인다.
new Function/AsyncFunction, vm 모듈, 그리고 "왜 임의 코드 실행이 위험한가/언제 안전한가"를 공부한다. ego lite가 로컬·신뢰된 에이전트라는 전제 위에서만 이 패턴을 쓰는 이유를 이해한다. DSL·플러그인 런타임 설계로 시야를 넓힌다.
Anthropic의 Claude Code 스킬/플러그인 구조, SKILL.md 규범, agentskills.io 스펙을 읽는다. ego lite의 marketplace.json·publish-ego-browser-skill.yml을 뜯어보며 "스킬을 만들어 여러 마켓에 배포"하는 실전 파이프라인을 재현해 본다.
자가 치유 세션·에러 택소노미·이벤트 큐·타임아웃/하드스톱 같은 "오래 도는 자동화가 안 죽게 하는 기술"을 모아 학습한다. browser-runtime.ts·ego-errors.ts·output-sink.ts를 교재로, 실패를 우아하게 다루는 런타임 설계를 익힌다.
| 용어 | 뜻 |
|---|---|
| harness (하네스) | 대상을 감싸 바깥에서 조종·실행하게 해주는 얇은 계층. 여기선 "에이전트 JS ↔ 브라우저 CDP" 통역·실행기. |
| CDP | Chrome DevTools Protocol. 크롬을 프로그램으로 원격 조종하는 공식 JSON-RPC 프로토콜. |
| agent skill | 에이전트(Claude Code 등)에게 특정 작업 수행법을 알려주는 패키지. SKILL.md + 스크립트로 구성. |
| Task Space | 로그인 상태를 상속하는 격리 브라우징 컨텍스트. 소유권(agent/user)이 붙어 사람·에이전트 충돌을 막음. |
| @N ref | 스냅샷이 클릭 가능 요소에 붙이는 참조 번호(= backendNodeId). 최신 스냅샷 안에서만 유효. |
| snapshot | 페이지를 에이전트가 읽기 좋은 텍스트로 요약한 것. 커널 커스텀 브라우저가 iframe까지 처리. |
| new AsyncFunction | 문자열을 비동기 함수로 만들어 헬퍼를 주입해 실행하는 JS 기법. ego lite의 "코드 한 덩어리 실행"의 정체. |
| transient / permanent | 재시도 가능한 일시적 실패 vs 즉시 실패해야 하는 영구적 실패. wait 루프가 이 분류에 따라 행동. |
| learnings | 사이트별로 성공한 조작 로직을 굳혀 재사용하는 지식팩. 에이전트 경험 축적의 최소 단위. |
| momentum (모멘텀) | TrendShift 순위의 굵은 숫자. 누적 별점이 아니라 "지금 화제가 번지는 속도". |
| ESM | ECMAScript Modules. import/export 기반 JS 표준 모듈 시스템(CommonJS의 require 대체). |
| 오픈/클로즈드 하이브리드 | 핵심 해자는 클로즈드로 숨기고 에이전트 접점만 오픈소스로 여는 전략. |
ego-browser-v2 0.1.0 · ★47)AGENTS.md(아키텍처, 필독) · README.md(비전·비교표) · skills/ego-browser/SKILL.md(에이전트 규범)package/ego-browser/src/run.ts(코드 주입 실행) · browser-runtime.ts(CDP·세션) · element-resolver.ts(요소 해석) · helpers.ts(헬퍼 단일 진실원) · driver/observe.ts(스냅샷)npx skills add citrolabs/ego-lite (macOS + Claude Code/Codex 필요)new Function 코드 실행 모델