Skip to main content
Glama

earmark

실행 중인 앱에서 요소를 클릭하고 무엇이 바뀌어야 하는지 말하면, 코딩 에이전트가 CSS 선택자, 소스 파일과 줄, 컴포넌트 경로, 계산된 스타일, 박스 지오메트리를 받습니다 — "오른쪽 버튼이 잘못 보인다" 대신에.

어떤 프레임워크에서도 동작합니다. 오버레이에 빌드 단계가 필요 없습니다.

┌─ browser ──────────────┐        ┌─ broker ────────┐        ┌─ agent ─────────┐
│ click → annotate       │ POST   │ store + SSE     │  MCP   │ list / watch    │
│ pins, panel, markdown  │───────▶│ long-poll       │◀──────▶│ ask / resolve   │
│                        │◀───────│ .earmark/*.json │        │ dismiss         │
└────────────────────────┘  SSE   └─────────────────┘        └─────────────────┘

30초 안에 사용해 보기

npm install && npm run example

http://127.0.0.1:5173/examples/vanilla/를 열고, 도구 모음(오른쪽 아래)의 화살표를 클릭하거나 alt+a를 누른 다음, 페이지의 아무 요소나 클릭하세요.

랜딩 페이지와 전체 가이드는 http://127.0.0.1:5173/site/에서 함께 제공됩니다 — 소스는 site/index.html에 있으며, 의존성이 없는 단일 자체 포함 파일입니다.

실시간 에이전트 동기화를 위해 두 번째 터미널에서 브로커를 실행하세요:

npm run server

Related MCP server: vibe-annotations

설치

npm install -D earmark
import { createEarmark } from 'earmark';

if (import.meta.env.DEV) {
  createEarmark();
}

번들러 없이:

<script type="module" src="/node_modules/earmark/src/index.js" data-earmark-auto></script>

옵션

createEarmark({
  endpoint: 'http://127.0.0.1:7331', // or false for copy-paste only
  hotkey: 'alt+a',
  theme: 'auto',                     // 'auto' | 'light' | 'dark'
  persist: true,                     // keep annotations across reloads
  onAnnotate: (annotation) => {},
});

엔드포인트는 기본적으로 로컬 브로커를 사용하며, 아무것도 수신하지 않으면 조용히 저하됩니다 — 오버레이는 여전히 동작하고, 동기화 점만 회색으로 변합니다.


사용법

도구

기능

요소를 클릭하세요. Shift-클릭으로 더 추가하고, 클릭하여 완료합니다.

T

텍스트를 선택하세요 — 정확한 문자열은 에이전트에게 넘길 수 있는 가장 grep하기 쉬운 것입니다.

영역을 드래그하세요. 내부의 모든 요소를 보고하거나, 빈 영역을 표시합니다.

움직이는 모든 것을 고정합니다 — CSS 애니메이션, element.animate(), <video>, <audio>.

패널: 검토, 삭제, 에이전트에게 답변, 마크다운 복사.

⌘↵는 주석을 저장하고, esc는 취소하며, alt+a는 선택을 토글합니다. 각 주석은 high, normal 또는 low 우선순위로 표시할 수 있으며, high는 에이전트에게 먼저 정렬됩니다.


복사-붙여넣기 모드

패널에서 마크다운 복사를 클릭하고 에이전트에 붙여넣으세요:

## UI feedback — 1 annotation

- **Page:** http://localhost:5173/dashboard
- **Viewport:** 1440×900 @2x, dark mode
- **Framework:** react

### 1. Export button padding is too tight — needs 10px 16px

- **Element:** `<button>` <ExportButton>
- **Selector:** `[data-testid="export-btn"]`
- **Source:** `src/components/Card.tsx:42:7`
- **Component path:** App › Dashboard › Card › ExportButton
- **Text:** "Export"
- **Box:** 66×37 at (194, 376)
- **Computed:** padding: 7px 13px; border-radius: 8px; font-size: 13px
- **Ancestors:** div.row ← section.card ← main

에이전트 동기화 모드 (MCP)

claude mcp add earmark -- npx -y earmark-mcp

또는, 프로젝트의 .mcp.json에 작성하려면:

npx earmark-mcp init

그 하나의 프로세스는 MCP 서버 그리고 브라우저가 통신하는 브로커를 함께 실행합니다. 무언가가 작동하지 않을 때, 그 이유를 물어보세요:

npx earmark-mcp doctor
✓ Node version: v24.12.0
✓ sqlite backend: available
✓ MCP registration: earmark is registered in .mcp.json
✓ Broker: responding on http://127.0.0.1:7331 — 1 annotations, 2 sessions
✓ Browser overlay: http://localhost:5173/ (1 annotations)

실패한 각 검사는 수정하는 명령을 출력하고, doctor는 0이 아닌 종료 코드로 종료되므로 CI에서 사용할 수 있습니다.

도구

도구

용도

earmark_list_annotations

대기 중인 작업, 마크다운 형식(또는 format: "json"); session으로 범위 지정

earmark_watch_annotations

사람이 주석을 달 때까지 차단합니다

earmark_get_annotation

전체 답글 스레드가 포함된 하나의 주석

earmark_list_sessions

열린 브라우저 탭과 주석이 달린 경로

earmark_get_session

생성한 모든 주석이 포함된 하나의 탭

earmark_acknowledge

"읽었습니다. 처리 중입니다" — 핀이 파란색으로 변합니다.

earmark_ask

명확한 질문을 하세요 — 핀이 호박색으로 변합니다.

earmark_resolve

요약과 함께 완료로 표시 — 핀이 초록색으로 변합니다.

earmark_dismiss

사람이 볼 수 있는 사유와 함께 거절합니다

earmark_clear

모두 삭제

earmark_status

오버레이가 연결되어 있나요? 어떤 엔드포인트를 사용해야 하나요?

이것이 가능하게 하는 수정 루프:

watch → acknowledge → read the source path → edit the file → resolve → watch

acknowledge는 느린 작업에서 중요합니다: 그것 없이는, 리팩터링 도중의 에이전트는 당신을 무시한 에이전트와 똑같이 보입니다. 파란 핀은 작업을 시작했음을 의미하고, 초록 핀은 실제로 완료되었음을 의미합니다.

피드백이 모호할 때는 추측하지 말고 ask를 사용하세요. 질문이 핀에 표시되고, 사람의 답변이 다음 watch를 깨웁니다.

상태

openacknowledgedresolved이며, 에이전트가 사람을 기다릴 때는 needs-input, 거절할 때는 dismissed입니다. 핀은 색으로 구분됩니다: 주황색, 파란색, 초록색, 호박색, 회색.

세션

세션은 페이지 로드가 아니라 브라우저 탭 하나입니다 — id는 sessionStorage에 저장되므로 새로고침 후에도 유지됩니다. 주석은 자체 page.url을 가지므로, 세 개의 경로를 오간 세션은 에이전트에게 서로 다른 세 개의 경로를 가진 하나의 그룹을 제공합니다.

SPA 탐색도 추적됩니다: pushState, replaceState, popstate, hashchange 모두 세션의 경로 목록을 업데이트합니다. 탭은 SSE 스트림이 열려 있는 동안만 연결된 것으로 간주됩니다.

curl http://127.0.0.1:7331/sessions

소스 파일 경로

선택자는 에이전트에게 무엇을 grep할지 알려줍니다. 소스 경로는 정확히 어디를 봐야 하는지 알려줍니다, 이는 한 번의 수정과 세 번의 grep의 차이입니다.

React 19는 런타임 _debugSource fiber 필드를 제거했으므로, 이 작업은 빌드 시에 수행됩니다:

// vite.config.js
import earmark from 'vite-plugin-earmark';

export default {
  plugins: [react(), earmark()],
};

모든 내장 JSX 요소는 vite dev 중에 data-earmark-src="src/Card.tsx:42:7"를 받습니다. 플러그인은 또한 오버레이를 주입하므로 앱 코드의 createEarmark()는 선택 사항이 됩니다.

earmark({
  inject: false,        // do not auto-mount the overlay
  endpoint: '…',        // passed through to createEarmark
  applyInBuild: true,   // also stamp production builds (off by default)
})

플러그인 없이도 모든 것이 여전히 작동합니다 — 선택자, 컴포넌트 이름, 텍스트를 얻을 수 있지만 file:line은 얻지 못합니다. data-earmark-src를 직접 추가할 수도 있습니다.

순수 HTML과 CSS — 빌드 단계 없음

정적 사이트는 스탬프할 빌드가 없으므로, earmark는 대신 주석 시간에 소스를 확인합니다:

  • HTML — 문서는 위치 추적으로 다시 가져와 파싱된 다음, 소스에서 요소의 하위 인덱스 경로를 따라갑니다. 각 단계는 실제 태그 이름과 대조되므로, 프레임워크로 렌더링된 페이지(제공된 HTML이 단지 껍데기인 경우)는 줄을 만들어내지 않고 아무것도 보고하지 않습니다.

  • CSS — 요소와 일치하는 모든 규칙을 선언하는 파일과 줄로 매핑합니다. 이것은 프레임워크든 아니든 모든 곳에서 작동합니다.

- **Source:** `index.html:101:11` _(resolved from the served HTML)_
- **CSS rules that style it:**
  - `button` → `index.html (inline <style>):49`
    - padding: 7px 13px; border-radius: 8px; border: 1px solid var(--line);
  - `button.primary` → `index.html (inline <style>):59`
    - background: var(--accent); color: rgb(255, 255, 255);

이제 에이전트는 변경해야 할 패딩이 .primary가 아니라 일반 button 규칙의 49번째 줄에 있음을 알게 됩니다. 인라인 <style> 블록은 호스트 문서에 오프셋되고, 외부 스타일시트는 자체 경로를 보고하며, 교차 출처 스타일시트는 내용을 읽을 수 없어 건너뜁니다.


독립 실행형 브로커

npx earmark-server --port 7331
curl http://127.0.0.1:7331/markdown

경로

GET /health

활성 상태 + 개수

GET /annotations?status=open&session=ID

목록

POST /annotations

생성 (일괄)

GET /annotations/wait?since=N&timeout=30000

롱폴링

PATCH /annotations/:id

상태 업데이트

POST /annotations/:id/replies

스레드에 추가

DELETE /annotations/:id · DELETE /annotations

제거 · 모두 지우기

POST /session

탭 등록 / 경로 변경 기록

GET /sessions · GET /sessions/:id

탭, 개수와 주석 포함

GET /events?session=ID

SSE 스트림; 탭의 활성 신호이기도 함

GET /markdown

에이전트용 문서

플래그: --host --store --file --no-persist --webhook --token --quiet.

저장소

--store json(기본값)은 250ms 디바운스로 읽을 수 있는 .earmark/annotations.json을 작성합니다. --store sqlite는 각 변경 사항을 node:sqlite를 통해 즉시 .earmark/annotations.db에 작성하므로, 충돌 시 처리 중인 명령문만 최대로 손실됩니다 — 의존성이 없고, Node 22.5+이며, 사용할 수 없으면 JSON으로 대체됩니다. --store memory는 아무것도 유지하지 않습니다.

웹훅

npx earmark-server --webhook https://hooks.example/earmark

또한 EARMARK_WEBHOOK_URLEARMARK_WEBHOOKS(쉼표로 구분)가 있습니다. 모든 주석 이벤트는 x-earmark-event 헤더와 함께 POST됩니다. 전송은 5초 타임아웃과 한 번의 재시도를 가진 fire-and-forget 방식이므로, 죽은 엔드포인트가 주석 루프를 지연시킬 수 없습니다.


보안

이것은 개발 도구입니다.

  • 브로커는 127.0.0.1에만 바인딩됩니다. 0.0.0.0에 바인딩하지 마세요.

  • CORS는 설계상 열려 있습니다 — 개발 서버가 임의의 오리진에 있기 때문입니다.

  • 브라우저에서 열린 모든 페이지는 루프백 포트에 도달할 수 있습니다. 이 문제가 중요하다면 --token SECRET을 전달하세요.

  • 웹훅은 주석 콘텐츠를 머신 밖으로 보냅니다 — 페이지 URL, 요소 텍스트, 그리고 입력한 모든 것. 직접 제어하는 엔드포인트만 설정하세요.

  • 소스 확인은 같은 오리진에서 자체 페이지와 스타일시트를 다시 가져옵니다. 아무데도 전송되지 않습니다.

  • 공유 또는 공개 호스트에서 실행하지 마세요.


테스트

npm test

일곱 개의 스위트, 88개의 테스트: 저장소 및 HTTP 동작, 실제 stdio 클라이언트로 구동되는 MCP 표면, 오버레이의 동기화 클라이언트, 두 영속성 백엔드, 웹훅 전달, init/doctor CLI, 그리고 소스 리졸버.


지원되지 않는 기능

데스크톱 브라우저만 지원됩니다. iframe, canvas/WebGL 내부, 스크린샷은 지원되지 않습니다. 전체 미해결 목록과 모든 설계 결정의 근거는 plan.md를 참조하세요.


라이선스

MIT. 클린룸 구현 — 다른 도구의 소스에서 파생되지 않았습니다.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.

  • A paid remote MCP for AI agent browser approval MCP, built to return verdicts, receipts, usage logs,

  • A paid remote MCP for AI agent browser DevTools MCP, built to return verdicts, receipts, usage logs,

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nahar-strativ/Agentic'

If you have feedback or need assistance with the MCP directory API, please join our Discord server