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 にあり、依存関係のない単一の自己完結型ファイルです。

ライブエージェント同期を行うには、2つ目のターミナルでブローカーを実行します:

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 はエージェント用に最初に並べられます。


コピー&ペーストモード

パネルの マークダウンをコピー をクリックして、エージェントに貼り付けます:

## 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

その1つのプロセスが、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 は非ゼロで終了するため、CIで利用できます。

ツール

ツール

目的

earmark_list_annotations

未処理の作業をマークダウンで返します(format: "json" も可)。session でスコープを指定します。

earmark_watch_annotations

人間が何かを注釈するまでブロックします

earmark_get_annotation

完全な返信スレッドを含む1つの注釈

earmark_list_sessions

開いているブラウザタブと、注釈が付けられたルート

earmark_get_session

生成されたすべての注釈を含む1つのタブ

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 になります。ピンは色分けされます: オレンジ、青、緑、琥珀、グレー。

セッション

セッションは1つのブラウザタブであり、1回のページロードではありません。IDは sessionStorage に保持されるため、リロード後も存続します。注釈はそれぞれ独自の page.url を持つため、3つのルートをまたいだセッションは、エージェントに3つの異なるルートを持つ1つのグループを提供します。

SPAナビゲーションも追跡されます: pushStatereplaceStatepopstatehashchange はすべてセッションのルートリストを更新します。タブは、SSEストリームが開いている間だけ接続済みと見なされます。

curl http://127.0.0.1:7331/sessions

ソースファイルパス

セレクタはエージェントに何をgrepすべきかを伝えます。ソースパスは正確にどこを見るべきかを伝えます。これが1回の編集と3回のgrepの違いです。

React 19はランタイムの _debugSource ファイバーフィールドを削除したため、これはビルド時に行われます:

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

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

vite dev 中、すべての組み込みJSX要素は 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);

エージェントは、変更する必要があるパディングが汎用の button ルールの49行目にあり、.primary にはないことを知ります。インライン <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秒のタイムアウトと1回のリトライでfire-and-forget方式のため、停止したエンドポイントによって注釈ループが止まることはありません。


セキュリティ

これは開発ツールです。

  • ブローカーは 127.0.0.1 のみにバインドします。0.0.0.0 にバインドしないでください。

  • CORSは設計上オープンです。開発サーバーは任意のオリジン上にあります。

  • ブラウザで開いている任意のページがループバックポートに到達できます。お使いのマシンでそれが問題になる場合は --token SECRET を渡してください。

  • ウェブフックは注釈の内容をマシンの外部に送信します — ページURL、要素テキスト、入力した内容など。自分が管理するエンドポイントだけを設定してください。

  • ソース解決は、同じオリジンから自分のページとスタイルシートを再取得します。どこにも送信されません。

  • 共有ホストや公開ホストで実行しないでください。


テスト

npm test

7つのスイート、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