Build This Now
Build This Now
キーボードショートカットステータスラインガイド
フックガイドClaude Code クロスプラットフォームフックClaude Code セットアップフックストップフック自己検証する Claude Code エージェントClaude Code セッションフックClaude Code コンテキストバックアップフックスキルアクティベーションフックClaude Code パーミッションフックClaude CodeのMCPツールフックCommands to Skills
Skills, Subagents, HooksSubagent Sweet SpotCLAUDE.md Best PracticesFix Context Limit
speedy_devvkoen_salo
Blog/Toolkit/Hooks/Cross-Platform Hooks

Claude Code クロスプラットフォームフック

Claude Codeのクロスプラットフォームフック: .cmd・.sh・.ps1のラッパーを捨て、nodeを直接呼び出すことで、1つの.mjsファイルがmacOS・Linux・Windowsで動く方法。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →
speedy_devvWritten by speedy_devvPublished Jan 16, 2026Toolkit hubHooks index

問題: cmd /c や PowerShell 経由で Windows から配布したフックは、Linux チームメンバーがリポジトリを開いた瞬間にエラーになる。多くの人が行き着く回避策は見苦しい。フックごとに3つのシムスクリプトを用意する方法だ。Windowsには .cmd、Linuxには .sh、PowerShell には .ps1。3つとも全く同じことをする。つまり、本当に重要な .mjs ファイルを呼び出すだけだ。

素早い解決策: ラッパーを捨てる。フック設定を Node.js に直接向ける:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/formatter.mjs"
          }
        ]
      }
    ]
  }
}

変更なしで Windows、Linux、macOS で動く。node は常に $PATH に存在する。Claude Code が Node.js をハードな要件としているからだ。

OSが変わるとフックが壊れる理由

自分しか設定を触らない場合、この問題には遭遇しない。問題が生じるのは .claude/settings.json が共有されたとき、リポジトリが公開されたとき、あるいは Windows のデスクトップと macOS のノートパソコンを行き来するようになったときだ。コマンド内に bash や powershell が現れた瞬間、チームの半分が実行できなくなる。

多くのチュートリアルがプラットフォーム固有の書き方をしている:

// Windows-only
"command": "cmd /c \".claude\\hooks\\formatter.cmd\""
 
// Linux-only
"command": "bash .claude/hooks/formatter.sh"
 
// PowerShell-only
"command": "powershell -NoProfile -File .claude/hooks/statusline.ps1"

これらのラッパーはどれも node 呼び出しの周りに2行のボイラープレートを追加しているだけだ。3つのファイル、3つのプラットフォーム、すべてで同じ仕事をしている。OSについて知っているレイヤーがシムだけなら、シムを削除できる。

settings.json のユニバーサルパターン

settings.json 内のフックは共通の形状を持つ:

{
  "statusLine": {
    "type": "command",
    "command": "node .claude/hooks/statusline-monitor.mjs"
  },
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/skill-activation.mjs"
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/backup.mjs",
            "async": true
          }
        ]
      }
    ]
  }
}

cmd /c なし。bash なし。powershell なし。ただ node だけ。すべてのフック型が同じ形状を取るため、PostToolUse、SessionStart/SessionEnd、Stop、12すべてのライフサイクルイベントが同じように設定できる。

クロスプラットフォームフックロジックの3つのルール

各 .mjs ファイルの中で、3つの習慣がロジックをどのOSでも移植可能に保つ。

プラットフォーム変数の代わりに os.homedir() を使う

import { homedir } from "os";
import { join } from "path";
 
// Cross-platform: resolves to C:\Users\you or /home/you
const settingsPath = join(homedir(), ".claude", "settings.json");

$HOME、$env:USERPROFILE、%USERPROFILE% をソースコードに書かない。ヘルパーに適切なものを選ばせる。

一時ファイルパスには os.tmpdir() を使う

import { tmpdir } from "os";
import { join } from "path";
 
// Cross-platform: resolves to C:\Users\you\AppData\Local\Temp or /tmp
const cacheFile = join(tmpdir(), "my-hook-cache.json");

/tmp や $env:TEMP を手書きしない。

すべてのファイルパス構築に path.join() を使う

import { join } from "path";
 
