0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Copilot CLIで指示待ち時にスマホ通知する

0
Last updated at Posted at 2026-03-22

はじめに

AIコーディングに眺めのタスクを投げるとき、ユーザ許可やタスク完了のタイミングでスマホに通知できるようにすると、PCをずっと見ている必要がなくなり便利です。

claude codeでは指示待ち時にスマホ通知するノウハウが公開されていますが、copilot-cliの情報はあまりないように思えたので、実現方法をまとめました。

参考: claude codeで指示待ち時にスマホ通知する方法

やりたいこと

copilot-cliでユーザの指示を待つタイミングでスマホに通知されるようにしたいです。
具体的には以下のタイミングで通知されるようにしたいです。

  • ツールの使用許可をユーザーに求めたとき
  • タスクを終了してユーザーの次の入力待ちになったとき

方法

claude code同様、copilot-cliにもhook機能がありますので、
特定のイベントが発生したときにスマホ通知を送るようにします。
claude codeの場合とやることはほとんど同じですが、イベントの種類が少し違うので、そこが解説のポイントです。

スマホはiphoneで試します。
通知の送り方はいくつかありますが、ntfyを使うのが手軽なのでntfyを使います。

copilot-cliにおけるユーザの指示待ち関連イベント

copilot-cliの場合は、以下のフックを設定すればよいです。

  • preToolUse
    • ツールの使用許可を含め、ユーザに質問する場合はask_userというツールが使われるため、このツールが使われた直後に通知を送ればよいです。
    • postToolUseはask_userに限らずすべてのツール利用で発生するイベントのため、コマンド側でツール名がask_userの場合のみ通知を送るようにする必要があります。
    • 試していませんが、ask_user自体がツールなので、postToolUseでツール名がask_userのときに通知を送る方法でも動く気はします。
  • agentStop
    • タスク完了やユーザの次の入力待ちに戻るタイミングで発生するイベントです。
    • ややこしい別のイベントとしてsessionEndもありますが、こちらはセッション全体の終了時に発生するイベントなので少し違います。

通知方法

通知の送り方はいくつかありますが、まずはntfyを使うのが手軽だと思います。
無料版だと1日あたりの通知回数に制限があるので、不足を感じたら別の方法を試すと良いと思います。

以下、ntfyを前提の説明となります。

ntfyをスマホアプリでインストールして、ntfyのトピックを決めます。
トピック名はランダムな文字列等を含めて、他者とかぶらないようにすることを推奨します。他者と被ると、知らない人の通知を受け取ったり、自分の通知が知らない人に届くことになります。

copilot-cliのhook設定

copilot-cliのhook設定は、リポジトリルートの.github/hooksにファイルを作成して行います。ユーザ単位で背設定したい場合は~/.copilot/hooksに指定してもよいです。

ここではリポジトリに設定する場合を説明します。
例えば以下のようなファイルを作成します。

~/.github/hooks/notifications.json
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      {
        "type": "command",
        "bash": "./notify.sh",
        "cwd": "scripts",
        "timeoutSec": 10
      }
    ],
    "agentStop": [
      {
        "type": "command",
        "bash": "./notify.sh",
        "cwd": "scripts",
        "timeoutSec": 10
      }
    ]
  }
}

設定内容は以下です。

  • 2種類のイベントpreToolUseagentStopに対してフックを設定
  • フックの内容は、bashコマンドを実行するタイプで、scriptsディレクトリにあるnotify.shを実行するように設定

フックで呼び出すスクリプトの内容

ntfyで通知を送るためのスクリプトの例は以下の通りです。
環境変数COPILOT_NTFY_TOPICにntfyのトピックを指定しておくと、そのトピックに通知が送られるようになります。COPILOT_NTFY_SERVERCOPILOT_NTFY_PRIORITYはデフォルト値から変えたい場合は指定します。hooksの場合は何もしなくても.bashrc等で指定した環境変数を読めていた気がしますが、もし読めない場合は、スクリプト内で直接指定したり、BASH_ENVを使う方法を試すと良いと思います。

今はpreToolUseとagentStop両方のイベントで同じスクリプトを呼び出すようにしていますが、イベントごとに別のスクリプトを用意しても良いと思います。

notify.sh
#!/usr/bin/env bash

set -u -o pipefail

log_debug() {
  echo "[notify_hook] $*" >&2
  if [ -n "${COPILOT_NTFY_DEBUG_LOG:-}" ]; then
    mkdir -p "$(dirname "$COPILOT_NTFY_DEBUG_LOG")"
    printf '[notify_hook] %s\n' "$*" >>"$COPILOT_NTFY_DEBUG_LOG"
  fi
}

topic="${COPILOT_NTFY_TOPIC:-}"
if [ -z "$topic" ]; then
  log_debug "skip reason=no_topic"
  exit 0
