1
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?

【完全無料】Ubuntu・Windows・Claude Codeの処理終了や許可待ちをApple Watchに通知する方法

1
Last updated at Posted at 2026-11-05

はじめに

株式会社Fieldの吉田です。
日頃は大学に通いながら、FieldでHPやLPのデザイン、AIでのシステム開発を行っています。

プログラムを実行している間、処理が終わっているか確認するために何度もターミナルを開くのが面倒だったので、処理が終わったらApple Watchに通知が届く仕組みを作りました。

今回は、以下の4つを実装します。

  • Ubuntu:15秒以上かかったコマンドが終了したら通知
  • Windows:15秒以上かかったコマンドが終了したら通知
  • Claude Code:許可待ちになって約15秒経過したら通知
  • Claude Code:15秒以上かかった内部処理や応答が完了したら通知

無料の通知サービス「ntfy」を利用するので、Apple Watch専用アプリを作る必要はありません。

動作環境

  • Ubuntu(zsh)
  • Windows(PowerShell 5.1)
  • iPhone / Apple Watch
  • Claude Code
  • ntfy

※ Ubuntuはzshを使用していることを前提に説明します。bashの場合は設定方法が異なります。

1. ntfyの準備

ntfyとは?

ntfyは、パソコンなどからスマートフォンに通知を送ることができる無料サービスです。

今回の仕組みは以下のようになります。

Ubuntu ──────────┐
                 │
Windows ─────────┼──→ ntfy ──→ iPhone ──→ Apple Watch
                 │
Claude Code ─────┘

iPhoneにntfyアプリをインストールすると、Apple Watchにも通知を転送できます。

① iPhoneにntfyをインストール

以下からntfyをインストールします。

ntfy(App Store)

アプリを開いたら、通知を許可してください。

② 通知用のトピック名を生成する

ntfyでは「トピック」という名前を使って通知先を指定します。

例えば、UbuntuとWindowsから別々に通知を送る場合、2つのトピックを使用します。

トピック名は、他人に推測されにくいランダムな文字列にします。

Ubuntuで生成

openssl rand -hex 16

Windows PowerShellで生成

[guid]::NewGuid().ToString("N")

それぞれ実行すると、32文字の英数字が出力されます。

例えば、次のような文字列です。

Ubuntu用:
a1b2c3d4e5f60718293a4b5c6d7e8f90

Windows用:
f9e8d7c6b5a403122130fedcba987654

※ 上記は説明用の例です。実際には自分で生成した文字列を使ってください。

生成した2つの文字列は、後で使うのでメモ帳などに控えておきます。

③ ntfyアプリにトピックを登録する

iPhoneのntfyアプリで、以下の操作をします。

  1. 「+」をタップする
  2. 「トピック」にUbuntuで生成した32文字を入力する
  3. 購読(Subscribe)する
  4. 同様にWindowsで生成した32文字も登録する

これで2つの通知先が登録されます。

④ 通知のテスト

Ubuntuで以下を実行します。

curl -d "Ubuntu TEST" \
  https://ntfy.sh/YOUR_UBUNTU_TOPIC

YOUR_UBUNTU_TOPICには、②でUbuntu用に生成した32文字を入力します。

例えば、

curl -d "Ubuntu TEST" \
  https://ntfy.sh/a1b2c3d4e5f60718293a4b5c6d7e8f90

という形です。

Windowsでは以下を実行します。