// Cross-platform path construction
const logFile = join(".claude", "hooks", "logs", "hook.log");

/ や \\ でパスを手動で連結するのをやめる。Node.js はフックが実行されるOSに応じた適切なセパレータをすでに知っている。

両プラットフォームをカバーするパーミッション

settings.json の permissions ブロックには Windows の名前と Unix の名前を並べて記述する:

{
  "permissions": {
    "allow": [
      "Bash(where:*)",
      "Bash(which:*)",
      "Bash(tasklist:*)",
      "Bash(ps:*)",
      "Bash(taskkill:*)",
      "Bash(kill:*)",
      "Bash(findstr:*)",
      "Bash(node:*)"
    ]
  }
}

現在のマシンにインストールされていないコマンドは静かに無視される。両方を記述してもコストはかからないし、フックは権限ダイアログを発生させることなく実際に存在するコマンドを選んで実行する。この側面のより詳細な自動化については、パーミッションフックガイドを参照してほしい。

完全な例: クロスプラットフォームファイルロガー

1つのフックをそのまま使える形で示す。仕事はファイルロガーだ。Claude が行った Write または Edit をすべてログに追記する:

#!/usr/bin/env node
import { readFileSync, appendFileSync, mkdirSync } from "fs";
import { join } from "path";
 
const logDir = join(".claude", "hooks", "logs");
mkdirSync(logDir, { recursive: true });
 
try {
  const input = JSON.parse(readFileSync(0, "utf-8"));
  const toolName = input.tool_name;
  const filePath = input.tool_input?.file_path || "unknown";
  const timestamp = new Date().toISOString();
 
  appendFileSync(
    join(logDir, "file-changes.log"),
    `${timestamp} | ${toolName} | ${filePath}\n`,
  );
} catch {
  // Silent fail -- don't block Claude
}
 
process.exit(0);

settings.json に登録する:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/file-logger.mjs"
          }
        ]
      }
    ]
  }
}

Windows 11、Arch Linux、macOS Sequoia で同じ動作をする。ラッパーはゼロだ。

1つのOSで壊れるときのデバッグ

あるマシンでは動くがほかのマシンで失敗するフックがある?このリストを上から順に確認してほしい:

  1. ハードコードされたパスセパレータ。 すべての .mjs ファイルで、パス内に現れる / や \\ を検索する。それらを path.join() に渡す。
  2. 環境変数の参照。 process.env.HOME、process.env.USERPROFILE、process.env.TEMP を探し、それぞれを os.homedir() または os.tmpdir() に置き換える。
  3. settings.json 内のシェル固有のコマンド。 bash、cmd、powershell、sh に言及する command エントリはそのOS以外ではすべて壊れる。node に向け直す。

手動でフックを発火させると失敗を隠せない:

echo '{"tool_name":"Write","tool_input":{"file_path":"test.js"}}' | node .claude/hooks/your-hook.mjs
echo $?  # Should output 0

あるOSでは 0 が返り、ほかでは違う値が返る場合、問題は settings.json のフックエントリではなく .mjs ファイルのパス処理にある。

リリースチェックリスト

チームへの展開または公開リリース前にこのリストを確認してほしい:

  • settings.json のすべての command が cmd、powershell、bash ではなく node を指している
  • ホームディレクトリは $HOME や %USERPROFILE% ではなく os.homedir() から取得している
  • 一時パスは /tmp や $env:TEMP ではなく os.tmpdir() から取得している
  • パスは手打ちのセパレータではなく path.join() で構築している
  • パーミッションに Windows と Unix の両方の同等コマンドが記述されている
  • statusLine のコマンドが powershell ではなく node を指している

1つのファイル。3つのプラットフォーム。メンテナンスなし。

Claude Code のフックは Windows で動くか?

動く。そのOSにしか存在しないシェルではなく node を通じて呼び出せば、Windows、Linux、macOS で同じように動作する。Node.js はすべてのプラットフォームで Claude Code のハードな要件なので、node は常に $PATH にある。settings.json に node .claude/hooks/your-hook.mjs を記述すれば、3つすべてで同一の動作が得られる。

フックに Node.js の代わりに Python を使えるか?

