VS Code 1.120 のターミナル出力圧縮とリスク評価がなかなかよさそう

TL;DR — VS Code 1.120 でプレビュー追加されたターミナル出力圧縮(chat.tools.compressOutput.enabled)とリスク評価(chat.tools.riskAssessment.enabled)。圧縮はコンテキスト管理、リスク評価は実行前の安全確認と役割が違う。特に圧縮は RTK と処理レイヤーが完全に別なので共存できる(らしい)。

何が追加されたか

VS Code 1.120 のリリースノートを眺めていたら、エージェント周りで自分の関心をひく機能が 2 つ入っていた。

ターミナル出力の自動圧縮ターミナルコマンドのリスク評価だ。

ターミナル出力の自動圧縮

設定は Chat › Tools › Compress Output: Enabled。これはプレビュー。

Claude さんの解説は以下。

有効にすると、エージェントがターミナルコマンドを実行したあと、その出力をモデルに送る前に VS Code 側で自動的に削減してくれる。具体的には以下の処理が入る。

  • git diff の差分で変更のない部分を折りたたむ
  • lockfile や snapshot の差分を丸ごと除外
  • ls -l をファイル名だけに削減
  • npm install の進捗バー・非推奨警告・audit サマリーを除去

圧縮された出力には先頭にバナーが付く。「どのフィルタが適用されたか」「生のテキストが必要なら圧縮を無効にできる」という情報をモデルに伝えるためのやつ。モデルが圧縮済みであることを認識できるのは地味に大事。

いや、これ RTK と同じじゃね?

AI を提供している会社のどれかがそのうち自社で実装するかもなー、とか思ってたけど案外早かったな。

リスク評価

設定は Chat › Tools › Risk Assessment: Enabled。こちらはエクスペリメンタル。

おなじみの Claude さんの解説は以下。

エージェントがターミナルコマンドを実行しようとしたとき、確認ダイアログにリスクバッジと AI 生成の説明が表示されるようになる。バッジは 3 段階。

バッジ意味
🟢 Safeファイルの読み取りや出力のみ。変更なし
🟠 Cautionワークスペースへの変更やネットワーク呼び出しを含む
🔴 Review carefullyforce push や外部への削除など、要注意な操作

バッジの横に 1 文のサマリーが出る。「このコマンドが何をするか」を一言で教えてくれるやつ。自動承認の判断材料として使える。

VS Code の Chronicle 機能が結構便利だった

TL;DR — Chronicle は Copilot Chat のチャット履歴をローカルで記録・分析する実験的機能。/chronicle:standup でその日の作業サマリー、/chronicle:tips で自分の使い方フィードバックが出せる。これがなかなか良い。Claude にはこういう公式機能はないけど、自宅では QMD で履歴検索は実現してる。

職場で VS Code を使っていて、ふと試してみた機能の話。

Chronicle とは

VS Code v1.118 で実験的に追加された GitHub Copilot Chat の機能。Copilot とのやり取り、編集したファイル、参照した PR や Issue あたりをローカルの SQLite データベースに記録しておいて、あとから振り返ったり分析したりできる。

で、早速使ってみた。

有効化は github.copilot.chat.localIndex.enabledtrue にするだけ。

GUI の設定じゃないのはまだプレビュー段階だからかな。

使えるコマンドは主に 3 つ。

/chronicle:standup 過去 24 時間の作業内容をまとめてくれる。「このブランチでこのファイル触って、この PR を参照した」みたいな感じで出てくる。朝会の準備が秒で終わるらしい(使ったことはない)。

/chronicle:tips 7 日間の使い方を分析して、「お前こういうプロンプトの書き方してるけど、こうしたほうが良くね?」みたいなフィードバックをくれる。自分の癖を指摘してもらえるのがおもしろいし、フィードバックがまあまあためになる。これはよき。

/chronicle [query] 自然言語で過去の履歴を検索できる。「先週やってたあれ、なんだっけ」が出てくる。

試してよかったのは tips

「同じような質問を繰り返してる」とか「毎回コンテキストを初めから説明してる」みたいな自分のパターンを指摘してくれる。ほう、わかってんじゃねーかこいつ…

Copilot との対話の仕方に改善余地があると気づかせてくれるのが嬉しい。

やるじゃん。

Claude だと?