curl.exe -d "Windows TEST" `
  https://ntfy.sh/YOUR_WINDOWS_TOPIC

こちらもYOUR_WINDOWS_TOPICを、Windows用に生成した32文字に置き換えます。

iPhoneに通知が届けば準備完了です。

※ Apple Watchに通知されない場合は、iPhoneの「Watch」アプリ→「通知」でntfyの通知が許可されているか確認してください。iPhoneを使用中は通知がiPhone側に表示される場合があります。


2. Ubuntuで15秒以上のコマンド終了を通知

Ubuntuでは、zshのpreexecとprecmdという機能を使います。

  • preexec:コマンドを実行する直前に動く
  • precmd:コマンドが終了して次の入力待ちになる直前に動く

この2つを使って、コマンドの実行時間を測定します。

① 設定ファイルを開く

Ubuntuのターミナルで以下を実行します。

nano ~/.zshrc

.zshrcは、zshを起動するときに読み込まれる設定ファイルです。

② 以下のコードを末尾に追加

# ===== ntfy settings =====

# Replace with your Ubuntu topic
export NTFY_TOPIC="YOUR_UBUNTU_TOPIC"

# Notification threshold (seconds)
export NTFY_THRESHOLD=15

autoload -Uz add-zsh-hook

typeset -gi _watch_start=-1

_watch_preexec() {
    _watch_start=$SECONDS
}

_watch_precmd() {
    (( _watch_start >= 0 )) || return 0

    local elapsed=$(( SECONDS - _watch_start ))
    _watch_start=-1

    # Ignore commands shorter than 15 seconds
    (( elapsed >= NTFY_THRESHOLD )) || return 0

    curl -fsS --max-time 8 \
        -H "Title: Ubuntu Terminal" \
        --data-binary "Command finished (${elapsed} sec)" \
        "https://ntfy.sh/$NTFY_TOPIC" \
        >/dev/null 2>&1 &!
}

add-zsh-hook preexec _watch_preexec
add-zsh-hook precmd _watch_precmd

変更する場所は以下の1か所だけです。

export NTFY_TOPIC="YOUR_UBUNTU_TOPIC"

YOUR_UBUNTU_TOPICを、先ほどUbuntu用に生成した32文字に置き換えます。

NTFY_THRESHOLD=15は、15秒以上かかったコマンドだけ通知するという意味です。

③ 保存して設定を反映

nanoで編集している場合は、Ctrl + O→Enter→Ctrl + Xで保存して終了します。

その後、以下を実行します。

source ~/.zshrc

④ 動作確認

sleep 16

sleep 16は、何もせず16秒間待機するコマンドです。

16秒後にコマンドが終了し、Apple Watchへ通知が届けば成功です。

これ以降、15秒以上のコマンド終了時に自動で通知されます。


3. Windowsで15秒以上のコマンド終了を通知

Windowsでは、PowerShellのprompt関数とコマンド履歴を利用します。

PowerShellはコマンドの実行開始時刻と終了時刻を記録できるため、その差から実行時間を計算します。

① 設定ファイルを開く

PowerShellで以下を実行します。

New-Item -ItemType Directory -Path (Split-Path $PROFILE) -Force | Out-Null

if (!(Test-Path $PROFILE)) {
    New-Item -ItemType File -Path $PROFILE -Force | Out-Null
}

notepad $PROFILE

メモ帳が開きます。

すでに設定ファイルに内容がある場合は、念のためバックアップを取っておきましょう。

② 以下のコードを追加

# ===== ntfy settings =====

# Replace with your Windows topic
$global:WatchNtfyTopic = "YOUR_WINDOWS_TOPIC"

# Notification threshold (seconds)
$global:WatchNtfyThreshold = 15

$global:WatchLastHistoryId = (Get-History -Count 1).Id

function global:prompt {

    $entry = Get-History -Count 1

    if ($null -ne $entry -and
        $entry.Id -ne $global:WatchLastHistoryId) {

        $global:WatchLastHistoryId = $entry.Id

        $elapsed = (
            $entry.EndExecutionTime -
            $entry.StartExecutionTime
        ).TotalSeconds

        if ($elapsed -ge $global:WatchNtfyThreshold) {

            $message = 'Command finished: {0:N1} sec' -f $elapsed
            $body = [System.Text.Encoding]::UTF8.GetBytes($message)

            try {
                Invoke-RestMethod `
                    -Uri ("https://ntfy.sh/{0}" -f $global:WatchNtfyTopic) `
                    -Method Post `
                    -ContentType "text/plain; charset=utf-8" `
                    -Headers @{ Title = "Windows Terminal" } `
                    -Body $body `
                    -TimeoutSec 5 `
                    -ErrorAction Stop | Out-Null
            }
            catch {
                Write-Warning $_.Exception.Message
            }
        }
    }

    return "PS $($executionContext.SessionState.Path.CurrentLocation)> "
}

変更する場所は以下の1か所だけです。

$global:WatchNtfyTopic = "YOUR_WINDOWS_TOPIC"

YOUR_WINDOWS_TOPICを、Windows用に生成した32文字に置き換えます。

WatchNtfyThreshold = 15は通知するまでの実行時間です。

