webctl
명령줄 인터페이스(CLI)를 기반으로 구축된 AI 에이전트 및 인간을 위한 브라우저 자동화 도구입니다.
pip install webctl
webctl navigate "https://example.com"
webctl click "Sign in"
...
왜 MCP 대신 CLI인가?
MCP 브라우저 도구에는 근본적인 문제가 있습니다. 바로 서버가 컨텍스트(Context)에 들어가는 내용을 제어한다는 점입니다. Playwright MCP를 사용하면 모든 응답에 전체 접근성 트리(Accessibility Tree)와 콘솔 메시지가 포함됩니다. 몇 번의 페이지 쿼리만으로도 컨텍스트 창(Context Window)이 가득 차게 됩니다. 이는 성능 저하, 컨텍스트 손실 및 비용 상승으로 이어집니다.
CLI는 이를 뒤집습니다. 사용자가 컨텍스트에 들어가는 내용을 제어합니다.
webctl snapshot --interactive-only --limit 30
webctl snapshot --within "role=main"
...
필터링 외에도 CLI는 다음과 같은 기능을 제공합니다:
벤치마크 (Benchmarks)
4가지 실제 웹 작업에 대해 webctl과 agent-browser (Vercel의 브라우저 CLI)를 직접 비교했습니다. 두 도구 모두 Claude Opus를 구동 에이전트로 사용합니다.
| 작업 (Task) | webctl | | | | agent-browser | | | |
|---|
| 점수 (Score) | 턴 (Turns) | 토큰 (Tokens) | 비용 (Cost) | 점수 (Score) | 턴 (Turns) | 토큰 (Tokens) | 비용 (Cost) |
| ... | | | | | | | | |
webctl은 4가지 모든 작업에서 더 낮은 비용으로 더 높은 품질 점수를 달성했습니다. 랜드마크 인식 스냅샷 (Landmark-aware snapshots)은 내비게이션/사이드바를 축소하고 콘텐츠를 우선시하며, 자동 폴백 (automatic fallbacks: 쿠키 거부, 스크롤하여 찾기, 오버레이 재시도) 기능은 에이전트의 추가 턴 없이도 복잡한 사이트를 처리합니다.
<details>
<summary>빠른 속도의 비결</summary>
- 구조화된 데이터 우선 (Structured data first):
navigate는 접근성 트리 (accessibility tree)를 건드리기 전에 JSON-LD/Open Graph 메타데이터 (가격, 평점, 저자 등)를 추출합니다. 이는 전체 스냅샷 없이도 질문에 답하기에 충분한 경우가 많습니다.
- 랜드마크 인식 필터링 (Landmark-aware filtering): 내비게이션/푸터/사이드바 랜드마크를 축소하여 에이전트가 브라우저 UI (chrome)가 아닌 콘텐츠를 볼 수 있게 합니다.
- 스마트 네트워크 유휴 상태 감지 (Smart network idle): 미디어 스트림과 웹소켓 (websockets)을 무시하는 맞춤형 로드 감지 기능을 제공합니다. 비디오/분석 도구가 포함된 페이지도 로딩을 방해하지 않습니다.
- 한 번의 턴으로 실행 및 관찰 (Act + observe in one turn): 클릭/타이핑 시
--snapshot 플래그를 사용하면 업데이트된 페이지 상태를 반환하여 왕복 시간 (round-trip)을 절약합니다.
</details>
<details>
<summary>벤치마크 상세 정보</summary>
설정 (Setup): 각 작업은 단일 도구 (webctl 또는 agent-browser)를 사용하는 Claude Opus를 기반으로 실행되며, $1의 예산 제한이 있고 인간의 개입은 없습니다. 품질은 별도의 Claude 평가 호출을 통해 0~10점으로 측정됩니다.
작업 (Tasks):
- Amazon 제품 조회: amazon.de에서 특정 제품의 가격과 배송 정보를 찾습니다.
- Spiegel.de 헤드라인: 독일 뉴스 사이트에서 상위 5개 헤드라인을 추출합니다.
- Google Maps 레스토랑: 베를린에서 별점 4점 초과인 비건 중식 레스토랑을 찾습니다.
- DuckDuckGo 검색: 펭귄 팬 사이트를 검색하고 상위 3개 결과를 반환합니다.
직접 벤치마크를 실행해 보세요: bash benchmarks/bench_run.sh
</details>
에이전트 통합 (Agent Integration)
옵션 A: 스킬 설치 (Claude Code, Cursor, Codex, Gemini CLI, Copilot, Goose, Windsurf, OpenCode에서 작동)
npx skills add cosinusalpha/webctl
이 명령은 스킬 (skill) 파일을 설치합니다. 사용자의 에이전트 (agent)는 처음 사용할 때 webctl 패키지를 자동으로 설치합니다.
옵션 B: pip를 통한 설치
pip install webctl
webctl setup
webctl init
...
webctl init은 Claude Code 및 Goose를 위한 온디맨드(on-demand) **스킬 (skills)**과 Gemini, Copilot, Codex를 위한 경량 **프롬프트 (prompts)**를 생성합니다.
<details>
<summary>지원되는 에이전트 및 파일 위치</summary>
| 에이전트 (Agent) | 형식 (Format) | 위치 (프로젝트) | 위치 (글로벌) |
|---|
claude | Skill | .claude/skills/webctl/SKILL.md | ~/.claude/skills/webctl/SKILL.md |
| ... | | | |
</details>
왜 스킬 (skills)인가요? 스킬은 온디맨드 (on-demand) 방식으로 로드됩니다. 즉, 에이전트가 실제로 웹 자동화 (web automation)를 수행할 때만 webctl 지침을 읽습니다. 이를 통해 다른 작업을 위한 컨텍스트 (context)를 깨끗하게 유지할 수 있습니다.
특정 에이전트 선택:
webctl init --agents claude,gemini
webctl init --agents claude-noskill
</details>
만약 에이전트가 생성된 파일을 자동으로 감지하지 못한다면, 시스템 프롬프트 (system prompt)에 다음 내용을 추가하세요:
웹 브라우징을 위해 webctl CLI를 사용하세요. 지침을 확인하려면 webctl agent-prompt를 실행하세요.
참고: 이미 브라우저 MCP가 구성되어 있다면, 충돌을 방지하기 위해 이를 비활성화하세요.
명령어 (Commands)
탐색 및 관찰 (Navigation & Observation)
webctl navigate "https://..."
webctl navigate "https://..." --snapshot
webctl navigate "https://..." --read
...
상호작용 (Interaction)
webctl click "Submit"
webctl click @e3
webctl click "Submit" --snapshot
...
대기 조건 (Wait Conditions)
webctl wait network-idle
webctl wait 'exists:role=button name~="Continue"'
webctl wait 'url-contains:"/dashboard"'
세션 및 콘솔 (Session & Console)
webctl status
webctl save
webctl console --count
...
핵심 개념 (Core Concepts)
세션 (Sessions)
명령어 간에 브라우저가 열린 상태로 유지됩니다. 쿠키는 디스크에 영구 저장됩니다.
webctl start
webctl start --mode unattended
webctl -s work start
요소 쿼리 (Element Queries)
ARIA 역할 (ARIA roles)을 기반으로 한 의미론적 타겟팅 — CSS 리팩토링 시에도 안정적입니다:
role=button
role=button name="Submit"
role=button name~="Submit"
출력 제어 (Output Control)
webctl snapshot
webctl --quiet navigate "..."
webctl --result-only --format jsonl navigate "..."
아키텍처 (Architecture)
┌─────────────┐ Unix Socket ┌─────────────┐
│ CLI │ ◄────────────► │ Daemon │
│ (webctl) │ JSON-RPC │ (browser) │
...
- CLI: 상태를 유지하지 않으며 (Stateless), 데몬(Daemon)으로 명령을 전송합니다.
- Daemon: 브라우저를 관리하며, 첫 번째 명령 시 자동으로 시작됩니다.
- Socket:
$WEBCTL_SOCKET_DIR 또는 OS 기본값 (아래 참조)
- Profiles:
~/.local/share/webctl/profiles/
<details>
<summary>소켓 경로 (Socket paths)</summary>
| 플랫폼 | 기본값 |
|---|
| Linux | /run/user/<uid>/webctl-<session>.sock |
| ... | |
WEBCTL_SOCKET_DIR 환경 변수로 디렉토리를 재정의할 수 있습니다.
</details>
</details>
보안 (Security)
webctl은 CLI 명령이 데몬 (daemon)과 동일한 사용자로부터 전달되었는지 확인합니다:
| 플랫폼 (Platform) | 메커니즘 (Mechanism) | 강도 (Strength) |
|---|
| Linux | SO_PEERCRED | 커널 강제 UID 확인 |
| ... | | |
모든 플랫폼은 커널 수준의 자격 증명 검증 (credential verification)을 사용합니다. 이를 통해 다른 사용자가 사용자의 브라우저 세션을 제어하는 것을 방지합니다.
<details>
<summary>고급 설정 (Advanced Configuration)</summary>
사용자 정의 브라우저 (Custom Browser)
사용자 정의 Chromium 바이너리를 사용합니다 (관리형 설치를 건너뜁니다):
webctl config set browser_executable_path /path/to/chrome
...
버전이 일치하지 않더라도 전역 Playwright 사용을 허용합니다 (선택 사항, 주의해서 사용하십시오):
webctl config set use_global_playwright true
재정의 설정 삭제:
webctl config set browser_executable_path null
webctl config set use_global_playwright false
프록시 설정 (Proxy Configuration)
기업 네트워크 또는 CI 환경을 위해 HTTP/HTTPS 프록시를 설정합니다.
환경 변수를 통한 설정 (CI 환경에 권장):
export HTTPS_PROXY=http://proxy.corp.com:8080
export NO_PROXY=localhost,*.internal.com
...
설정 파일을 통한 설정 (영구적):
webctl config set proxy_server http://proxy.corp.com:8080
webctl config set proxy_bypass localhost,*.internal.com
...
우선순위: WEBCTL_PROXY_SERVER > HTTPS_PROXY > HTTP_PROXY > 설정 파일
설정 확인 및 삭제:
webctl config show
webctl config set proxy_server null
명령 로깅 (Command Logging)
모든 webctl 명령과 그 출력을 shell-transcript 형식으로 기록합니다:
export WEBCTL_LOG=/tmp/webctl.log
webctl navigate "https://example.com"
webctl click "Submit"
...
각 명령은 $ 접두사와 함께 출력 내용이 파일에 추가되어 기록됩니다.
도메인 정책 (Domain Policy)
브라우저가 탐색할 수 있는 도메인을 제한합니다. 설정 파일을 직접 편집하십시오 (webctl config show를 사용하여 경로를 찾을 수 있습니다):
{
"domain_policy": {
"enabled": true,
...
모드 (Modes):
| 모드 (Mode) | 동작 (Behavior) |
|---|
allow | 화이트리스트 (Whitelist) — 나열된 도메인만 허용 |
| ... | |
도메인 패턴은 glob 와일드카드(예: *.example.com)를 지원합니다. 내장된 기본 거부 목록 (default deny list)은 모드와 관계없이 알려진 악성 패턴을 차단합니다.
컨테이너 배포 (Container Deployment)
호스트와 컨테이너 사이(또는 컨테이너 간)에 Unix 소켓 (Unix socket)을 공유하려면 WEBCTL_SOCKET_DIR을 설정하십시오.
컨테이너에 데몬 (Daemon), 호스트에 클라이언트 (Client):
mkdir -p /tmp/webctl-ipc
docker run -d --name webctl-daemon \
...
-u $(id -u):$(id -g)를 사용하면 소켓 파일의 소유권이 호스트 사용자로 지정됩니다.
별도의 컨테이너에 데몬과 클라이언트가 각각 실행되는 경우:
docker volume create webctl-ipc
docker run -d --name webctl-daemon \
...
UID 매칭이 필요하지 않습니다 — 두 컨테이너가 동일한 사용자로 실행됩니다.
</details>
<details>
<summary>uv를 이용한 전역 설치 (Global installation with uv)</summary>
uv tool install webctl
uv tool run webctl
</details>
<details>
<summary>Linux 시스템 의존성 (Linux system dependencies)</summary>
playwright install-deps chromium
</details>
라이선스 (License)
MIT