で、家で使ってる Claude Code でこういう機能があるかというと、公式にはない。 そこんとこどうなんよ?と Claude さんに聞いてみた結果が以下。

RTK に issue 立ててプルリク作った話

TL;DR — RTK に立てた issue が1週間放置されたので自分でプルリクを出した。run_in_terminal の未認識バグを修正し、重複関数を統合。ローカル確認では mise と linuxbrew の PATH 競合に引っかかったが解決し、PR #1800 を提出した。

前の記事で「引き続き更新を待つかぁ」と書いたやつの続き。

1週間待ったけど動きがなかった

Issue #1425 を立てたあと、1週間ほど本体の動向を見ていた。メンテナさんも忙しいだろうし、そんなもんかと思っていたけど、なかなか動きがない…

うん。待つの飽きた。

「どうせなら自分でプルリクを出してしまえ」

リファクタしてからプルリクを作る

ローカルには fix(hooks): VS Code Copilot Chat... というコミットがすでにあった。ただそのまま出すのは品質的に不安だったので、upstream/develop ベースでブランチを切り直して cherry-pick し、ついでに既存のコードベースのお作法を調査してリファクタも入れた。

変更の内容は3つ:

  1. detect_format()"run_in_terminal" を追加 VS Code Copilot Chat が渡す tool_name の値で、これが認識されないとフックが PassThrough になっていた。根本的なバグ修正。

  2. handle_vscode()handle_copilot_cli()handle_copilot_rewrite() に統合 ほぼ同じロジックが2関数に分散していたので1つにまとめた。

  3. VS Code 向けのレスポンスを allow/ask + updatedInput から deny + suggestion に変更 前の記事で書いた「承認ループ」の回避。Copilot Chat は updatedInput を承認後に無視するので、Copilot CLI と同じ deny + reason 方式に統一した(詳細は #1425)。

QMD の MCP サーバーをやめて Bash で直接叩くようにした

TL;DR — QMD の MCP サーバーが重すぎたので、プラグインを削除して qmd query --no-rerank を Bash で直接呼ぶ運用に切り替えた。リランカーなしでも BM25 + ベクトル検索の組み合わせで十分実用的。

以前の記事で QMD を MCP サーバーとして導入した話を書いた。

その後、重さが気になり過ぎて運用を見直した話。

いや、本気で重かったのよ。全然結果が返ってこない。

なにこれとか思って調べたら GPU なしだとこんなもんだろうとのこと。

そうですかぁ…

今の運用

ということでどうしたかというと、Claude さんが過去セッションを検索するときは、MCP ツールではなく Bash コマンドを直接叩くようになった。

qmd query --no-rerank "調べたいキーワード"

CLAUDE.md に「QMD は qmd query --no-rerank で使う」と書いてあるので、Claude さんが自動でこの形式で呼ぶ。settings.jsonpermissions.allow には Bash(qmd *) を追加済み。

なぜ重かったか

以下 Claude さんの解説。

QMD は内部で 2 つのローカル ML モデルを動かしている。

モデルサイズ用途
embeddinggemma-300M-Q8_0.gguf314 MBベクトル埋め込み生成
Qwen3-Reranker-0.6B-Q8_0.gguf610 MB検索結果のリランキング

自分の環境は専用 GPU がなく CPU 推論になるので、2 モデル合計で 924 MB がオンメモリに乗る。MCP サーバーとして常駐させていると、起動のたびにこれをロードして複数プロセスを spawn する。qmd query(MCP が使う推奨コマンド)はさらにリランキングまで走らせるので、検索 1 回に数分かかることもあった。

WSL の playwright-cli からホスト Windows の Chrome にアタッチする

TL;DR — WSL2 ミラーモードなら --cdp=chrome チャンネル名は使えないが、Chrome を --remote-debugging-port=9222 で起動して --cdp=http://localhost:9222 を使えばアタッチできる。Firewall ルールも不要。なお、--remote-debugging-address は非 headless Chrome では無視され、Chrome は常に 127.0.0.1 にバインドする。localhost で繋がるのはミラーモードが 127.0.0.1 を通してくれるおかげ。

どっかで聞いたところによると…

playwright-cli(@playwright/cli)には、起動済みの Chrome にアタッチしてそのセッションをそのまま操作できる機能があり、SAML/SSO 認証済みのページを操作したいときにサンドボックスの Chrome にログインし直す手間が省ける、とのことです。

確かに便利そうなんだけど、この機能を WSL2 から使おうとしてハマったので記録しておきます。

ほんと大体ハマってんな俺。

やりたいこと

WSL 上の playwright-cli から、ホスト Windows で開いている Chrome(ログイン済み)にアタッチして操作する。

前提

  • WSL2 ネットワークモード:ミラーモード(networkingMode=mirrored
  • playwright-cli:0.1.9mise use --global npm:@playwright/cli@latest でインストール)
    • 前回自宅でハマったので職場では間違えなかった

チャンネル名(--cdp=chrome)は WSL から使えない

そもそもこれが駄目だった。

以下は Claude さんの解説です。

playwright-cli には microsoft/playwright#40177(2026年4月マージ)で、チャンネル名でアタッチできる機能が追加された。

playwright-cli attach --cdp=chrome

これは DevToolsActivePort ファイルを読んでポートを自動解決する仕組みなのだが、WSL では動かない。

原因は process.platform。WSL 上では linux になるため、スクリプトは ~/.config/google-chrome/DevToolsActivePort(Linux のパス)を探しに行く。ホスト Windows の Chrome が書き込むのは %LOCALAPPDATA%\Google\Chrome\User Data\DevToolsActivePort なので、当然見つからない。

NanoClaw のアップデートで RTK が pnpm test を素通りしてた話

TL;DR — RTK の rewrite は pnpm run build を圧縮するが pnpm test(実体は vitest run)は素通り。加えて /update-nanoclaw/update-skills を同一コンテキストで自動呼び出ししていた。SKILL.md を2行変えて解決。

NanoClaw の大型アップデート来ましたね。かなり中身が変わっていてローカルでのマージにものすごく時間がかかりました。最終的には、

「もう俺の作ったスキルさえ無事なら後はどうでもいいから全部上書きしちゃって!」

と雑な投げ方をしてアップデートをしてもらいました。

無事(一部無事じゃなかったけど git のログから復旧した)終わったんだけど、後日再度 /update-nanoclaw を実行した時の話です。

/update-nanoclaw を実行したら5時間制限の40%くらいを1回で使い切ってしまった。なにこれ、と思って Claude さんに調べてもらった。

以前 RTK を入れた記事を書いたとき、「効果はこれからに期待」と書いたんだけど、うまく行かなかったようで…

以下は、Claude さんに解説してもらった文章です。

RTK の仕組みをおさらい

RTK は Claude Code の PreToolUse hook として動く。Bash ツールが呼ばれるたびに rtk hook claude が起動し、rtk rewrite "<コマンド>" でコマンドを書き換えられるか確認する。

  • 書き換えできる(exit 3)→ rtk <subcommand> が代わりに実行され、出力が圧縮される
  • 書き換えできない(exit 1)→ 元のコマンドがそのまま実行される(RTK はノータッチ)

何が素通りしていたか

rtk rewrite "pnpm run build"
# → rtk pnpm run build(exit 3: 書き換え成功)

rtk rewrite "pnpm test"
# → (何も出力なし、exit 1: 書き換えなし)

pnpm run build は圧縮される。でも pnpm test は exit 1 で素通り。

Ubuntu 初期設定メモ:日本語入力・CapsLock・HackGen フォント

TL;DR — Ubuntu を入れたら最初にやること3つ:fcitx5+Mozc で日本語入力、CapsLock → Ctrl リマップ、HackGen Nerd Font インストール。

ふと思い出したけど、MacBook Pro 2015 Mid に Ubuntu 24.04 を入れてから安定するまでの道のりはひどかった…

それ書いて満足してたんだけど、一番先にやってた日本語入力のあれこれを記事にしてなかったので、やったこと3つをここに書いておく。

ちなみにデスクトップは全然いじってなくて壁紙変えたくらいなので、標準の Ubuntu デスクトップ環境です。

設定1:日本語入力(fcitx5 + Mozc)

Ubuntu のデフォルト IME は IBus なんだけど、IBus+Mozc は動作が不安定なことがある(変換がもたつく、日本語にすると直接入力モードが選択されてデフォルト英字になるなど)。

頭来たので、fcitx5 に乗り換えた。

インストール

sudo apt remove --purge ibus-mozc ibus-table
sudo apt install -y fcitx5 fcitx5-mozc fcitx5-configtool
im-config -n fcitx5

Ctrl+Space の競合を解消

GNOME が Ctrl+Space を入力ソース切り替えとして横取りしているので無効化する。

gsettings set org.gnome.desktop.wm.keybindings switch-input-source "[]"

これで fcitx5 が Ctrl+Space を受け取れるようになる。

あとは fcitx5-configtool を起動して Mozc を追加し、トリガーキーに Ctrl+Space を割り当てれば完了。

npm グローバル管理から mise に移行したら npm キャッシュにハマった話

TL;DR — mise の npm バックエンドで @latest が存在しないバージョンに解決される場合、mise cache clear で mise の versions host キャッシュを消すと直る。

npm でグローバル管理していたツールを mise に移行しようとしたら、キャッシュ問題でちょっとハマったので記録しておく。

移行対象

$ npm list -g --depth=0
├── @playwright/[email protected]   ← 新しいやつ(旧: playwright-cli)
├── @tobilu/[email protected]
├── @playwright/[email protected]
└── [email protected]

今回 mise に移行したのは @playwright/cli@tobilu/qmd の2つ。

@playwright/cli の移行でハマった

まず Deprecated なパッケージを入れてしまう

まず playwright-cli(旧・Deprecated)と @playwright/cli(新)を間違えて Deprecated の方を mise に入れてしまった。mise unuse で無効化してから改めてやり直し。

そしたら謎のエラーが出た。

$ mise use --global npm:@playwright/cli@latest
npm error code ETARGET
npm error notarget No matching version found for @playwright/[email protected].

@latest を指定しているのに 0.262.0 という存在しないバージョンを引いてくる。なにそれ。

mise + linuxbrew 環境で cargo install したバイナリが VSCode に認識されない問題

TL;DRmise で Rust を管理している環境では .cargo/env が no-op になる。.profileexport PATH="$HOME/.cargo/bin:$PATH" と無条件に書くのが確実。

前の記事RTK のバグ報告のために深夜にせこせこやってたんですよ。

で、cargo install --path . してローカルのバイナリで確認しようとしたら、Claude Code が旧バイナリを使い続ける。小一時間ハマってイライラしたので記録しておく。

症状

cargo install --path .   # ローカル fix 済みバイナリをインストール
which rtk                # → /home/linuxbrew/.linuxbrew/bin/rtk  ← 旧バイナリ

~/.cargo/bin/rtk のはずが、linuxbrew の rtk が勝っている。

なにやっても変わらねぇ…

調査

PATH の順序

1  ~/.local/share/mise/shims
2  /home/linuxbrew/.linuxbrew/bin   ← ここで rtk を拾う
...
7  ~/.cargo/bin

linuxbrew が .cargo/bin より前にいるんでよくある単純な PATH 順の問題だろうと甘く見てました。はい。

そこからはまりまくった。

.bashrc に追記しても効かない

Claude さんのおすすめにより、.bashrc 末尾に . "$HOME/.cargo/env" を追記して VSCode を再起動、結果変わらず。そりゃそうだろ。前調べた時って非インタラクティブじゃなかったっけ?

WSL + VSCode Copilot Chat で RTK インストールしたら動かなかった話

TL;DR — RTK のフックが vscode の Copilot Chat では動かない(2つの理由がある)。フックをやめてグローバルインストラクションに .github/copilot-instructions.md の内容を転記すれば Copilot が自発的に rtk プレフィックスを使うようになった。

職場の WSL 環境に RTK をインストールして VSCode Copilot Chat と組み合わせようとしたら、フックが全然動かなかった。調査した結果と、現状の対策を書いておく。

RTK とは

RTK(Rust Token Killer) は CLI プロキシで、コマンド出力を 60〜90% 圧縮して AI エージェントのトークン消費を削減するツール。git status の代わりに rtk git status を使うと、AI に渡る出力がコンパクトになる。

前の記事でも紹介したなこれ。書かなくてもいいかと思ったけど一応書いておく。

rtk init -g は Copilot 向けではない

RTK のセットアップで rtk init -g を実行すると Claude Code 向けのフックしか設置されない。Copilot 向けは --copilot フラグが必要:

rtk init -g --copilot

ただし -g(グローバル)をつけても実質プロジェクトスコープで、このコマンドを実行したディレクトリの .github/ 以下に copilot-instructions.mdhooks/rtk-rewrite.json が生成される。