※ 既存のprompt関数がある場合、このコードはそれを置き換えます。すでにプロンプトをカスタマイズしている場合は調整が必要です。

③ 設定を反映する

メモ帳で保存した後、PowerShellを一度閉じて開き直します。

④ 動作確認

Start-Sleep -Seconds 16

16秒後に通知が届けば成功です。

なお、Windows PowerShell 5.1では日本語メッセージが文字化けする場合があるため、今回は英語のメッセージを使用しています。


4. Claude Codeの許可待ちも通知する

Claude Codeでは、ファイル編集やコマンド実行の際にユーザーの許可が必要になることがあります。

この許可待ちに気づかず、作業が止まってしまうことがあるため、Apple Watchへ通知するようにします。

今回はClaude CodeのHooks機能を使用します。

Hooksとは?

Claude Codeで特定のイベントが発生した際、自動的にプログラムを実行する機能です。

今回はNotification Hookのpermission_promptイベントを使用します。

通常、ターミナルで許可待ちが約6秒続いたときにイベントが発生するため、そこからさらに9秒待って通知を送ります。

Claude Codeが許可を要求
          ↓
約6秒後にNotification Hookが起動
          ↓
PowerShellスクリプトで9秒待機
          ↓
ntfyでApple Watchに通知

① 通知スクリプトを作成

Windows PowerShellで以下を実行します。

New-Item -ItemType Directory -Path "$HOME\.claude\hooks" -Force | Out-Null

notepad "$HOME\.claude\hooks\permission-notify.ps1"

メモ帳が開くので、以下を貼り付けます。

# Wait 9 seconds
Start-Sleep -Seconds 9

# Replace with your Windows topic
$topic = "YOUR_WINDOWS_TOPIC"

$message = "Claude Code is waiting for your approval."
$body = [System.Text.Encoding]::UTF8.GetBytes($message)

