From 22c054f1791ca049bb21d7ae6fc44d61ec00d684 Mon Sep 17 00:00:00 2001 From: gapul <92638132+gapul@users.noreply.github.com> Date: Mon, 31 Aug 2026 00:16:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(browser):=20=E5=8B=95=E7=B7=9A?= =?UTF-8?q?=E3=82=92=203=20=E6=AE=B5=E3=81=AB=E3=81=97=E3=80=81=E5=AE=9F?= =?UTF-8?q?=20Chromium=20=E3=81=AE=E5=BD=B9=E3=82=92=20terminal-browser=20?= =?UTF-8?q?=E3=81=AB=E6=B8=A1=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #514 で 4 段と書いたのは整理を誤っていた。1 と 2 はコストの階段だが、3 と 4 は どちらも実 Chromium で重さがほぼ同じで、分かれ目は「見せるか見せないか」 だった。梯子ではなく、2 段の下に枝が生えている形。 terminal-browser に寄せる。3 段に畳んで、Helium は動線から外す。 1. WebFetch 2. Lightpanda (9223 / MCP 8932) — 裏で回す既定、14MB 3. terminal-browser — 実 Chromium、必ず見える 8931 の playwright-mcp は撤去した。繋ぐ相手が居なくなるため。terminal-browser も CDP は出しているが、**ポートが起動のたび変わる** (実測 53218 → 53337) ので固定の --cdp-endpoint では掴めない。あれは `terminal-browser action` で駆動するのが 正しい入口。 Helium 自体は残す。ヘッドレスで WebGL とスクリーンショットが要る検証 (vrma-lab の scripts/chrome-lab.sh) がまだそこに依存していて、Lightpanda は レンダラを持たず、terminal-browser は必ず見えてしまうので代われない。 動線には出てこないもの、という位置づけを CLAUDE.md に明記した。 --- configs/cli/claude/CLAUDE.md | 25 +++++---- nix/modules/home/darwin-services.nix | 80 ++++------------------------ 2 files changed, 22 insertions(+), 83 deletions(-) diff --git a/configs/cli/claude/CLAUDE.md b/configs/cli/claude/CLAUDE.md index 63c49282..bcbe1c15 100644 --- a/configs/cli/claude/CLAUDE.md +++ b/configs/cli/claude/CLAUDE.md @@ -8,7 +8,7 @@ - UTCではなくJST(日本時間)を使用 ### ブラウザ操作 -常用ブラウザはZen。自動化は用途ごとに4段で、上から順に安い方を選ぶ。 +常用ブラウザはZen。自動化は3つで、まず1、足りなければ2、見せる必要があれば3。 Chromeは2026-08-30に撤去した(Claude in Chrome拡張ごと)。拡張ができることはPlaywrightで 全部できたうえ、拡張は`--remote-debugging-port`を開けている間ずっと、localhostの誰にでも ブラウザを明け渡す状態を作っていた。 @@ -17,21 +17,20 @@ Chromeは2026-08-30に撤去した(Claude in Chrome拡張ごと)。拡張が 2. **Lightpanda**(常駐、CDP=9223 / Playwright MCP=`http://localhost:8932/mcp`) 裏で回す既定。実測14MB。見えないし軽いので常駐させたままでよい。 ただし実装していないAPIに触るSPAは**エラーではなく空で返る**。取れた内容が - 空だったらここを疑い、下に落とす。 -3. **terminal-browser** — 見せる担当。Electron同梱の実Chromiumなので描画の穴がなく、 - `terminal-browser open --split right ` で会話の隣に並ぶ。操作は + 空だったらここを疑い、3へ落とす。 +3. **terminal-browser** — 実Chromium(Electron同梱)なので描画の穴がない。 + `terminal-browser open --split right ` で会話の隣に並び、操作は `terminal-browser action -- snapshot|click|fill|eval`。ssh越しも可 - (`open --ssh user@host `)。TTYが無くても見えるペインを開くので、 - **ユーザーの目視が要らない場面では使わない**。 -4. **Helium**(ungoogled-chromium)— フルのChromiumが要るとき。 - `open -gjn -a Helium --args --user-data-dir=... --no-startup-window --remote-debugging-port=9222` - で起こすと`http://localhost:8931/mcp`のPlaywright MCPが掴む。常駐させない。 - 9222はローカルに開いたポートなので、使い終わったら落とす。 - ungoogledなのでGoogleログインは通らない見込み。それが要る仕事は今この機械にはない。 + (`open --ssh user@host `)。終わったら`terminal-browser shutdown`。 + **必ず見えるペインを開く**(TTYが無くても右に分割する)ので、ユーザーの + 目視が要らない場面では2で粘る。 + Playwrightからは掴めない: CDPは出しているが**ポートが毎回変わる** + (実測 53218 → 53337)ので、固定の`--cdp-endpoint`にできない。`action`で操作する。 - 速度は描画ではなく往復回数で決まる。読み取りだけなら1と2で足りる。 -- `--headless=new`をChromeで試した記録が残っているが(2026-08-10、拡張のnative hostが - 起動しない)、Chromeごと無くなったので過去の話。Lightpandaは最初からheadless。 +- Heliumはこの動線には出てこない。ヘッドレスでWebGL/スクリーンショットが要る + 検証(vrma-lab の`scripts/chrome-lab.sh`)専用に残してある。Lightpandaは + レンダラを持たないのでそこは代われず、terminal-browserは必ず見えてしまう。 - ポートの確認は`netstat -an | grep LISTEN`で。**この機械に`/usr/bin/lsof`は無い**ので、 lsofは黙って空を返し、空きポートに見えてしまう(9333で実際に踏んだ)。 diff --git a/nix/modules/home/darwin-services.nix b/nix/modules/home/darwin-services.nix index 26b70fde..a43f7ad8 100644 --- a/nix/modules/home/darwin-services.nix +++ b/nix/modules/home/darwin-services.nix @@ -55,50 +55,22 @@ in # The MCP entry in ~/.config/claude/.claude.json used to be `stdio`, which means every session # spawns its own server process: measured 2026-08-15 at 15 sessions = 15 node processes, 176MB, # and ~120MB each once a session actually drives the browser. All of them attach over CDP to the - # same Chrome on 9222 anyway, so the isolation bought nothing. Listening on 8931 and pointing - # every session at `http://localhost:8931/mcp` collapses that to one process (70MB idle). + # same browser anyway, so the isolation bought nothing. Listening on a port and pointing every + # session at it collapses that to one process (70MB idle). # # Sessions still share the browser, so a parallel run must give each session its own tab # (`browser_tabs {action:"new"}` before navigating) — verified: without it two sessions grab the # same page and the second navigation wins. # # localhost-bound by the server itself, and it rejects any request whose Host is not - # `localhost:8931` (127.0.0.1 in the URL gets a 4xx — write the URL with localhost). - # The connection is lazy, so this stays cheap while nothing is on 9222 — the normal state. - # Chrome used to be what listened there; it was dropped on 2026-08-30 and Helium takes the - # role, started only for a job (see CLAUDE.md) and killed after. - # Binary comes from nixpkgs (0.0.69). It used to be the pnpm global install, but that store - # evaporated: both ~/Library/pnpm/bin/node and the @playwright/mcp package were symlinks into - # store paths that no longer exist, so the agent died with "node: not found" and then - # "Cannot find module .../cli.js". npm's latest is 0.0.79 — a patch ahead, which is a cheap - # price for not depending on a global store nothing declares. - # Lightpanda: the cheap CDP target for background work. 14MB resident against the 296MB a full - # Chromium takes (both measured here), so unlike that one this can just stay up — there is no - # "start it for the job and kill it after" dance. The heavy browser stays the exception, for - # the SPAs Lightpanda renders empty. - launchd.agents.lightpanda = { - enable = true; - config = { - ProgramArguments = [ - "/run/current-system/sw/bin/lp" - "serve" - # 9333 ではない。あそこには別に立てたヘッドレス Chrome が既に居て - # (/json/version が Chrome/152 を返す)、Lightpanda が AddressInUse で - # 起動できなかった。9223 は 9222 の実 Chrome の隣という意味。 - "--port" - "9223" - ]; - RunAtLoad = true; - KeepAlive = true; - ProcessType = "Background"; - StandardErrorPath = "/tmp/lightpanda.err"; - StandardOutPath = "/tmp/lightpanda.log"; - }; - }; - - # Second playwright-mcp, pointed at Lightpanda instead of Chrome. Two instances rather than - # switching one: the Chrome-backed 8931 keeps working exactly as before, and the caller picks - # a port instead of a mode. Both connect lazily, so an idle one costs nothing. + # `localhost:8932` (127.0.0.1 in the URL gets a 4xx — write the URL with localhost). + # + # There used to be a second instance on 8931 aimed at 9222, for whatever full browser was + # started for a job. It went away with Chrome: terminal-browser took that role and cannot be + # driven this way — it does expose CDP, but on a port that changes every launch (measured + # 53218 → 53337), so no static --cdp-endpoint can find it. It is driven by its own + # `terminal-browser action` instead. Binary comes from nixpkgs (0.0.69). + # Playwright MCP, pointed at Lightpanda. Connects lazily, so it costs nothing while idle. launchd.agents.playwright-mcp-light = { enable = true; config = { @@ -120,38 +92,6 @@ in }; }; - launchd.agents.playwright-mcp = { - enable = true; - config = { - ProgramArguments = [ - "${lib.getExe pkgs.playwright-mcp}" - "--cdp-endpoint" - "http://127.0.0.1:9222" - "--port" - "8931" - "--output-dir" - "${config.home.homeDirectory}/tmp/playwright-mcp" - ]; - EnvironmentVariables.PATH = mcpPath; - RunAtLoad = true; - KeepAlive = true; - ProcessType = "Background"; - StandardErrorPath = "/tmp/playwright-mcp.err"; - StandardOutPath = "/tmp/playwright-mcp.log"; - }; - }; - - # Shell-independent env distribution: GUI apps / processes under launchd don't go through - # zsh's .zshenv (hm-session-vars.sh is effectively only read by zsh), so they receive none of - # home.sessionVariables' env. The most notable case is the accident where an unset GNUPGHOME makes - # gpg regenerate an empty ~/.gnupg, but EDITOR/PAGER/various telemetry opt-outs/XDG bases/CARGO_HOME etc. - # are also missed on the GUI side. At login, push them into the whole session via launchctl setenv to cut the zsh dependency. - # - # Auto-generated from home.sessionVariables rather than hardcoded (single source, drift prevention). - # Values are made safe with escapeShellArg (handles values with spaces/quotes like MANPAGER). - # Variables whose value contains "$" (e.g. the TERMINFO_DIRS that home-manager injects, - # "...:$TERMINFO_DIRS${TERMINFO_DIRS:+:}...") assume shell expansion at export time and - # break under the non-expanding launchctl setenv (a literal $ gets in), so they're excluded and left to zsh. launchd.agents.session-env = { enable = true; config = { From c29641561f07a07b86fdc446ad09de43dff5d2ae Mon Sep 17 00:00:00 2001 From: gapul <92638132+gapul@users.noreply.github.com> Date: Mon, 31 Aug 2026 02:19:49 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix(herdr):=20kitty=5Fgraphics=20=E3=82=92?= =?UTF-8?q?=E6=9C=89=E5=8A=B9=E3=81=AB=E3=81=97=E3=81=A6=20terminal-browse?= =?UTF-8?q?r=20=E3=82=92=E5=AE=9F=E9=9A=9B=E3=81=AB=E6=8F=8F=E3=81=8B?= =?UTF-8?q?=E3=81=9B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configs/cli/claude/CLAUDE.md | 9 +++++++++ configs/cli/herdr/config.toml | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/configs/cli/claude/CLAUDE.md b/configs/cli/claude/CLAUDE.md index bcbe1c15..2069f155 100644 --- a/configs/cli/claude/CLAUDE.md +++ b/configs/cli/claude/CLAUDE.md @@ -26,6 +26,15 @@ Chromeは2026-08-30に撤去した(Claude in Chrome拡張ごと)。拡張が 目視が要らない場面では2で粘る。 Playwrightからは掴めない: CDPは出しているが**ポートが毎回変わる** (実測 53218 → 53337)ので、固定の`--cdp-endpoint`にできない。`action`で操作する。 + herdrの`[experimental] kitty_graphics`が要る(既定false)。切れているとペインは + 作られてブラウザも生きているのに**何も描かれない**。無言で失敗するので注意。 + 見えているかの確認は`terminal-browser ls`ではなくherdrに聞く。`ls`は自分の + モデルを喋るだけで描画を保証しない(`pane`も`viewport`も返るのに真っ白だった)。 + `herdr pane process-info --pane `の前面プロセスがterminal-browserなら生きて + いて、`herdr pane read `が**空なら正常**(絵はテキストに写らない)。逆に + コマンド行とプロンプトが読めたらそれは死骸のシェル。 + `shutdown`は残骸を残す。次の`open`がそれを拾うと`tty`も`cdpPort`も無いJSONを + 返して終わり、空のペインだけが積もる。`pkill -f agent-browser`してから開き直す。 - 速度は描画ではなく往復回数で決まる。読み取りだけなら1と2で足りる。 - Heliumはこの動線には出てこない。ヘッドレスでWebGL/スクリーンショットが要る diff --git a/configs/cli/herdr/config.toml b/configs/cli/herdr/config.toml index 6240dd65..5adcd6cc 100644 --- a/configs/cli/herdr/config.toml +++ b/configs/cli/herdr/config.toml @@ -45,3 +45,10 @@ show_agent_labels_on_pane_borders = true # そのときは rclone の死んだ NFS マウントが残っていて mds が getattrlistbulk で # 止まっていた)。OS 通知自体は Claude Code の Stop フック (agent-notify) が osascript で # 出しているので、外しても手元に届く通知は変わらない。むしろ二重通知が一本になる。 + +[experimental] +# terminal-browser がペインに絵を出すのに要る。既定は false で、切っていると +# ペインは作られてブラウザのプロセスも前面に居座るのに、中身が何も描かれない。 +# エラーも出ないので「開いたのに見えない」という形でしか気づけない。 +# herdr はクライアント側で kitty graphics を合成して Ghostty へ渡す。 +kitty_graphics = true