VS Codeの新機能Custom Chat Modeを使って指定した手順通りにGitHubにpushしてもらう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/aba02aea-2f7c-49c3-9eb1-b389d766736b.png)


## これは何?

最近のVS Codeのリリースで新たににCustom Chat Modeが追加されました!

https://code.visualstudio.com/updates/v1_101#_custom-chat-modes-preview

この機能を使うと新たにオリジナルChat Modeを作ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/66ac3add-0846-4234-9a88-c0d0634278ee.png)

↑自分が作成した「github-push」というCustom Chat Modeが使用できるようになっている。

---

## 既存機能と何が違うの?

今までは，GitHub Copilotのシステムプロンプトとしては，`.github/copilot-instructions.md`を使用することができていました。

https://docs.github.com/ja/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot

しかし，すべてのプロンプトをこのファイルに記載する必要があったため，

- 長いプロンプトだと無視されやすい。
- 使用するツールの権限管理ができない

等の問題がありました。

:::note
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/3e0fdc23-4829-4787-8920-bd8809bf2a3d.png)
↑そもそも1つのリクエストに128以上のツールを含めるとエラーになる。
:::

しかし，今回追加されたCustom Chat Modeでは個別に使用できるツールを制限させることができます。

```md
---
description: Generate an implementation plan for new features or refactoring existing code.
tools: ['codebase', 'fetch', 'findTestFiles', 'githubRepo', 'search', 'usages']
---
# Planning mode instructions
You are in planning mode. Your task is to generate an implementation plan for a new feature or for refactoring existing code.
Don't make any code edits, just generate a plan.

The plan consists of a Markdown document that describes the implementation plan, including the following sections:

* Overview: A brief description of the feature or refactoring task.
* Requirements: A list of requirements for the feature or refactoring task.
* Implementation Steps: A detailed list of steps to implement the feature or refactoring task.
* Testing: A list of tests that nee
```

そのため，AIエージェントによる暴走を抑制できます。

---

## とりあえず，使ってみるが動かない

練習のため，GitHubにPRを作成するCustom Chat Modeを作ってみます。

### GitHub MCPサーバの設定

settings.jsonに以下の設定を追加します。

https://github.com/github/github-mcp-server

```settings.json
{
  "servers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    }
  }
}
```

### Custom Chat Modeの追加

Ctrl shift pを押してコマンドパレットを開き，`Chat: Configure Chat Mode`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/ba1ef300-55c4-4ccf-b939-7c5bbff79dd2.png)

名前は`github-push`にしましたが，なんでも良いです。

設定ファイルに以下を記載します。Toolは適当に必要そうなやつを選んでみました。

「Configure Tools...」を押下するとツールの一覧が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/fc50c8e8-84dc-4d9e-a380-1c40e31ad5e3.png)


```github-push-chatmode.md
description: 'Pull Requestを作成するためのモード'
tools: [<適当に選んだツールたち>]
---
ユーザからPull Requestを出すように指示があった場合には以下の手順で進めてください。
コミットメッセージやブランチ名などはユーザから指示がない場合にはあなたが推測して決めてください。
- `git branch`を実行し，現在のブランチ情報を取得する
- 現在のブランチがmainもしくはmasterでない場合には`git checkout`コマンドを使い，あたらしいブランチを作成する。ブランチメッセージは以下の形式とし，英語にする。
  - feature/開発機能名
  - hotfix/バグ修正内容
  - refactor/リファクタリング内容
- `git add .`を実行し，変更をステージする
- `git commit -m <コミットメッセージ>`を実行し，変更をコミットする。ただし，コミットメッセージは以下の形式とする。
  - feat: (feature)
  - fix: (bug fix)
  - docs: (documentation)
  - style: (formatting, missing semi colons, …)
  - refactor: (refactoring)
  - test: (when adding missing tests)
  - chore: (maintain)
- git push -u origin <作成したブランチ名>を実行し変更をリモートリポジトリに更新します。mainやmasterに直接pushしてはいけません。

```

いざ実行してみるとコマンド実行権限がないと怒られます。

```
現在、ファイル編集やターミナルコマンド実行のためのツール（編集・pushなど）が無効化されているため、実際のgit操作（add/commit/pushなど）を自動で実行できません。

権限や認証の問題ではなく、「AIが直接コマンドを実行するための機能」が有効になっていない状態です。
もし自動でpushまで進めたい場合は、ファイル編集やターミナル実行のツールを有効化してください。

有効化後は、指示に従い自動で全手順を進めます。
```

