Devloop について
Devloop はブラウザーまたは Expo/React Native アプリの操作と開発サーバーのログを共通タイムラインにまとめ、開発者やコーディングエージェントの調査を支援します。MCP ツールで操作や記録を行い、同時刻の事象を確認できます。
主な機能
- 01ブラウザーとサーバーログの時系列統合
- 02ブラウザーページ操作とネットワーク記録
- 03Expo/React Native のネイティブ対応
- 04ページスナップショットと再現情報
- 05stdio または HTTP/SSE で提供
活用シーン
- 01ブラウザーのエラーとサーバーのスタックトレースを照合
- 02ブラウザーを操作して機能をテスト
- 03Expo または React Native アプリの問題を調査
- 04ネットワーク記録やバグレポートを出力
MCP 対応
Devloop は開発サーバー、ブラウザー操作、ログ、再現情報のツールを MCP 経由で公開します。stdio で起動するほか、HTTP/SSE で共有 daemon またはデスクトップ Cockpit に接続できます。ネイティブデバイスの操作には Cockpit が必要です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
46掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい | 読み込む絶対 URL(例:http://localhost:3000/path)。 |
詳細
ブラウザー制御と開発サーバーのログを、AI エージェントと人間のために、相関関係を示すひとつのタイムラインにまとめます。
統合開発ループツールです。ブラウザーと開発サーバーを操作し、両方のイベントをタイムスタンプ付きのひとつのバッファーに記録するため、ブラウザーコンソールのエラーと、同じ時点のバックエンドのスタックトレースを関連付けて確認できます。共通のコアを使って、次の2つの方法で動作します。
- ヘッドレス(stdio) — Puppeteer 経由で Chrome を操作し、stdio で提供します。Claude Code がセッションごとに起動する軽量モードです。代わりに
devloop-mcp daemonを実行すると、多数のエージェントやセッションが接続できる、HTTP/SSE 経由の単一の共有長時間稼働インスタンスとして提供されます(「デーモンモード」を参照)。 - コックピット(Electron) — 単一のデスクトップウィンドウで、タブ付きブラウザーペイン(CDP 経由で操作する埋め込み
WebContentsViews)に、戻る/進む/再読み込みとアドレス入力欄を備えたブラウザーバーを配置します。その横には、ログと再現ビルダーを切り替えられる折りたたみ式サイドパネルがあります。プロジェクト選択、自動ナビゲーション、ポップアウト対象に対応しています。レンダラーは React 19 + Tailwind v4 + Radix + lucide-react で構築されています。同じツールを HTTP 経由で提供します。
ブラウザーのコンソール/ネットワーク/ページエラーと、サーバーの stdout/stderr のすべてのイベントが単調増加する共通のクロックを使うため、get_logs_around / repro は、タイムラインから複数のソースにまたがる相関関係付きの範囲を返します。
ネイティブターゲット — Expo / React Native(iOS + Android)
このコックピットは Web だけでなく、Expo/React Native プロジェクトも操作できます。ネイティブプロジェクトを開くと、Web · iOS · Android のターゲット切り替え、バンドラー切り替え(Metro)と Build ボタン(expo run:ios / expo run:android、@expo/fingerprint による古さの検出)を備えたペインが表示され、次の機能を利用できます。
- CDP 経由の JavaScript コンソールとエラー(両プラットフォーム) — Metro の Hermes インスペクターを使用し、スタックトレースはソースマップに対応しています(バンドル後の
index.bundle:1:…は元の.tsxに解決されます)。 - React Native のネットワークキャプチャ — 注入された
XMLHttpRequestフックにより、アプリの fetch/XHR トラフィックが Web と同じnetworkタイムライン行に記録されます(そのため、ネイティブでもget_network/export_har/ ネットワークチップが機能します)。 - ネイティブデバイスログ — iOS の
simctl log stream、Android のlogcatをnativeソースとしてタイムラインに統合します。 - ペイン内に埋め込まれた、ライブでインタラクティブなデバイス — iOS は serve-sim(MJPEG、タップ/スクロール/入力)経由、Android はポーリング式の
screencapミラー(約 2 fps)を使用し、クリックをタップに変換してキー入力も行います。どちらもスクリーンショットに対応しています。 - エージェントが操作できるインタラクション —
browser_snapshotはネイティブのアクセシビリティツリーを読み取ります(iOS は idb の UIKit a11y ツリー、Android はuiautomator dumpを使用)。browser_click/type/scroll/pressは、(スナップショットから取得した)要素のpt:x,y参照またはラベルを使ってデバイスを操作します。操作はreproで再生でき、MCP 経由でnative_open/native_buildを呼び出して開くこともできます。Web と同じエージェントツールをネイティブ向けに対応付けています。
すべての情報は、アプリ単位で相関付けられた同じタイムラインに記録されます。ネイティブアプリで Web の開発ループ体験を実現します。(埋め込み iOS シミュレーターには macOS + Apple Silicon が必要です。Android は Android SDK とエミュレーターが利用できる環境で動作します。)
iOS のインタラクションには idb が必要です: brew install facebook/fb/idb-companion と pipx install fb-idb を実行してください(Python 3.14 未満を使用してください。それより新しい Python では fb-idb が動作しません)。Android のインタラクションには Android SDK platform-tools(adb)と、起動済みのエミュレーターが必要です。コックピットの Settings → native readiness では、プラットフォームごとの事前チェック(iOS:idb · companion · 起動済みシミュレーター、Android:adb · 起動済みデバイス)を実行し、不足している項目ごとに具体的な解決方法を表示します。ログやスクリーンショットの取得は、インタラクション用ツールがなくても利用できます。
serve-sim はコックピットに同梱され、Electron 自身の Node で実行されるため、埋め込みシミュレーターはオフラインで、bun/node/npx や初回起動時のダウンロードなしにそのまま動作します。(ソースから実行する場合は、node_modules 内のコピーを使用します。)
アーキテクチャ
3 つのトランスポートが 1 つの共有コアを公開し、コアが複数の基盤(実際のブラウザー、またはコックピット内のネイティブデバイス)を操作します。すべての情報は、タイムスタンプ付きの単一のタイムラインに送られます。
%%{init: {"flowchart": {"wrappingWidth": 700}}}%%
flowchart TD
clients["<b>MCP clients</b><br/>Claude Code · agents · mcporter"]
clients --> stdio & daemon & cockpit
stdio["<b>stdio</b><br/><i>spawned per session</i>"]
daemon["<b>daemon</b><br/><i>HTTP/SSE · one shared instance</i>"]
cockpit["<b>cockpit</b><br/><i>HTTP/SSE · Electron app</i>"]
stdio --> mcp
daemon --> mcp
cockpit --> mcp
mcp(["<b>MCP Server</b><br/><i>stdio transport, or HTTP/SSE for the daemon + cockpit</i>"])
mcp --> core
core["<b>shared core</b> · <i>transport- and substrate-agnostic</i><br/>the MCP tool layer + one unified, correlated timeline"]
core --> iface(["<b>IBrowserController · IBrowserManager · ITargetController</b><br/><i>capability-gated by the active target</i>"])
iface --> pup & elec & rn
pup["<b>web</b> · Puppeteer / Chrome<br/><i>stdio + daemon</i>"]
elec["<b>web</b> · Electron CDP panes<br/><i>cockpit · per-project partitions</i>"]
rn["<b>native</b> · React Native (Hermes)<br/><i>JS + network over Metro CDP</i>"]
rn -->|"idb / adb"| nd["<b>NativeDriver</b><br/>iOS idb · Android adb<br/>taps · snapshot · screens · logs"]
ツールレイヤーは、その背後にあるものを意識しません — Puppeteer か Electron か、stdio か HTTP か、Web ページかネイティブアプリかは問いません。起動時に一度だけ接続されます。ブラウザーは単一の IBrowserController インターフェイスの背後にあり、コックピットのペインマネージャーは、より豊富な IBrowserManager を実装します(複数のペインに対応し、browser_* をアクティブなペインに委譲します。iOS/Android ターゲットが開いている場合は、ネイティブコントローラーに委譲します)。機能レイヤーはアクティブなターゲットに応じてツールを制御するため、エージェントには基盤のエラーではなく、明確なメッセージが表示されます。
stdio モードでは stdout を MCP プロトコル専用とし、ユーザー向けの出力はすべて stderr に送ります。
レイヤー
- トランスポート — 2つのプロトコルを使う3つのエントリーポイントです。stdio(セッションごとに1つのサーバー)と、長時間稼働するデーモンおよびコックピットのHTTP/SSEです。いずれもツールレイヤーにバインドされた同じMCPサーバーを構築します。マルチクライアントに対応するのはHTTPトランスポートのみで、接続するクライアントごとに独自のセッションが割り当てられ、バックエンドは1つを共有します。
- 共有コア — ツールレイヤー(MCPツールと、機能に応じてアクセスを制御するディスパッチャー)を、統合された相関タイムライン(サーバー出力、ブラウザーのコンソール/ネットワーク/エラー、ネイティブログ)の上に構築し、別個の全件キャプチャ用ネットワークリングで支えています。プロジェクトレジストリ、エラー診断、ソースマップ解決、HARエクスポート、バグレポートバンドルなど、ツールが公開する横断的な機能もここにあります。
- ブラウザー基盤 — 共有コントローラーインターフェースと、2つのWeb実装(ヘッドレス向けのPuppeteer/Chrome、コックピット内でCDP経由のペインとして動作するElectron
WebContentsView)、および1つのネイティブ実装(Hermes/Metro上のReact Native)で構成されます。共通のページ操作・アクセシビリティスナップショット処理と、デバイス/スロットリングのエミュレーションがその上にあります。 - ネイティブターゲット — RNコントローラー(Metro CDP経由のJS/エラー/ネットワーク)が、タップとスナップショットを**
NativeDriver**(iOSではidb、Androidではadb)に委任します。ネイティブログ(simctl/logcat)、スクリーンショットとライブミラー、ビルドのオーケストレーション(expo run)、起動準備の事前チェックも備えています。 - 状態と分離 — ディスク上のレジストリ(プロジェクト/セッション/ペイン)、プロジェクトごとのセッションパーティション、Chrome拡張機能の管理で構成されます。
- コックピット(Electron) — デスクトップシェルです。ペインマネージャー(プロジェクトごとのパーティション、ネイティブルーティング)、React UI(タイムライン、ブラウザーバー、再現ビルダー、ターゲット切り替え、Androidミラー)、同梱されたserve-sim iOSミラー、ストア内の「Add to Devloop」インジェクション、アプリ内アップデーターを備えています。
インストール
ヘッドレスMCP(stdio) — クローンは不要です。Claude Codeに登録してください。
claude mcp add devloop --scope user -- npx -y devloop-mcp
npmではdevloop-mcpとして公開されています。Puppeteerは初回インストール時にChromiumを取得します。
コックピット(デスクトップアプリ) — Releasesから、お使いのOS向けインストーラー(.dmg/.exe/.AppImage)をダウンロードしてください。macOS版にはApple Silicon(arm64)とIntel(x64)のビルドが用意されています。アプリは起動時にGitHubで新しいリリースを確認し、ダウンロードまたはインストールの前に確認を求めます。または、settings → updates → check for updatesから手動で実行できます。
ソースから(開発用)— bunが必要です。
bun install
bun run app # build + launch the Electron cockpit
bun run start # or run the stdio MCP directly
コーディングエージェントから使う
登録したら、エージェントがコードだけから判断するのではなく、Devloopを通じて機能を操作し、実際に動かして検証するように、これを**CLAUDE.md**(または任意のエージェントのルールファイル)に追加してください。
## Devloop — use it for any web/mobile feature work
When you build, test, or debug a feature that runs in a **browser** or an **Expo /
React Native** app, drive it through **devloop** instead of reasoning from the code
alone. It puts the dev-server logs and the live browser/device on one correlated
timeline, so you can see what actually happened.
- **Start the loop:** `dev_start` (auto-detects the dev command), then
`browser_navigate` to the page — or `native_open` for an iOS/Android target.
- **Act, then verify — don't assume:** after a change, reproduce it with `repro`
(a navigate/click/type sequence) and read the result. Never claim a fix works
without exercising it in the running app.
- **Find/target elements** with `browser_snapshot` (returns clickable `ref`
selectors) — prefer it over screenshots.
- **When something breaks:** `diagnose` first (groups errors + failed requests),
then `get_logs_around` a timestamp to line up the browser console error with the
matching server stack trace from the same moment. `get_network` / `export_har`
for request detail.
- **Definition of done:** the feature is verified live in devloop — no console or
page errors, the expected network calls succeeded, the UI reflects the change —
not just "the code looks right."
- **Setup stays yours:** if a native build needs a toolchain that isn't installed,
devloop tells you exactly what's missing and the command to fix it — it
**diagnoses, it never installs or touches your toolchain.** Run the fix, then rebuild.
Register once: `claude mcp add devloop --scope user -- npx -y devloop-mcp`
ツール(46)
開発サーバー — 実行時に使用します。プロジェクトごとの登録は不要です。
dev_start({ project?, cmd?, cwd? })— 開発サーバーを起動し、ログを複製して出力します。指定方法は3つあります。保存済みレジストリのproject、明示的なcmdとcwd、またはいずれも指定しない方法です(cwdの既定値はサーバーのディレクトリで、cmdはpackage.jsonのスクリプトからdev/develop/web/start/serveの順に自動検出されます)。dev_stop()— サーバーを停止します。プロセスグループ全体を終了するため、next dev/metroの子孫プロセスも停止します。dev_status()— 実行中かどうかと、cmd/cwd/pidを返します。 ネイティブターゲット — Expo/React Native(コックピットのみ。Electron とシミュレーター/エミュレーターが必要です)native_open({ platform })— アクティブなペインの iOS シミュレーターまたは Android デバイスミラーを開きます。その後、browser_*でネイティブアプリを操作し(idb/adb)、JS とネイティブのログがタイムラインにストリーミングされます。デバイス/ツールの準備ができていない場合は、理由とともにok:falseを返します。native_close()— ペインの Web コンテンツに戻ります。native_build({ platform, cwd? })—expo run:ios/expo run:androidを実行し、タイムラインにストリーミングします(cwdの既定値はアクティブなペインのプロジェクトです)。SDK/JDK がセットアップされていない場合、Android はビルドせずにツールチェーンのチェックリストを返します。native_doctor()— ビルドや起動をせずに、ネイティブ環境の準備状況を再確認します。iOS と Android の操作環境、および Android のビルドツールチェーンを、それぞれ不足項目の修正方法付きの ✓/✗ チェックリストとして表示します。不足しているツールをインストールした後に実行し、問題が解決したことを確認してください。- ヘッドレスの stdio/デーモンモードでは、コックピットが必要であることを報告します(Puppeteer は Web 専用です)。
ブラウザー制御 — アクティブなペインを操作します
browser_navigate({ url })browser_back()·browser_forward()·browser_reload({ hard? })— 履歴の移動と再読み込み(ブラウザーバーの ←/→/⟲。hardを指定するとキャッシュを無視します)。browser_screenshot({ fullPage? })→ PNG 画像browser_click({ selector })browser_type({ selector, text })browser_hover({ selector })·browser_scroll({ selector? | x?, y? })·browser_select({ selector, value })·browser_press({ key, selector? })—Enter/Escape/Tab/ArrowDownなどのキー。browser_wait_for_idle({ idleMs?, timeoutMs? })— ネットワークが落ち着くまで待機します。browser_clear_storage({ allOrigins? })— 現在のオリジン(またはセッション全体)の Cookie/localStorage/IndexedDB/キャッシュ/サービスワーカーを消去します。ログアウトしたり、新規ユーザーとしてテストしたりする際に使います。browser_emulate({ device? | width?, height?, mobile?, deviceScaleFactor?, userAgent?, reset? })— デバイス/ビューポートをエミュレートします(device:iphone/ipad/pixel、またはカスタム指定。reset→ デスクトップ)。browser_throttle({ profile })— ネットワーク状況を設定します:slow-3g/fast-3g/offline/none。browser_eval({ expression })— ページのコンテキストで実行します(CSP によるブロックはありません)。browser_snapshot()— 構造化されたページスナップショット:url、title、および CSS セレクターのrefを持つインタラクティブ要素/ランドマーク要素(role、アクセシブル名、値/状態、見出しレベル)。refはbrowser_click/browser_typeで使用できます。要素を確実に見つけて指定するには、スクリーンショットよりこちらを優先してください。browser_wait_for({ selector?, text?, timeoutMs? })— セレクターが表示されるか、テキストが存在するまで待機します(ナビゲーション/非同期レンダリング後)。{ ok, waitedMs }を返します。 ログと相関get_logs({ source?, stream?, grep?, app?, sinceSeq?, limit? })— 統合されたログの末尾を取得します。sourceはserver|browser、streamはstdout/stderr/console/network/pageerrorです。appを指定すると、1 つのプロジェクトのログに絞り込めます。ペインの ラベル(プロジェクト名)または ID(pane_listを参照)に一致し、どのペインがアクティブかにかかわらず、そのペインのサーバーログとブラウザーログの両方をフィルタリングします。最後に取得したseqをsinceSeqに渡すと、差分を継続的に取得できます。get_logs_around({ ts, windowMs?, source?, app? })— 相関ツールです。タイムスタンプの前後windowMsミリ秒以内のすべてのイベントを、両方のソースにまたがって時系列順に取得します(必要に応じて 1 つのappに絞り込めます)。- タイムラインには、失敗したネットワークイベント、またはステータスが
DEVLOOP_NET_THRESHOLD以上のイベントが表示されます(0に設定すると、すべてのイベントをインライン表示します)。すべての基盤(Puppeteer / CDP / React Native)で、詳細なdetailが含まれます。内容は、メソッド、ステータス、リソースタイプ、MIME タイプ、所要時間、リクエストとレスポンスのヘッダー、および上限付きのリクエストとレスポンスの本文です。 get_network({ grep?, app?, limit? })— 完全なキャプチャリングバッファーに記録されたすべてのリクエストを取得します。しきい値に関係なく取得できます(get_logsでは、厳選されたタイムラインに表示されるもののみを取得します)。気になる高速な 200 レスポンスがタイムラインにない場合に使用します。export_har({ app? })— ネットワークバッファー全体を HAR 1.2 ドキュメントとしてエクスポートします(Chrome DevTools / Charles にインポートできます)。しきい値に関係なく完全な内容をエクスポートします。必要に応じて 1 つのappに絞り込めます。diagnose({ windowMs?, app? })— 現在発生している問題をトリアージします。繰り返されるエラー(コンソール / ページ / サーバー)を件数付きでグループ化・重複排除し、失敗したネットワークリクエストと 4xx-5xx のネットワークリクエストを一覧表示して、1 行の概要を返します。get_logsを調べる前に、まずこちらを実行してください。- ページエラーには
resolvedStackが含まれます — 圧縮されたブラウザースタックトレースを、バンドルのソースマップを使って元のソースに対応付けます(ブラウザーでは DevTools UI 上でのみ難読化を解除できます。error.stackはコンパイル後のままなので、こちらで対応付けを行います)。エントリーのdetailに含まれます。 export_bundle({ app?, windowMs? })— 共有可能な バグレポートバンドル(JSON)を作成します。内容は、診断の概要、タイムライン、スクリーンショット、HAR、再現手順です。コックピットの レポートボタンを押すと、自己完結型の HTML ページとして保存されます。clear_logs()— 問題を再現する前にログをリセットします。repro({ actions | action, waitFor?, settleMs?, stepSettleMs?, idleMs?, timeoutMs?, continueOnError?, clear? })— 問題を再現して相関付けます。バッファーをクリアし、1 つのアクションまたは一連のアクションを実行して待機した後、一連の操作を通して両側で発生したすべての内容を返します。ステップごとの結果(steps[])、byStreamの件数、事前にフィルタリングされたerrorsの一覧が含まれます。actions: [{kind, ...}]— 使用できる種類はnavigate/click/type/hover/scroll/select/press/eval/wait/noneです。action(単数形)は、1 ステップだけ実行する場合の簡易形式です。- ステップ間は
stepSettleMs(デフォルトは 300 ミリ秒)、最後のステップ後はsettleMs(デフォルトは 1000 ミリ秒)待機します。waitFor: "networkidle"を指定すると、idleMs(デフォルトは 500 ミリ秒)の間ネットワーク通信がなくなるまで待機します。最大待機時間はtimeoutMs(デフォルトは 10000 ミリ秒)です — 遅いレスポンスやストリーミングレスポンスにはこれを使用してください(Expo の最初のウェブバンドルには約 12 秒かかります)。タイムアウトした場合も、到着した内容は返され、waitNoteが含まれます。 continueOnError(デフォルトは false)を指定しない場合、失敗したステップで停止します(stoppedAtStep)。
プロジェクトレジストリ — 保存済みプロジェクトを ~/.devloop/projects.json に永続化します
project_list()— 保存済みプロジェクト(名前、cwd、cmd、url、steps)を一覧表示します。project_add({ name, cwd, cmd?, url?, steps? })— プロジェクトを保存または置き換えます(保存済みの再現用stepsシーケンスを含む)。これにより、名前を指定してdev_start({ project })を実行できます。project_remove({ name })。 ペイン — 複数ターゲットに対応します(コックピットのみ。stdio モードは単一ペインで、その旨を報告します)pane_list()— 各ペインの情報:{ id, url, active, popped }。アクティブなペインがbrowser_*/reproのターゲットになり、イベントにはペインのidが付与されます。pane_new({ url? })— 新しいペインを開き、アクティブにします。pane_select({ id })— ペインをアクティブにします。pane_close({ id })。pane_pop({ id })— ペインを独立したウィンドウに切り離します(ターゲットを横並びにできます)。pane_set_label({ id, label })— ペインの名前を変更します(タブをダブルクリックするのと同じです)。
拡張機能 — Chrome 拡張機能の管理(コックピットのみ)
ext_list()— インストール済みの拡張機能:{ id, name, version, enabled }。ext_install({ idOrUrl })— Chrome ウェブストアの ID/URL を指定してインストールします。ext_remove({ id })— アンインストールします。ext_set_enabled({ id, enabled })— アンインストールせずに有効/無効を切り替えます。
コンソールの引数
console.log(obj) は、JSHandle@object ではなく、実際の値に解決された引数とともにキャプチャされます(例:[log] user {"id":7})。Electron の基盤は CDP プレビューから引数を同期的に描画します。Puppeteer の基盤では、予約してから値を埋めるパターンを使い、到着時に seq/ts を同期的に記録してから解決済みの引数を後から反映するため、出力順序と一致し、サーバーログとも正しく交互に並びます。
ヘッドレスモード(stdio)
ユーザースコープで一度だけ登録すれば、すべてのプロジェクトで使えます:
claude mcp add devloop --scope user -- npx -y devloop-mcp
その後、任意のプロジェクトで次のように指示します:「dev_start を実行して、/projects へのナビゲーションを再現してください」。dev_start は cwd のデフォルトとして現在のプロジェクトを使い、コマンドを自動検出します。
| 変数 | デフォルト | 意味 |
|---|---|---|
DEVLOOP_HEADLESS | false | "true" にすると Chrome をヘッドレスで実行します。デフォルトでは画面に表示されるため、動作を確認できます。 |
DEVLOOP_CHROME_PATH | (バンドル済み) | Chrome 実行ファイルのパスを明示的に指定します。 |
DEVLOOP_NET_THRESHOLD | 400 | この値以上のステータスを持つネットワークレスポンスを記録します(失敗は常に記録されます)。 |
DEVLOOP_ACTION_TIMEOUT | 10000 | インタラクションの上限(ms)です。ページが応答しなくなった場合、ハングせずにすぐ失敗します。 |
DEVLOOP_NAV_TIMEOUT | 30000 | ナビゲーションの上限(ms)です。 |
DEVLOOP_LOG_CAPACITY | 5000 | バッファーに保持するイベントの最大数です。 |
DEVLOOP_NET_RING | 3000 | フルキャプチャ用ネットワークリング(get_network/export_har)に保持するリクエストの最大数です。DEVLOOP_NET_THRESHOLD とは独立しています。 |
DEVLOOP_DEV_CMD / DEVLOOP_DEV_CWD | (なし) | 起動時に開発サーバーを自動起動するための任意の設定です(通常は dev_start を使います)。 |
DEVLOOP_HOME | ~/.devloop | レジストリの保存場所です。 |
デーモンモード(共有 HTTP/SSE)
HTTP/SSE 経由で全クライアントが接続する、長時間稼働するデーモンを自分で 1 つ起動します(stdio の起動でもプロジェクトごとにすでに実行されます。以下の 共有モード を参照)。複数のクライアントが 1 つの Devloop インスタンス(1 つのブラウザー、1 つの開発サーバー、1 つの相関タイムライン)に接続します:
devloop-mcp daemon # headless; serves MCP at http://localhost:7333/mcp
# then point any number of MCP clients at it:
claude mcp add --transport http devloop http://localhost:7333/mcp
stdio と同じバックエンドと環境変数を使います(デフォルトはヘッドレスです。画面に表示するには DEVLOOP_HEADLESS=false を設定します)。また、DEVLOOP_HTTP_PORT(デフォルトは 7333)から空きポートを自動的に選択します。各クライアントは独自の MCP セッションを持ちますが、同じバックエンドを共有するため、あるエージェントの dev_start/ナビゲーションが、別のエージェントの get_logs に表示されます。(Electron コックピットもまったく同じ HTTP トランスポートを提供します。デーモンはそのヘッドレス版です。)
デーモンのライフサイクルを管理します:
devloop-mcp daemon --status # is one running? (pid + url)
devloop-mcp daemon --stop # SIGTERM the running daemon
DEVLOOP_DAEMON_IDLE_MS=60000 devloop-mcp daemon # auto-exit 60s after the last client disconnects
共有モード — stdio ではデフォルトで有効です
自分でデーモンを実行する必要はありません。通常の stdio 起動(npx -y devloop-mcp)では、プロジェクトのデーモンに接続します。そのディレクトリですでに実行中のデーモンがあれば接続し、なければ起動してデタッチします。そのため、Claude Code の再起動、/mcp の再接続、同じリポジトリでの新しいセッションでは、別の Chrome を開くのではなく、同じ Chrome を再利用します。2 つのリポジトリを同時に開くと、それぞれ別のデーモンが使われるため、開発サーバーやタイムラインが干渉しません。
stdio プロセスは薄いプロキシとなり、クライアントとは stdio で通信し、ツールの呼び出しを HTTP 経由でデーモンに転送します。Chrome が起動するのはブラウザツールが初めて使われたときだけで、セッションの開始時には起動しません。自動起動したデーモンでは stdio のブラウザが表示され(非表示にするには DEVLOOP_HEADLESS=true)、プロジェクトディレクトリで実行されます。また、最後のセッションが切断されてから 10 分後に終了します(変更するには DEVLOOP_DAEMON_IDLE_MS を指定します)。プロジェクト内で devloop-mcp daemon --status/--stop を実行すると、そのプロジェクトのデーモンを管理できます。問題が発生した場合(デーモンが起動しないなど)は、セッションは通常のローカルインスタンスにフォールバックするため、突然停止することはありません。
npx -y devloop-mcp --shared # or DEVLOOP_DAEMON=1: one global daemon shared by every project
npx -y devloop-mcp --local # or DEVLOOP_DAEMON=0: the old behavior, one browser per session
グローバルデーモンは $DEVLOOP_HOME/daemon.json に情報を記録し、プロジェクトごとのデーモンは $DEVLOOP_HOME/daemons/ に記録します。
MCP がブロックされている場合(エンタープライズサンドボックス)— mcporter で Devloop を操作
一部のサンドボックス/エンタープライズ環境では、エージェントによる MCP サーバーの登録や起動が許可されていない(または MCP トランスポートがブロックされている)一方で、シェルコマンドの実行は許可されている場合があります。mcporter はこのギャップを埋めます。任意の MCP サーバーのツールを通常の CLI コマンドとして呼び出せるため、エージェントは MCP クライアントではなく Bash 経由で Devloop を操作できます。
堅牢な方法は、デーモンと HTTP 経由の mcporter を組み合わせることです。Devloop デーモンを 1 つ実行し(サンドボックスの外部、またはサンドボックスと並行して一度だけ起動)、そのツールをシェルコマンドとして呼び出します。
devloop-mcp daemon # one shared instance on :7333
# point mcporter at it ad-hoc (no config); --allow-http since it's localhost cleartext
npx mcporter list --allow-http --http-url http://localhost:7333/mcp --name devloop
npx mcporter call --allow-http --http-url http://localhost:7333/mcp 'devloop.dev_start(cwd: "/repo")'
npx mcporter call --allow-http --http-url http://localhost:7333/mcp 'devloop.browser_navigate(url: "http://localhost:3000")'
npx mcporter call --allow-http --http-url http://localhost:7333/mcp 'devloop.diagnose()'
または、デーモンを使わず、mcporter に呼び出しごとに stdio サーバーを起動させます(プロセスの起動が許可されている場合)。
npx mcporter list --stdio "npx devloop-mcp" --name devloop
npx mcporter call --stdio "npx devloop-mcp" 'devloop.get_logs(limit: 50)'
注意事項:
- 設定を永続化して、記述子を繰り返し指定しなくて済むようにします。Devloop を
~/.mcporter/mcporter.jsonに追加するか(または--persistを渡します)。mcporter は、Claude Code/Desktop、Cursor、Codex などですでに設定されているサーバーも自動インポートします。そのため、以前にclaude mcp add devloop …を実行していれば自動的に認識され、npx mcporter call devloop.<tool> …を実行するだけで使えます。 npx mcporter list devloop --schemaを実行すると、TypeScript 形式のシグネチャとともにすべてのツールが表示されます。エージェントが引数を確認するのに便利です。- 完全に自己完結した CLI を使う場合、
npx mcporter generate-cli devloopはスタンドアロンバイナリを生成します。また、mcporter serveはサーバーを再公開し、1 つのブリッジ済みエンドポイントとして提供します。mcporter のドキュメントを参照してください。
(その場で指定するフラグは mcporter のバージョンによって異なる場合があります。npx mcporter --help を正としてください。)
エージェントスキル: skills/devloop/SKILL.md は、これをインストール可能な Agent Skill としてまとめています。配置(cp -r skills/devloop ~/.claude/skills/、またはプロジェクトの .claude/skills/ 内に配置)すると、エージェントは MCP がブロックされている場合に mcporter 経由で Devloop を操作する方法を把握できます。デーモンのセットアップとツールの使用例も含まれています。
コックピットモード(Electron)
bun run app # build + launch the cockpit
bun run app:selftest # headless integration test (no visible windows)
1つのウィンドウ(React 19 + @theme トークンを使用する Tailwind v4 + Radix の Dialog/Tooltip + lucide-react アイコン)を、次のように配置しています。
- トップバー — ペインのタブ、アクティブなペインの開発用コントロール、ウィンドウ切り替えボタンの順に表示します。
- 開発用コントロール(アクティブなペインを操作):ステータスチップ(実行中は緑色の
● project、ゼロ以外の終了コードで終了した場合は赤色の✗ exited (code N)、それ以外はdev: stopped/not configured)、開発サーバーの起動・停止を切り替える ▶/⏹、再起動する ⟳(Power)、ペインのスクリーンショットをタイムラインに追加する 📷。 ⚙設定 ·⤢アクティブなペインを独立したウィンドウにポップアウトします。- タブ名にはプロジェクト名(
package.jsonのname、ない場合はフォルダーのベース名)が自動で設定されます。ペインのサーバーが起動中の場合は緑色の実行中ドットが表示され、ポップアウト中は⤢が表示されます。クリックすると切り替わり(タイムラインはアクティブなペインに追従)、ダブルクリックすると名前を変更でき、×で閉じ、+ paneで追加できます。UI または Claude からペインが変更された場合も、リアルタイムで反映されます。
- 開発用コントロール(アクティブなペインを操作):ステータスチップ(実行中は緑色の
- ブラウザバー(ペインの上)— ←/→ 戻る/進む(履歴がない場合は無効)、⟲ 再読み込み、⤓ キャッシュを無視して強制再読み込み、⌫ サイトデータを消去(cookies/localStorage を消去して再読み込み)、アクティブなペインの現在の URL を表示するアドレスバーを備えています。リンクのクリックや SPA のルート変更に追従します(マネージャーが
did-navigateを監視します)。ポート番号だけの入力(3000→http://localhost:3000)と、任意のhttp(s)://URL を受け付けます。Enter キーで移動し、⌘Lでフォーカスします。 - ブラウザー領域 — アクティブなペインを、CDP 経由で操作する Chromium の実際の
WebContentsViewに表示します。他のペインはバックグラウンドで動作し続け(ログも流れ続けます)、アクティブなペインはこの領域に配置され、パネルの折りたたみやサイズ変更に合わせて再配置されます。 - 設定(
⚙の背後にあり、トップバーをすっきり保つためデフォルトでは折りたたまれています)— ラベル付きの行があります。- project — 保存済みプロジェクトのドロップダウン。一つ選ぶとすぐに開き(cmd/cwd/url + 再現手順を設定し、開発サーバーを起動して移動します)、アクティブなペインを現在のタブラベルを名前にしてプロジェクトとして保存する 💾 save を利用できます(タブで名前を変更します)。
- dev —
cmd(空欄の場合は自動検出)+ 📁 フォルダーピッカー +cwd。フォーカスを外したとき(およびフォルダーを選択したとき)にアクティブなペインへ自動保存されます。「適用」ボタンはありません。保存後は、トップバーの ▶ からすぐに起動できます。 - ext — ペインに Chrome 拡張機能(React/Redux DevTools、または開発中の独自拡張機能)を読み込みます。Chrome ウェブストアの ID/URLを指定するか、📁 unpacked を読み込むからフォルダーを選択してインストールします。拡張機能は保存され、次回起動時に読み込まれます。ペインのセッション内で動作するため、コックピット UI から分離されています。
electron-chrome-web-storeを使用します。Electron の拡張機能 API は一部のみ対応しています(MV3 はおおむね動作しますが、一部のchrome.*API は利用できません)。
- サイドパネル(折りたたみ可能)— logs / repro を切り替えるセグメントコントロールがあります。
- logs — ライブイベントリスト(ソース別の色分け、タイムスタンプ、ペインタグ、長い行のクリックによる展開、スクリーンショットのサムネイル → Radix の
Dialogライトボックス)。ネットワーク行はステータスの範囲(2xx/3xx/4xx/5xx)ごとに色分けされ、展開するとメソッド/ステータス/所要時間とリクエスト/レスポンスのヘッダーおよび本文を表示します。固定フィルターバーには、部分一致フィルター + チップ(server/console/network/errors/repro)、↓ latestピル、HAR エクスポート、clearがあります。常にアクティブなペインに絞り込まれます。 - repro — 再現手順ビルダー(
+ step/pick/run)があります。pick を使うと、ページ内の要素をクリックして安定したセレクターを取得し、クリック手順に直接追加できます。実行結果はログのタイムラインに追加され(自動的に切り替わります)、各手順の ✓/✗ と、関連するエラー一覧が表示されます。 - パネルヘッダーの
›で折りたためます。右端の小さなホバーハンドルで再展開できます。アクティブなペインを独立したウィンドウにポップアウトすると、空いた領域にタイムラインが表示されます。仕切りをドラッグするとサイズを変更できます。
- logs — ライブイベントリスト(ソース別の色分け、タイムスタンプ、ペインタグ、長い行のクリックによる展開、スクリーンショットのサムネイル → Radix の
- ポップアウトウィンドウ — URL バーの右にある
⤢をクリックすると、アクティブなペインが独自のバー(戻る/進む/再読み込み/強制再読み込み/アドレス/スクリーンショット)を備えた独立したブラウザーウィンドウに切り離されます。ペイン ID で操作し、ライブ URL はナビゲーションに追従します。⌘Rでページを再読み込みします。ウィンドウを閉じると、ペインは元の場所に戻ります。 - キーボード:
⌘Lアドレスバー ·⌘R/⌘⇧R再読み込み/強制再読み込み ·⌘K消去 ·⌘Bパネルの切り替え ·⌘,設定 ·⌘1–9ペインの切り替え ペインごとのプロジェクト: 各ペインには独自の開発サーバーと設定(cmd/cwd)があるため、別々のペインで異なるプロジェクトを同時に(異なるポートで)実行でき、操作はアクティブなペインに対して行われます。
自動ナビゲーション: 開発サーバーの起動時(またはプロジェクトを開いたとき)に、コックピットはそのペインのサーバー出力を監視し、ペイン内でサーバーが最初に通知した http://localhost:PORT を開きます。ポートを入力する必要はありません。
永続化と復元: 開いているペイン(各ペインの URL、プロジェクトラベル、開発設定)は ~/.devloop/panes.json に保存され、再起動時に復元されます。フォームの状態(再現手順と選択したプロジェクト)は ~/.devloop/session.json に保存されます。復元時に開発サーバーが実行中だとは想定しません。保存された URL が開発用(localhost)の URL であるペインは、「▶ を押して起動」というプレースホルダーとして復元されます(実際の URL は保持されます)。▶ を押すとサーバーが起動し、自動的にナビゲーションします。
コックピットは、同じツールをMCP-over-HTTP(ステートフルなセッション)でも提供します。DEVLOOP_HTTP_PORT(デフォルトは 7333)から利用可能なポートを自動的に選び、URL をログに出力します。実行中のコックピットを Claude に指定してください。
claude mcp add --transport http devloop-cockpit http://localhost:7333/mcp
(接続されるのは bun run app の実行中のみです。)
クリーンな終了処理: ウィンドウを閉じる(または終了/SIGTERM/SIGINT)と、開発サーバーのプロセスグループ、すべてのブラウザペイン、HTTP サーバーを含むすべてのプロセスを終了します。正常な終了が滞った場合は、強制終了に切り替えます。また、開発サーバーは親 PID ウォッチドッグの下で実行されるため、コックピットがクラッシュまたは SIGKILL で終了しても、開発サーバーが孤立することはありません(:3000 を占有したままの next dev が残りません)。
コックピット専用の環境変数:DEVLOOP_HTTP_PORT(デフォルトは 7333)、および共有環境変数の DEVLOOP_NET_THRESHOLD/DEVLOOP_ACTION_TIMEOUT/DEVLOOP_LOG_CAPACITY/DEVLOOP_HOME。
プロジェクトの構成
src/
logBuffer.ts source-aware, timestamped ring buffer (+ live onPush)
devServer.ts runtime dev-server manager (process-group kill) + detectDevCommand
registry.ts persisted project registry
browserController.ts IBrowserController + IBrowserManager interfaces
browser.ts PuppeteerBrowserController (headless/stdio)
electronBrowser.ts ElectronBrowserController (cockpit; CDP debugger)
toolLayer.ts TOOLS + handleTool, bound via configureTools(deps)
index.ts stdio entry (Puppeteer + stdio)
cockpit/
main.ts Electron main: windows, BrowserManager, MCP-over-HTTP, lifecycle
browserManager.ts multi-pane manager (IBrowserManager)
preload.ts contextBridge IPC surface
renderer/ React UI — main.tsx (app) + global.d.ts (IPC types) +
styles.css (Tailwind v4 @theme) + index.html
build.ts Bun build for main/preload/renderer + Tailwind CLI step
テストとチェック
CI では、すべてのプッシュと PR に対して、lint/format、types、unit、smoke、daemon、mcporter CLI、コックピットのセルフテスト、GUI のエンドツーエンドテストを必須としています。すべてのチェックをローカルで実行するには bun run test:all を使用するか、個別に実行してください。
bun run check # Biome lint + format check (the CI gate; `bun run format` to auto-fix)
bun run typecheck # tsc across core + renderer + gui
bun test # unit tests (pure logic)
bun run test-smoke.ts # headless Puppeteer: structured args, networkidle, repro sequence, abort
bun run test:daemon # HTTP/SSE daemon: two clients sharing one backend
bun run test:mcporter # the mcporter CLI path: `mcporter call devloop.<tool>` over HTTP
bun run app:selftest # headless Electron: substrate→buffer, tool layer, MCP-over-HTTP,
# renderer IPC, registry, multi-target panes + pop-out, auto-navigate,
# derived project name, per-pane dev (server-log tagging), app-scoped
# get_logs, inline repro builder, pane persistence/restore, teardown
bun run mcp-drive.ts # live smoke test: drives a RUNNING cockpit over its MCP-over-HTTP
# endpoint (start dev server → auto-navigate → verify the live app via
# browser_eval → app-scoped get_logs → screenshot). Cockpit must be up.
新機能は、このテストハーネスを使ってテストファーストで開発します。コードの lint とフォーマットには Biome を使用します(bun run check/bun run format)。コミットは Conventional Commits に従います。ワークフローの詳細は CONTRIBUTING.md を、脆弱性の報告は SECURITY.md をご覧ください。リリース履歴は CHANGELOG.md に記載されています。
現場で得た注意点
- ポートの競合はブラウザーで 500 エラーとして表れます。 別のプロセスがポート 8081 を使用している状態で Expo アプリに接続したところ、ブラウザー側で
500が発生しました。サーバーのログを見ると、Expo の起動がスキップされていました。アプリごとに空いているポートを割り当ててください。統合タイムラインが役立つ理由を示す好例でもあります。 bun run devは実際のサーバーを孫プロセスとして起動します。 シェルを終了するとnext dev/metroが孤立します。そのため、開発サーバーはデタッチして起動し、プロセスグループ単位で停止します。- 対話的な使用時に
CI=1を渡さないでください。 Metro の watch/HMR が無効になります。
次に取り組むこと
- EAS Build のフォールバック — ローカルのツールチェーンがない場合(特に Android)のネイティブビルド向けに、
eas buildのパスを用意し、Settings → native readiness の事前チェックに表示します。 - スナップショット深度の設定 — 密度の高い UI(データテーブルや長いフォーム)に対応できるよう、
browser_snapshotで 250 要素の上限を上書きできるようにします。
完了:ブラウザーとサーバーのタイムライン統合 · get_logs_around による相関付け · repro のワンショット実行とアクションシーケンス(結果をインライン表示) · waitFor: networkidle · 構造化されたコンソール引数 · 操作タイムアウトの上限設定 · 自動修復による再取得(Puppeteer と Electron のペイン — レンダラーのクラッシュから復旧) · ネットワークリクエスト/レスポンスの本文(上限付き、Base64 デコード済み、ログに記録された Electron エントリーで利用可能) · プロジェクトレジストリ(保存済みの repro 手順付き) · セッションの永続化 · 単一ウィンドウの Electron コックピット — タブ付きペイン、折りたたみ可能なツールバーとタイムライン、ポップアウト、プロジェクト名付きタブ · ペインごとの開発サーバー、初回設定のみ(自動保存) · ログからの自動ナビゲーション · ペインの永続化と復元(「実行中」と仮定しない) · React 19 + Tailwind v4 + Radix + lucide-react のレンダラー · ブラウザーバー(戻る/進む/再読み込み + ライブアドレス) · セグメント化されたログ/repro パネル · 独自のブラウザークロームを備えたポップアウトウィンドウ · スクリーンショット → タイムライン(サムネイル + ライトボックス) · 開発失敗状態インジケーター · プロジェクトピッカー(選択時に開く)+ フォルダー参照 · 視覚的な repro ビルダー · MCP over HTTP · プロセスグループのクリーンな終了 + クラッシュ監視 · Electron のセキュリティ警告の抑制 · ネイティブターゲット(Expo / React Native iOS) — Web・iOS 切り替え、個別のバンドラー/ビルド(@expo/fingerprint による古さの検出付きの expo run:ios)、CDP 経由のソースマップ対応 Hermes JS ログ、タイムライン上の simctl ネイティブデバイスログ、ペインに埋め込まれた ベンダー提供のオフライン対応ライブ iOS シミュレーター · エージェント主導のネイティブ操作 — UIKit の a11y ツリーの browser_snapshot + idb 経由の browser_click/type/scroll/press(pt:x,y の参照またはラベルを使用)、repro から再生可能、Settings → native readiness の事前チェック付き · ペインごとの Chrome 拡張機能の読み込み/切り替え + ストア内の 「Add to Devloop」インストールボタン · アプリ内更新バナー(ダウンロードの進行状況 + 再起動) · Android ターゲット(Web・iOS・Android の切り替え、uiautomator による adb 駆動のスナップショット/タップ、タイムライン上の logcat、ライブ screencap ミラー、expo run:android) · RN ネットワークキャプチャ(挿入された XHR フック → network 行) · 完全なネットワークキャプチャリングバッファー(完全な HAR + get_network、しきい値に依存しない) · ビューポート/スロットリング選択 UI · プロジェクトごとのセッションパーティション(同一オリジン分離) · 共有 HTTP/SSE デーモン(devloop-mcp daemon — 多数のエージェントで 1 つのインスタンスを共有) · MCP 経由のネイティブ起動/ビルド(native_open/native_close/native_build) · 共有モードの stdio 自動接続(stdio エントリーは稼働中のデーモンに接続 — またはデーモンを起動 — し、ローカルインスタンスにフォールバック) · MCP の完全な同等機能(拡張機能管理 ext_*、browser_back/forward/reload、pane_set_label)。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。