try {
    Invoke-RestMethod `
        -Uri ("https://ntfy.sh/{0}" -f $topic) `
        -Method Post `
        -ContentType "text/plain; charset=utf-8" `
        -Headers @{ Title = "Claude Code - Permission needed" } `
        -Body $body `
        -TimeoutSec 8 `
        -ErrorAction Stop | Out-Null
}
catch {
    Add-Content `
        -Path (Join-Path $env:TEMP "claude-ntfy-error.log") `
        -Value $_.Exception.Message
}

ここでも1か所変更します。

$topic = "YOUR_WINDOWS_TOPIC"

YOUR_WINDOWS_TOPICを、3章のWindowsターミナルで使用したものと同じ32文字に置き換えてください。

新しくトピックを生成する必要はありません。

② Claude CodeにHookを登録

次のファイルを開きます。

notepad "$HOME\.claude\settings.json"

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

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\permission-notify.ps1"
            ],
            "async": true
          }
        ]
      }
    ]
  }
}

変更する場所

C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\permission-notify.ps1

YOUR_USERNAMEはWindowsのユーザー名に変更してください。

自分のユーザー名はPowerShellで次のコマンドを実行すると確認できます。

$env:USERNAME

例えばhyoshと表示されれば、次のようになります。

C:\\Users\\hyosh\\.claude\\hooks\\permission-notify.ps1

※ settings.jsonにすでに設定がある場合は、ファイル全体を上書きせず、既存のhooksに追加してください。JSONでは同じ名前のキーを重複させないようにします。

③ 通知スクリプトの動作確認

PowerShellで以下を実行します。

powershell.exe -NoProfile -ExecutionPolicy Bypass `
    -File "$HOME\.claude\hooks\permission-notify.ps1"

約9秒後に以下の通知が届けば成功です。

Claude Code - Permission needed

Claude Code is waiting for your approval.

④ Claude Codeで実際にテスト

Claude Codeを再起動します。

claude

Claude Code内で以下を入力します。

/hooks

Notificationにpermission_promptが登録されているか確認します。

次に、Claude Codeで許可が必要な操作を実行させます。

許可画面が表示されたら、何も操作せず待機します。

約15秒後にApple Watchへ通知が届けば成功です!

※ この仕組みは厳密に「許可待ちが15秒継続している」と再判定するものではありません。待機中に許可しても、通知される場合があります。


5. Claude Codeの処理が15秒以上かかったときも通知する

ここからは追加実装です。

4章までの設定では、Claude Codeの「許可待ち」は通知できますが、Claude Codeが処理を終えたことは通知できません。

また、Windowsのコマンド終了通知だけでは、Claude Code内部の処理終了を検知できません。

例えばPowerShellで、

claude

と実行すると、PowerShellからはclaudeという1つのコマンドが動き続けているように見えます。

そのため、Claude Codeで何度処理が完了しても、PowerShell側の終了通知は発火せず、Claude Code自体を終了したときに初めて通知されます。

そこで、Claude Code内部の処理完了を直接検知するHookを追加します。

5.1 Claude Codeの処理終了を検知する仕組み

Claude Codeには、以下のHookがあります。

Hook 動作
UserPromptSubmit ユーザーが指示を送信したとき
Stop Claude Codeが応答を完了したとき
PreToolUse Claude Codeがツールを実行する直前
PostToolUse ツールが正常終了したとき
PostToolUseFailure ツールが失敗したとき

今回は2種類の時間を計測します。

① Claude Codeの応答全体の実行時間

ユーザーが指示を送信
      ↓
UserPromptSubmit:開始時刻を保存
      ↓
Claude Codeが処理
      ↓
Stop:終了時刻を取得
      ↓
15秒以上なら通知

② Claude Code内部のツール実行時間

PreToolUse:ツール実行開始
      ↓
PowerShellなどで処理を実行
      ↓
PostToolUse:ツール終了
      ↓
15秒以上なら通知

応答全体の完了だけでなく、内部で実行された長時間のツール処理も検知できます。

5.2 応答全体の終了通知スクリプトを作成

まず、Windows PowerShellで以下を実行します。

notepad "$HOME\.claude\hooks\turn-notify.ps1"

開いたファイルに以下を入力します。

param(
    [ValidateSet("Start", "Stop")]
    [string]$Mode
)

# Replace with your Windows topic
$topic = "YOUR_WINDOWS_TOPIC"
$threshold = 15

$stateDir = Join-Path $env:TEMP "claude-turn-timers"
$log = Join-Path $env:TEMP "claude-turn-notify.log"

try {
    # Read Claude Code's JSON as UTF-8
    $reader = [System.IO.StreamReader]::new(
        [Console]::OpenStandardInput(),
        [System.Text.Encoding]::UTF8
    )

    $data = $reader.ReadToEnd() | ConvertFrom-Json
    $id = [string]$data.session_id

    if ([string]::IsNullOrWhiteSpace($id)) {
        exit 0
    }

    New-Item -ItemType Directory -Path $stateDir -Force |
        Out-Null

    $safeId = $id -replace '[^a-zA-Z0-9_-]', '_'
    $stateFile = Join-Path $stateDir "$safeId.txt"

    $now = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()

    if ($Mode -eq "Start") {
        [System.IO.File]::WriteAllText(
            $stateFile, $now.ToString()
        )
        Add-Content $log "START $id"
    }

    if ($Mode -eq "Stop" -and (Test-Path $stateFile)) {
        $start = [long](
            [System.IO.File]::ReadAllText($stateFile).Trim()
        )

        Remove-Item $stateFile -Force

        $elapsed = ($now - $start) / 1000.0
        Add-Content $log ("STOP elapsed={0:N1}s" -f $elapsed)

        if ($elapsed -ge $threshold) {
            $message = "Claude Code finished in {0:N1} seconds" -f $elapsed
            $body = [System.Text.Encoding]::UTF8.GetBytes($message)

            Invoke-RestMethod `
                -Uri ("https://ntfy.sh/{0}" -f $topic) `
                -Method Post `
                -ContentType "text/plain; charset=utf-8" `
                -Headers @{ Title = "Claude Code - Task completed" } `
                -Body $body `
                -TimeoutSec 5 `
                -ErrorAction Stop | Out-Null

            Add-Content $log "NOTIFICATION SENT"
        }
    }
}
catch {
    Add-Content $log ("ERROR: " + $_.Exception.Message)
}

変更する場所

$topic = "YOUR_WINDOWS_TOPIC"

この部分を、Windows用に生成した32文字に置き換えます。

$threshold = 15は、15秒以上で通知する設定です。

5.3 ツール終了通知スクリプトを作成

続いて以下を実行します。

notepad "$HOME\.claude\hooks\tool-notify.ps1"

以下のコードを保存します。

param(
    [ValidateSet("Pre", "Post")]
    [string]$Mode
)

# Replace with your Windows topic
$topic = "YOUR_WINDOWS_TOPIC"
$threshold = 15

$log = Join-Path $env:TEMP "claude-tool-notify.log"
$stateDir = Join-Path $env:TEMP "claude-tool-timers"

try {
    # Read UTF-8 JSON correctly
    $reader = [System.IO.StreamReader]::new(
        [Console]::OpenStandardInput(),
        [System.Text.Encoding]::UTF8
    )

    $data = $reader.ReadToEnd() | ConvertFrom-Json

    $id = [string]$data.tool_use_id
    if ([string]::IsNullOrWhiteSpace($id)) {
        exit 0
    }

    New-Item -ItemType Directory -Path $stateDir -Force |
        Out-Null

    $key = "{0}_{1}" -f $data.session_id, $id
    $key = $key -replace '[^a-zA-Z0-9_-]', '_'
    $stateFile = Join-Path $stateDir "$key.txt"

    $now = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()

    if ($Mode -eq "Pre") {
        [System.IO.File]::WriteAllText(
            $stateFile, $now.ToString()
        )
        exit 0
    }

    $elapsed = $null

    if ($null -ne $data.duration_ms) {
        $elapsed = [double]$data.duration_ms / 1000.0
    }
    elseif (Test-Path $stateFile) {
        $start = [long](
            [System.IO.File]::ReadAllText($stateFile).Trim()
        )
        $elapsed = ($now - $start) / 1000.0
    }

    Remove-Item $stateFile -ErrorAction SilentlyContinue

    if ($null -eq $elapsed) {
        exit 0
    }

    $tool = [string]$data.tool_name

    Add-Content $log (
        "TOOL {0}: {1:N1}s" -f $tool, $elapsed
    )

    if ($elapsed -ge $threshold) {
        $message = "Claude Code: {0} finished in {1:N1} sec" -f $tool, $elapsed
        $body = [System.Text.Encoding]::UTF8.GetBytes($message)

        Invoke-RestMethod `
            -Uri ("https://ntfy.sh/{0}" -f $topic) `
            -Method Post `
            -ContentType "text/plain; charset=utf-8" `
            -Headers @{ Title = "Claude Code - Tool completed" } `
            -Body $body `
            -TimeoutSec 5 `
            -ErrorAction Stop | Out-Null

        Add-Content $log "NOTIFICATION SENT"
    }
}
catch {
    Add-Content $log ("ERROR: " + $_.Exception.Message)
}

こちらも以下の1か所だけ、Windows用の32文字に変更します。

$topic = "YOUR_WINDOWS_TOPIC"

これで、ツール実行時間が15秒以上の場合に通知されるようになります。

5.4 Claude CodeにHookを登録する

次に、作成した2つのスクリプトをClaude Codeに登録します。

Windows PowerShellで次を実行します。

notepad "$HOME\.claude\settings.json"

4章で登録したNotificationに加え、UserPromptSubmit、Stop、PreToolUse、PostToolUse、PostToolUseFailureを追加します。

例えば、Windowsのユーザー名がYOUR_USERNAMEの場合、hooksの部分は次のようになります。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\permission-notify.ps1"
            ],
            "async": true
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\turn-notify.ps1",
              "Start"
            ]
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\turn-notify.ps1",
              "Stop"
            ]
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\tool-notify.ps1",
              "Pre"
            ]
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\tool-notify.ps1",
              "Post"
            ],
            "async": true
          }
        ]
      }
    ],
    "PostToolUseFailure": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell.exe",
            "args": [
              "-NoProfile",
              "-ExecutionPolicy",
              "Bypass",
              "-File",
              "C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\tool-notify.ps1",
              "Post"
            ],
            "async": true
          }
        ]
      }
    ]
  }
}