このあたりを試してみましたが解決せず


- VS Codeの再起動
- Dev Containersを一旦やめる
- Github Copilot Chatが最新か確かめる

:::note warn
2025年6月21日追記
[reddit](https://www.reddit.com/r/GithubCopilot/comments/1lf2gvf/why_does_copilot_gpt4o_41_agent_mode_feel_more/)でこんな記事がでてきました。
GPT-4oやGPT-4.1を使うとAskやEditモードのような動作をするとのこと。
もしかしたら，GPT-4oを使うとうまくいかないのかもしれない。
:::

### 補足: ツールが動かない問題

自分と同じ問題が起こっている人が結構いるみたい。

https://github.com/microsoft/vscode/issues/251313

---

## とりあえず，GitHubの操作はできたがだめそう。
Claude Sonnet 4に泣きついたところ，「Configure Tools...」にないツールが追加されました。そしてその状態だとコマンド実行できるようになった。
どうなってんねん!

<details><summary>details</summary>

```github-push-chatmode.md
---
description: 'Pull Requestを作成するためのモード'
tools: ['run_in_terminal', 'create_file', 'insert_edit_into_file', 'replace_string_in_file', 'mcp_github_create_branch', 'mcp_github_get_commit', 'mcp_github_get_issue', 'mcp_github_get_issue_comments', 'mcp_github_get_me', 'mcp_github_get_pull_request', 'mcp_github_get_pull_request_comments', 'mcp_github_get_pull_request_diff', 'mcp_github_push_files', 'mcp_github_create_pull_request', 'mcp_github_request_copilot_review', 'mcp_github_update_issue', 'mcp_github_update_pull_request']
---
ユーザからPull Requestを出すように指示があった場合には以下の手順で進めてください。
コミットメッセージやブランチ名などはユーザから指示がない場合にはあなたが推測して決めてください。
- `git branch`を実行し，現在のブランチ情報を取得する
- 現在のブランチがmainもしくはmasterでない場合には`git checkout`コマンドを使い，あたらしいブランチを作成する。ブランチメッセージは以下の形式とし，英語にする。
  - feature/開発機能名
  - hotfix/バグ修正内容
  - refactor/リファクタリング内容
- `git add .`を実行し，変更をステージする
- `git commit -m <コミットメッセージ>`を実行し，変更をコミットする。ただし，コミットメッセージは以下の形式とする。
  - feat: (feature)
  - fix: (bug fix)
  - docs: (documentation)
  - style: (formatting, missing semi colons, …)
  - refactor: (refactoring)
  - test: (when adding missing tests)
  - chore: (maintain)
- git push -u origin <作成したブランチ名>を実行し変更をリモートリポジトリに更新します。mainやmasterに直接pushしてはいけません。

```
:::note
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/690b8066-8571-4e9f-9334-40318df263e1.png)
↑なんのツールも登録されていない。
:::

</details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/f26376c5-3386-486f-b697-825564bf3404.png)

プロンプトが悪いのかブランチ名の命名規則が守られていませんがとりあえず動いた。

:::note info
もしかして`tools`を見てないのでは?と思い，空にしたら動きませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/91bcee26-ba5f-4096-8c86-70512e165390.png)
↑指示を出すだけでなにもやってくれない。
:::

---

## 動作を安定させるためにプロンプトをチューニングする

:::note warn
うまく動いたり動かなかったりするのでいろいろ試行錯誤中。
:::

最新は，[GitHub](https://github.com/RyosukeDTomita/vs-code-custom-chat/blob/main/.github/chatmodes/github-push.chatmode.md)を参照されたし。

### 工夫した点

- 方針に対して認識齟齬が少なくなるようにShell Script形式で具体例を示した。
- ある程度AI Agentに裁量をもたせた。
    - 足りない情報とかを補ってくれるので)やりやすいようにやってくれと記述
