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つ:
detect_format()に"run_in_terminal"を追加 VS Code Copilot Chat が渡すtool_nameの値で、これが認識されないとフックが PassThrough になっていた。根本的なバグ修正。handle_vscode()とhandle_copilot_cli()をhandle_copilot_rewrite()に統合 ほぼ同じロジックが2関数に分散していたので1つにまとめた。VS Code 向けのレスポンスを
allow/ask + updatedInputからdeny + suggestionに変更 前の記事で書いた「承認ループ」の回避。Copilot Chat はupdatedInputを承認後に無視するので、Copilot CLI と同じdeny+ reason 方式に統一した(詳細は #1425)。
// before: handle_vscode / handle_copilot_cli に重複していたロジック
// after: handle_copilot_rewrite に統合
fn handle_copilot_rewrite(cmd: &str) -> Result<()> {
let rewritten = match get_rewritten(cmd) {
Some(r) => r,
None => return Ok(()),
};
let output = json!({
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": format!(
"Token savings: use `{}` instead (rtk saves 60-90% tokens)",
rewritten
)
}
});
println!("{}", output);
Ok(())
}
cargo test は 1819 passed, 0 failed。test_detect_vscode_run_in_terminal と test_copilot_deny_output_vscode_format を新たに追加してあるので、次に繋がるかと思う。
ローカル動作確認で罠にはまった
テストは通っていたけど、一応 VS Code Copilot Chat で実際に動かして確認しようとした。
cargo install --path . でバイナリをインストールして Copilot Chat でコマンドを実行したら、VS Code の Output パネル(「GitHub Copilot Chat Hooks」チャンネル)のログがこうなった:
[PreToolUse] Running: {"command":"rtk hook copilot",...}
[PreToolUse] Completed (Success) in 16ms, no output
フックは呼ばれてるのに no output。run_in_terminal が認識されていないときの挙動(PassThrough = 無出力)と同じだ。
原因を調べたら、mise の activate bash --shims が linuxbrew の rtk を優先していた。cargo install で ~/.cargo/bin/rtk を更新しても、Copilot Chat が開くインタラクティブシェルでは linuxbrew 側の古いバイナリを見に行っていた。
/tmp に置いたスクリプトで呼び出すと修正済みバイナリが動いて deny JSON が出るのに、rtk hook copilot 直打ちだと動かない、という奇妙な状況だった。
パスの問題と分かれば話は早い。シェルの PATH を整理して新しいバイナリを確認し、Copilot Chat を再起動したらちゃんと動いた:
[PreToolUse] Running: {"command":"rtk hook copilot",...}
[PreToolUse] Completed (Success) in 18ms
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny",
"permissionDecisionReason":"Token savings: use `rtk git status` instead ..."}}
no output だったログに deny JSON が出るようになった。
プルリク提出
動作確認が取れたのでプルリク提出。
fix(hooks): recognize run_in_terminal for VS Code Copilot Chat #1800
upstream のコントリビューションガイドと PR テンプレに沿って英語で書いた。というか、Claude さんに書いてもらった。
upstream へそのままマージされると嬉しいんだけど、どうなることやら。