変更する場所

すべてのYOUR_USERNAMEをWindowsのユーザー名に変更してください。

例えばユーザー名がhyoshなら、

C:\\Users\\hyosh\\.claude\\hooks\\turn-notify.ps1

のようになります。

※ これはhooksの設定例です。既存のsettings.jsonにほかの設定やHookがある場合は、ファイル全体を置き換えず、必要な項目を追加してください。編集前にバックアップを取ることをおすすめします。

5.5 動作確認

Claude Codeを再起動します。

claude

次に、Claude Codeへ以下のように指示します。

PowerShellで Start-Sleep -Seconds 20 を実行し、処理が終わったら結果を報告してください。

20秒以上かかったツールが終了すると、次のような通知が届きます。

Claude Code - Tool completed

Claude Code: PowerShell finished in 20.8 sec

さらにClaude Codeの応答全体が15秒以上かかった場合は、以下も届きます。

Claude Code - Task completed

Claude Code finished in 24.9 seconds

Claude Codeそのものを終了しなくても通知が届くことがポイントです。

実際に動いているかは、別のPowerShellで次のコマンドを実行して確認できます。

ツール終了ログ

Get-Content "$env:TEMP\claude-tool-notify.log" -Tail 10

応答完了ログ

Get-Content "$env:TEMP\claude-turn-notify.log" -Tail 10