fi

if ! command -v jq >/dev/null 2>&1; then
  log_debug "skip reason=missing_jq"
  echo "jq が見つからないため ntfy.sh 通知をスキップします" >&2
  exit 0
fi

if ! command -v curl >/dev/null 2>&1; then
  log_debug "skip reason=missing_curl"
  echo "curl が見つからないため ntfy.sh 通知をスキップします" >&2
  exit 0
fi

input="$(cat)"
server="${COPILOT_NTFY_SERVER:-https://ntfy.sh}"
priority="${COPILOT_NTFY_PRIORITY:-default}"
configured_event_name="${COPILOT_HOOK_EVENT:-}"

if ! cwd="$(printf '%s' "$input" | jq -r '.cwd // ""')" ||
  ! formatted_timestamp="$(printf '%s' "$input" | jq -r 'if .timestamp == null then empty else ((.timestamp / 1000) + (9 * 60 * 60) | floor | strftime("%Y/%m/%d %H:%M:%S")) end')" ||
  ! tool_name="$(printf '%s' "$input" | jq -r '.toolName // .tool // empty')" ||
  ! tool_args="$(printf '%s' "$input" | jq -r '.toolArgs // empty')" ||
  ! stop_reason="$(printf '%s' "$input" | jq -r '.reason // .stopReason // empty')" ||
  ! fallback_tool_args="$(printf '%s' "$input" | jq -r '(.args // []) | join(" ")')"; then
  log_debug "skip reason=invalid_json"
  echo "hook 入力の JSON 解析に失敗したため通知をスキップします" >&2
  exit 0
fi

if [ -z "$tool_args" ]; then
  tool_args="$fallback_tool_args"
fi

event_name="$configured_event_name"
if [ -z "$event_name" ]; then
  if [ -n "$tool_name" ]; then
    event_name="preToolUse"
  else
    event_name="agentStop"
  fi
fi

build_pre_tool_use_message() {
  local tool_name="$1"
  local tool_args="$2"
  local question
  local choices_str

  if [ "$tool_name" != "ask_user" ]; then
    log_debug "skip reason=not_ask_user tool=$tool_name"
    return 1
  fi

  title="${COPILOT_NTFY_TITLE:-Copilot CLI: ユーザ確認待ち}"
  question="$(printf '%s' "$tool_args" | jq -r '.question // empty' 2>/dev/null || true)"
  choices_str="$(printf '%s' "$tool_args" | jq -r '(.choices // []) | join(", ")' 2>/dev/null || true)"
  message=""

  if [ -n "$question" ]; then
    message="question: $question"
  fi
  if [ -n "$choices_str" ]; then
    message="$message
choices: $choices_str"
  fi
  if [ -z "$message" ] && [ -n "$tool_args" ]; then
    message="args: $tool_args"
  fi
}

build_agent_stop_message() {
  local stop_reason="$1"

  title="${COPILOT_NTFY_TITLE:-Copilot CLI: エージェント停止}"
  message=""

  if [ -n "$stop_reason" ]; then
    message="reason: $stop_reason"
  fi
}

case "$event_name" in
  preToolUse)
    if ! build_pre_tool_use_message "$tool_name" "$tool_args"; then
      exit 0
    fi
    ;;
  agentStop)
    build_agent_stop_message "$stop_reason"
    ;;
  *)
    log_debug "skip reason=unsupported_event event=$event_name"
    exit 0
    ;;
esac

message="$message
cwd: $cwd"

if [ -n "$formatted_timestamp" ]; then
  message="$message
timestamp: $formatted_timestamp"
fi

log_debug "event=$event_name topic=$topic cwd=$cwd"

if ! curl \
  --silent \
  --show-error \
  --fail \
  -X POST \
  -H "Title: $title" \
  -H "Priority: $priority" \
  --data-binary "$message" \
  "${server%/}/$topic" >/dev/null; then
  log_debug "send=failed event=$event_name topic=$topic"
  echo "ntfy.sh への通知に失敗しました" >&2
else
  log_debug "send=ok event=$event_name topic=$topic"
fi

exit 0

動作確認

上記の設定とスクリプトを用意した状態でcopilot-cliを起動して、ユーザの指示待ちになるようなタスク(例えば「フックのテストをしたいのでユーザになにか許可を求めてください」)を投げてみてください。ユーザの指示待ちになるタイミングでスマホに通知が届けば成功です。

プレミアムリクエストがもったいないのでgpt-4.1で試すと良いと思います。

おわりに

copilot-cliで指示待ちのタイミングでスマホ通知する方法について解説しました。
いろいろ改良点はありそうですが、とりあえずスマホに通知は届くようになったので満足しています。
どなたかのご参考になれば。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?