EZO Watcher는 사용자 프로젝트에 설치되는 경보 벽 및 페이저입니다. 구성은 코드로 .watcher/에 저장되고, 로컬 Node 프로세스 하나가 실행되며, 계정이 필요 없습니다. 당신의 임무는 전체 설치를 완전히 검증하는 것이며, 단지 제안 목록을 제공하는 것이 아닙니다.
CLI가 진실의 원천입니다. 아래의 모든 주제는 watcher skills <topic> 명령어로 출력됩니다 (주제: install, discover, sources, channels, hosting, cloudflare, netdata, operate, fix, telemetry). 또는 이 파일 옆의 references/<topic>.md 파일을 읽으십시오. 모든 명령은 watcher <verb> 형태로 실행하며, doctor와 같은 단독 단어는 호스트 에이전트 자체의 /doctor와 충돌할 수 있으므로 절대 사용하지 마십시오.
CLI 설치하기
CI=1 npm_config_yes=true npm i -g ezo-watcher
watcher --version
전역 설치 없이: npx -y ezo-watcher <verb> 명령어로 동일한 CLI를 실행할 수 있습니다. 소스 체크아웃에서: npm ci && npm run build && npm link. Node 24+ 필요. GitHub에서 최신 메인 설치를 포함한 전체 세부 사항: watcher skills install.
워크플로우
.watcher/ 디렉토리가 이미 존재한다면, 먼저 watcher doctor --json과 watcher scan --json을 실행한 후, 순위가 부족하다고 표시하는 항목만 추가하십시오. 이미 작동 중인 설치 위에 다시 init을 실행하지 마십시오.
- Init. 프로젝트 루트에서
watcher init을 실행합니다. 멱등적이며, 프롬프트를 표시하지 않습니다..watcher/config.json,.watcher/.env(0600 권한),.watcher/data/디렉토리를 생성하고, 마지막 두 개를 .gitignore에 추가하며, 7717부터 사용 가능한 포트를 선택하고, 첫 번째 doctor 요약을 출력합니다. - Scan.
watcher scan --json→{signals, suggestedCommands}. 소규모 수동 레이블링 샘플에서 프로토타입은 19개의 HTTP/TLS 포인트 중 15개를 찾았지만, 10개의 정적 분석 포인트 중 2개만 찾았습니다 (watcher skills discover참조): 명령어를 후보로 간주하고, 아래 코드 읽기를 통한 정적 분석 우선 접근 방식을 수행하십시오. - 순위에 따라 선택 (다음 섹션). 실제 포인트당 하나의 소스만 추가하십시오. 녹색으로 보이기 위해 소스를 임의로 생성하지 마십시오.
- 추가. 선택한 각 소스에 대해:
watcher add <kind> --id <id> … --found-at <file:line> --read "<what it proves>".--found-at/--read는 출처 정보이며,watcher doctor는 이 정보 없이 경고를 표시합니다.--dry-run을 사용하면 미리 볼 수 있습니다. 그런 다음 하나의 채널:watcher add channel <type> --id <id> …(watcher skills channels참조). 자격 증명을 사용할 수 없는 경우(헤드리스 박스, 벤더 계정 없음, 페이저를 선택하지 않은 사용자)는 자격 증명이 필요 없는 폴백을 추가하십시오:watcher add channel file --id local. 이는.watcher/data/아래에 알림당 JSON 라인 한 개를 작성하며, 실제 테스트 가능한 채널이지 스텁이 아닙니다.watcher add … --replace는 기존 id를 덮어씁니다.watcher rm <id>는 제거합니다. - Doctor 루프.
watcher doctor --json실행;ok:false인 경우, 첫 번째fail의next를 사용하여 수정하고 다시 실행합니다.channel.missing경고가 있고 사용자가 전화 알림을 원한다면, 지금 8단계의 채널을 추가하고 다시 돌아오십시오. 종료 코드 0은 통과, 1은 실패, 64는 사용법 오류입니다. - 실행.
watcher run --detach(또는watcher service install을 사용하여 재부팅 후에도 유지). 그런 다음watcher doctor --live --json으로 실행 중인 서버를 읽습니다. - 검증.
watcher doctor --live --prove --json을{"ok": true, "live": true}를 반환할 때까지 실행합니다.--prove는 각 소스의 자체 임계값을 초과하도록 이동시키고, 규칙이 실제로 플립되지 않으면 실패합니다(source.assertion-not-red; 빈약한 http-probe 어설션은source.assertion-vacuous로 실패). http-probe 응답은 변조되고, 하트비트는 누락된 실행과 유예 기간 이후 평가되며, 호스트 읽기는 디스크/메모리/로드 임계값을 초과하도록 이동되고, TCP 연결은 실패하며, 만료는pageDays내에 속합니다. 알림이 발신자가 보고하는 종류(grafana, vmalert, sentry, netdata, feed, webhook)는source.prove-unsupported로 명명된 건너뛰기이며, 실패가 아닙니다. 프로젝트에 서버와 예약된 작업이 모두 없는 경우,watcher add host --id host를 추가하십시오(머신 자체, 아무것도 설치하지 않고 로컬로 읽음) — 그리고 검증합니다. 서버, 예약된 작업 및 감시할 호스트가 모두 없는 프로젝트만watcher doctor --no-runtime-surface --json을 실행합니다 →{"ok": true, "live": false, "reason": "no-runtime-surface"}, 명확하게 보고됩니다. 구성된 소스는 항상--no-runtime-surface보다 우선합니다(그러면 보고서는doctor.no-runtime-surface-ignored경고를 표시합니다). 검증되지 않은 설치를 완료되었다고 호출하지 마십시오. - 페이지. 채널 하나를 추가하고
watcher test-alert를 실행합니다. 중요한 기기에 도착했는지 확인합니다. 자격 증명 누락은 명명된 건너뛰기이지 통과가 아닙니다. - 호스팅 (선택 사항). 사다리는 local → service → Docker/VPS → Cloudflare Tunnel (기본값: "내 Cloudflare 키로 호스팅") → Containers 베타입니다.
watcher skills hosting,watcher skills cloudflare. - 다음 사용을 위해 스킬 설치.
watcher skills install --target all --dir .명령어를 실행하여 스킬을 프로젝트에 기록합니다. Claude Code에서는 이후 **/reload-skills**를 실행하십시오. 세션 중간에 생성된 최상위 skills 디렉토리는 따로 로드되지 않습니다.
Day two — 경보 벽 읽기, 확인, 댓글, 음소거, 보류, 재확인 — 은 watcher skills operate을 참조하십시오.
문제 발생 시
인시던트는 증거가 있는 주장이지 알림이 아닙니다. 전체 워크플로우는 watcher skills fix입니다:
watcher status --brief로 한 줄 요약을 보거나,watcher incidents --output json으로 키를 확인합니다 (MCP:watch_state,list_incidents).get_fix_context { key }(CLI:watcher incident <key> --fix-context): 인시던트, 소스 및 대상 구성(자격 증명은 환경 변수 이름으로 표시), 규칙의 어설션 및 실패한 어설션, 엔드포인트가 발견된 위치, 마지막 양호 관찰 옆의 마지막 불량 관찰, 검사를 다시 실행하는 정확한 명령어, 그리고next를 제공합니다.- 해당 명령어에서 문제를 재현합니다. 임계값은 원인이 아닙니다.
- 원인을 수정하고, 수정 사항이 적용되도록 재배포 또는 재시작합니다.
verify_fix { key, by }(CLI:watcher recheck <key> --wait): 재확인하고, 소스의 새로운 응답을 기다리며, 모든 경보가 해결되면 확인을 기록합니다. 또는 여전히 실패하는 어설션을 알려 수정을 수정할 수 있습니다. 재확인이 녹색이 되기 전에 인시던트를 해결된 것으로 표시하지 마십시오.park는 수정 사항이 병합되었지만 아직 라이브가 아닌 경우 사용하고,confirm_resolution은 소스가 이미 인시던트를 종료한 경우 사용합니다.- 발견한 내용에 대해
comment를 남깁니다. 조용한 수정은 다음 사람에게 아무런 단서를 남기지 않습니다.
순위: 무엇을 감시할지, 순서대로
- 프로덕션 프로세스의 가장 깊은 준비 상태 경로, 종속성이 중단될 때 변경되는 필드를 어설션합니다. 하드코딩된
{"ok": true}/{"status": "ok"}는 절대 사용하지 마십시오. 이는 활성 신호(liveness)이며, 중요한 실패에 대해 빨간색으로 변할 수 없습니다. - 플랫폼이 이미 선언한 준비 상태 프로브:
/readyz,/health/ready, docker-compose의healthcheck, Kubernetes의readinessProbe, fly/railway/render의 health 경로. 동일한 경로와 포트로 외부에서 미러링합니다. - 서버 없음 → 예약된 작업당 하나의 하트비트. 침묵이 신호입니다.
- 서버 및 예약된 작업이 모두 없음 →
watcher add host --id host(로드, 메모리, 여유 공간, 선택적으로 pid 파일; 아무것도 설치하지 않음) 를 추가하고 검증합니다. 서버, 예약된 작업 및 감시할 호스트가 모두 없는 경우만 →watcher doctor --no-runtime-surface --json,NO_RUNTIME_SURFACE보고, 중지합니다. 구성된 소스는 항상--no-runtime-surface보다 우선합니다. 소스를 절대 임의로 만들지 마십시오. - 그 다음 이미 존재하는 시스템 — Sentry, Grafana, Netdata, 인바운드 발신자 — 자격 증명이 필요한. 자격 증명 누락은 코드와
next가 있는 명명된 건너뛰기이지, 조용한 통과가 아닙니다.
정적 분석 우선 (스캐너가 놓치는 것)
코드에서 다음 여섯 가지 클래스를 읽으십시오. 각각은 watcher add heartbeat 또는 watcher add webhook --stale-after가 됩니다:
- 설치 시 생성되는 스케줄 —
install.sh/setup.*에서 plist, unit 또는 crontab을 작성하는 heredoc,launchctl load,systemctl enable,crontab쓰기. - 런타임에 생성되는 launchd/systemd/cron —
.plist템플릿,OnCalendar=,StartInterval,KeepAlive,node-cron,schedule(, 작업 주변의setInterval, celery beat. 작업당 하나의 하트비트 (--every/--schedule+--grace); N개의 작업은 N개의 소스를 의미합니다. - 풀 큐 워커 —
worker,queue,bullmq,sqs,claim,lease,dequeue. 실패는 포트가 아닌 큐 깊이 또는 진행 부재입니다. 성공 경로에서 하트비트를 보내거나state: failing을 포함한checks.list항목을 푸시합니다. - 제품 자체 구성의 부실 —
staleAfterSec,presenceTtlSec,maxAge,ttl,refreshInterval,lastRunAt. 동일한 기간을 적용합니다:watcher add webhook --id <sender> --token-env <ENV> --stale-after-sec <sec>. - 상태 디렉토리 쓰기 가능 여부 —
mkdir,state/,data/, sqlite, 잠금 파일. 성공적인 쓰기 후에만 하트비트를 보냅니다. 단순한test -w는 소스가 아닙니다. - 코드 상수로 유지되는 종속성 엔드포인트 —
process.env.X ?? "https://…", host:port 리터럴, gRPC/ClickHouse/LLM 기반 주소.watcher add http-probe(HTTPS GET) 또는watcher add tcp-probe --host --port,--found-at는 상수 위치.
작업의 성공 경로에 하트비트 핑을 배치하십시오 — POST /ingest/heartbeat/<id>, 실패 실행 시 /fail, 특정 종료 코드에 대해 /<exit-code>. watcher add heartbeat는 명명된 변수에 값이 아직 없을 때 .watcher/.env (0600)에 토큰을 생성하거나, 전달한 --secret-value를 쓰며, 정확한 라인을 출력합니다 (아래 $NIGHTLY_TOKEN은 --id nightly에 대해 선택된 이름입니다; 전달한 --token-env는 대신 출력할 변수입니다):
set -a; . .watcher/.env
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>?token=$NIGHTLY_TOKEN" # 성공적인 실행 후
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>/fail?token=$NIGHTLY_TOKEN" # 실패한 실행 후
curl -fsS -m 10 "${WATCHER_URL:-http://127.0.0.1:7717}/ingest/heartbeat/<id>/<exit-code>?token=$NIGHTLY_TOKEN" # 작업의 종료 코드와 함께
단일 작업이 아닌 수집기는 전체 목록을 푸시합니다: POST /ingest/<source> with {"checks":{"list":[{"id":"…","service":"…","state":"ok","lastRunAt":"…"}]}} — 전체 형태와 상태는 watcher skills sources에 있습니다.
health 경로가 리터럴만 반환하는 경우, 더 깊은 경로를 찾거나 추가하십시오: GET /readyz → 종속성이 응답하면 200 {"db":{"ok":true}}, 응답하지 않으면 503 {"db":{"ok":false}}. 사용자 프로젝트 편집은 허용됩니다 — 당신은 파일을 작성하는 에이전트입니다. 그런 다음 절대 {"ok":true}가 아닌 변경되는 필드를 어설션하십시오.
규칙
- Watcher 자체의
/healthz를 소스로 가리키지 마십시오 —source.self-probe가 거부합니다. - 소스는 플립될 수 있는 것을 어설션해야 합니다. 단순한 200은 활성 신호(liveness)에 불과합니다 (
source.bare-200);watcher doctor --live --prove가 게이트이며,--found-at는 경고입니다 (source.untraced). - 비밀은 구성에서 환경 변수 이름으로만, 값은 오직
.watcher/.env에만 존재합니다. 스캔 중에.env값을 절대 읽지 말고,.watcher/.env또는.watcher/data/를 커밋하지 마십시오. - 하나의 작동하는 채널이 다섯 개의 구성된 채널보다 낫습니다.
watcher test-alert로 검증하십시오. 자격 증명이 전혀 없습니까?watcher add channel file --id local을 추가하고 검증하십시오: 파일은 실제 채널이며, 자격 증명 누락은 명명된 건너뛰기이지 통과가 아닙니다. - 입증된 것을 보고하십시오 — 추가된 소스, 명령어 출력 및 모든 명명된 건너뛰기. 에이전트가 단계를 완료할 수 없는 경우(자격 증명 누락, 영역 없음), 그 이유를 한 줄로 말하십시오.
단계별로 더 자세한 정보가 필요할 경우: watcher skills discover (전체 신호 카탈로그 및 정적 분석 체크리스트), watcher skills sources (모든 종류, 플래그, 예제), watcher skills channels, watcher skills hosting, watcher skills cloudflare, watcher skills netdata, watcher skills operate (MCP 도구 및 인시던트 트라이지).