私の環境では、以下のようなログが出力されました。

TOOL PowerShell: 20.8s
NOTIFICATION SENT
START ...
STOP elapsed=24.9s
NOTIFICATION SENT

NOTIFICATION SENTが表示されていれば、ntfyへの送信処理が成功しています。

なお、ツール終了と応答全体の完了が両方15秒以上の場合は、通知が2件届くことがあります。


6. よくあるエラーと対処法

通知が「????」になる

Windows PowerShell 5.1では、日本語の文字コードが原因で通知が文字化けする場合があります。

今回は通知メッセージを英語に統一して対処しています。

手動通知は届くのに、自動通知が届かない

Ubuntuでは、以下でトピックが設定されているか確認します。

echo "$NTFY_TOPIC"

何も表示されなければ.zshrcの設定が正しく読み込まれていません。

source ~/.zshrc

を実行して再確認します。

Windowsでは、以下でトピック名を確認します。

$global:WatchNtfyTopic

設定した32文字が表示されるか確認してください。

Claude Codeを終了したときにしか通知が届かない

これは、PowerShellがClaude Code全体を1つのコマンドとして扱っているためです。

Claude Codeを起動した状態で処理終了通知を受け取るには、5章のStopやPostToolUse Hookを利用します。

Claude Codeの日本語を含む処理でJSON解析エラーが発生する

今回の実装で特に苦労した部分です。

最初はClaude Codeから送られてくるJSONを、次のように読み込んでいました。

$data = [Console]::In.ReadToEnd() | ConvertFrom-Json

しかし、Windows PowerShell 5.1では、標準入力の文字コードがUTF-8として正しく解釈されず、日本語が文字化けする場合があります。

例えば、日本語のコマンドや応答がJSONに含まれていると、ConvertFrom-Jsonで解析エラーになりました。

そこで、次のように修正しました。

$reader = [System.IO.StreamReader]::new(
    [Console]::OpenStandardInput(),
    [System.Text.Encoding]::UTF8
)

$data = $reader.ReadToEnd() | ConvertFrom-Json

これにより、標準入力をUTF-8として明示的に読み取れます。

実際にこの修正を行ったことで、それまでエラーになっていたClaude Codeのツール終了通知が正常に送信されるようになりました。

バックグラウンド実行には注意

今回のUbuntu・Windowsのコマンド終了通知は、基本的に対話型ターミナルで実行したコマンドが対象です。

nohupや&などでバックグラウンド実行した処理は、実際の処理終了を検知する別の仕組みが必要になります。

また、SSH接続先で実行したコマンドを個別に監視したい場合は、接続先のシェルにも設定する必要があります。


おわりに

今回はntfyを利用して、Ubuntu・Windows・Claude CodeからApple Watchへ無料で通知する仕組みを作りました。

最終的には、以下の4つを実現できました。

監視対象 通知条件
Ubuntuターミナル コマンドが15秒以上で終了
Windows PowerShell コマンドが15秒以上で終了
Claude Codeの許可待ち 許可待ち開始から約15秒
Claude Codeの内部処理・応答 15秒以上で終了

一度設定してしまえば、長時間のプログラム実行やClaude Codeの許可待ち、処理終了などをApple Watchから確認できます。

特に、Claude Codeを起動したまま別の作業をしている場合に便利です。

無料で実現できるので、ぜひ試してみてください。

― Happy coding ―

参考資料

1
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
1
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?