- [commitメッセージ](https://gist.github.com/stephenparish/9941e89d80e2bc58a153#allowed-type)はこれをベースに作った。
- ローカルブランチは手動で切るようにした。
    - ブランチをGitHub MCP Server経由で切ってもらうとリモートにしかブランチを作ってくれないので後々めんどくさい
    - mainとmasterブランチの場合はブランチ名の提案だけ行って処理を中断するように

```.github/chatmodes/github-push.chatmode.md
---
description: 'Pull Requestを作成するためのモード'
tools: ['run_in_terminal', 'create_file', 'insert_edit_into_file', 'replace_string_in_file', 'mcp_github_create_branch', 'mcp_github_get_commit', 'mcp_github_get_issue', 'mcp_github_get_issue_comments', 'mcp_github_get_me', 'mcp_github_get_pull_request', 'mcp_github_get_pull_request_comments', 'mcp_github_get_pull_request_diff', 'mcp_github_push_files', 'mcp_github_create_pull_request', 'mcp_github_request_copilot_review', 'mcp_github_update_issue', 'mcp_github_update_pull_request']
---
ユーザからPull Requestを出すように指示があった場合には以下の手順で進めてください。

<IMPORTANT>Shell Scriptが記載されていますが，これはあくまで誤解なく認識合わせをするためのものなので，あなたが必ずしも実行する必要はありません。また，Shell Scriptに含まれる「TO LLM:」というキーワードはあなたへのメッセージです。ユーザに確認を求めずにあなた自信が判断してください。</IMPORTANT>

1. 現在のブランチ名を取得してください。
  ```bash
  current_branch=$(git rev-parse --abbrev-ref HEAD)
  if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
  ```
2. <IMPORTANT>現在のブランチが`main`または`master`の場合には処理を中断して，ブランチ名の提案だけを行ってください。3番移行の処理は実行してはいけません。</IMPORTANT>
  ```bash
  if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
    git diff
    echo "TO LLM: 今回の変更内容をもとにbranch_prefixを選択してください:"
    echo "1) feature/"
    echo "2) hotfix/"
    echo "3) docs/"
    read -rp "TO LLM: 番号を入力してください (1-3): " branch_prefix_num
    case "$branch_prefix_num" in
      1) new_branch_prefix="feature/$(date +%Y%m%d%H%M%S)";;
      2) new_branch_prefix="hotfix/$(date +%Y%m%d%H%M%S)";;
      3) new_branch_prefix="docs/$(date +%Y%m%d%H%M%S)";;
      *) echo "無効な入力です"; exit 1;;
    esac
    read -rp "TO LLM: 新しいブランチ名を決定するために，変更内容を簡潔に文章にしてください。ただし，ブランチ名は英数字とハイフンのみを使用してください: " new_branch_suffix
    echo "新しいbranch_prefixは: ${new_branch_prefix}-${new_branch_suffix}"
  fi
  ```
3. リポジトリトップに戻り，変更をステージングします。
  ```bash
  cd "$(git rev-parse --show-toplevel)"
  git add .
  ```
4. 変更内容をもとに，コミットタイプを選択し、コミットメッセージを入力します。
  ```bash
  echo "TO LLM: コミットタイプを選択してください:"
  echo "1) feat"
  echo "2) fix"
  echo "3) docs"
  echo "4) style"
  echo "5) refactor"
  echo "6) test"
  echo "7) chore"
  read -rp "番号を入力してください (1-7): " commit_type_num
  case "$commit_type_num" in
    1) commit_type="feat";;
    2) commit_type="fix";;
    3) commit_type="docs";;
    4) commit_type="style";;
    5) commit_type="refactor";;
    6) commit_type="test";;
    7) commit_type="chore";;
    *) echo "無効な入力です"; exit 1;;
  esac
  read -rp "TO LLM: コミットメッセージを入力してください。（例: add login form)" commit_msg
  ```
5. コミットを作成します。
  ```bash
  git commit -m "${commit_type}: ${commit_msg}"
  ```
6. 新しいブランチをリモートにプッシュします。
  ```bash
  git push -u origin "$new_branch"
  ```

7. GitHubのMCPサーバを使用して，PRを作成してください。PRは.github/pull_request_template.mdにしたがって作成してください。

---

とりあえず，mainブランチで実行してprが出されないことを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718390/378a70a0-369b-4686-98a9-a27495c8ba69.png)

だが，prを出して!とかだとローカルのリポジトリ操作をすっ飛ばしてしまうことが結構ある。
正直まだ使い物にならない。`tools`の設定がうまく機能していないので，gitのmcpサーバとかいれてみたがうーんという感じ。