Python でも動く。ただし、チームメンバー全員がすでにインタープリターをマシンに持っている必要がある。command フィールドでは python ではなく python3 を使う。一部の Linux ディストリビューションには python というコマンドが存在しないからだ。Node.js の方が安全な選択だ。Claude Code はすべてのプラットフォームで Node.js を保証しているが、Python は保証していない。

プラットフォームをまたいだ改行コードの扱いは?

ほぼ何もしなくてよい。readFileSync と writeFileSync はすでに改行を正規化している。すべてのフックは stdin から JSON を読み込み、JSONパーサーは改行が CRLF か LF かを気にしない。例外は自分でシェルスクリプトを出力するフックだ。そのパスでは \n を書き、残りは Git の autocrlf 設定に任せる。

Continue in Hooks

  • Slash Commands Are Now Skills: Migrating Commands to Skills
    Claude Code slash commands and skills now do the same thing. Here is how to migrate .claude/commands to .claude/skills and why it pays off.
  • Claude Code セットアップフック
    スクリプト、エージェント、ドキュメントをClaude Codeのセットアップフックに組み合わせる方法。1つのコマンドで決定論的スクリプトを実行し、診断エージェントに出力を渡し、自動更新されるドキュメントを記録する。
  • Claude Code コンテキストバックアップフック
    StatusLineを活用したClaude Codeのコンテキストバックアップフック。10Kトークンごとに構造化されたスナップショットを書き込み、自動圧縮によってエラー文字列・関数シグネチャ・判断内容が失われるのを防ぐ。
  • フックガイド
    Claude Code フックの基礎から実践まで: 終了コード、JSON出力、非同期コマンド、HTTPエンドポイント、PreToolUseとPostToolUseのマッチャー、本番環境パターン。
  • Claude CodeのMCPツールフック
    type: mcp_toolを使ってClaude CodeのフックからMCPサーバーのツールを直接呼び出す方法。スキーマ、変数展開の構文、ユースケース、本番パターンまで解説します。
  • Claude Code パーミッションフック
    3階層の Claude Code パーミッションフックをインストールする: 安全な呼び出しは即時許可、危険な呼び出しは即時拒否、グレーゾーンは LLM チェック。スキップフラグ不要。

More from Toolkit

  • CLAUDE.md, Skills, Subagents, Hooks: When to Use Which
    Claude Code skills vs subagents vs hooks vs CLAUDE.md: a plain mental model for picking the right primitive, with token costs and examples.
  • Claude Code Subagents: The 3 to 5 Agent Sweet Spot
    Claude code subagents work best at 3-5 concurrent agents. Here is why that ceiling exists, how to set them up, and what to use past it.
  • CLAUDE.md Best Practices: The File That Makes Claude Code Reliable
    CLAUDE.md best practices: keep it under 200 lines, write it by hand, and use hooks when you need real enforcement, not advice.
  • How to Fix Claude Code Running Out of Context
    Claude Code running out of context is a session design problem. Fix it with /compact, lean CLAUDE.md, skills, and subagents, not a bigger window.

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →

フックガイド

Claude Code フックの基礎から実践まで: 終了コード、JSON出力、非同期コマンド、HTTPエンドポイント、PreToolUseとPostToolUseのマッチャー、本番環境パターン。

Claude Code セットアップフック

スクリプト、エージェント、ドキュメントをClaude Codeのセットアップフックに組み合わせる方法。1つのコマンドで決定論的スクリプトを実行し、診断エージェントに出力を渡し、自動更新されるドキュメントを記録する。

On this page

OSが変わるとフックが壊れる理由
settings.json のユニバーサルパターン
クロスプラットフォームフックロジックの3つのルール
プラットフォーム変数の代わりに os.homedir() を使う
一時ファイルパスには os.tmpdir() を使う
すべてのファイルパス構築に path.join() を使う
両プラットフォームをカバーするパーミッション
完全な例: クロスプラットフォームファイルロガー
1つのOSで壊れるときのデバッグ
リリースチェックリスト
Claude Code のフックは Windows で動くか?
フックに Node.js の代わりに Python を使えるか?
プラットフォームをまたいだ改行コードの扱いは?

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

企業向けに構築している実績を見る →