Build This Now
Build This Now
Atalhos de TecladoGuia da Status Line
Guia de HooksHooks Multiplataforma para o Claude CodeHooks de Setup do Claude CodeStop HooksAgentes Claude Code Auto-ValidantesHooks de Ciclo de Vida de Sessão do Claude CodeHooks de Backup de Contexto para o Claude CodeHook de Ativação de SkillsHook de Permissões do Claude Code
speedy_devvkoen_salo
Blog/Toolkit/Hooks/Cross-Platform Hooks for Claude Code

Hooks Multiplataforma para o Claude Code

Hooks do Claude Code multiplataforma: elimina wrappers .cmd, .sh e .ps1 e invoca node diretamente para que um único ficheiro .mjs corra em macOS, Linux e Windows por toda a equipa.

Pare de configurar. Comece a construir.

Templates SaaS com orquestração de IA.

Published Jan 16, 2026Toolkit hubHooks index

Problema: Um hook que enviaste do Windows via cmd /c ou PowerShell fica vermelho no momento em que um colega Linux abre o repositório. A solução que a maioria das pessoas usa é feia. Três scripts shim por hook: um .cmd para Windows, um .sh para Linux, um .ps1 para PowerShell. Os três fazem exatamente a mesma coisa, que é chamar o ficheiro .mjs que realmente importa.

Solução Rápida: Deita os wrappers fora. Aponta a configuração do hook diretamente para o Node.js:

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

Corre em Windows, Linux e macOS sem alterações. node está sempre no $PATH porque o Claude Code lista o Node.js como requisito obrigatório.

Por Que os Hooks Partem Quando o OS Muda

Se mais ninguém tocar no teu setup, nada disto te afeta. O problema começa no momento em que .claude/settings.json é partilhado, o repositório se torna público, ou começas a alternar entre um PC Windows e um portátil macOS. Logo que bash ou powershell apareça dentro de um comando, metade da equipa não consegue executá-lo.

A maioria dos tutoriais vai logo para plataformas específicas de qualquer forma:

// 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"

Cada um desses wrappers são duas linhas de boilerplate à volta de uma chamada node. Três ficheiros, três plataformas, mesmo trabalho em todos. Se a única camada que sabe sobre o OS é o shim, podes apagar o shim.

O Padrão Universal no settings.json

Os hooks dentro de settings.json partilham uma forma única:

{
  "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
          }
        ]
      }
    ]
  }
}

Sem cmd /c. Sem bash. Sem powershell. Apenas node. Cada tipo de hook tem a mesma forma, por isso PostToolUse, SessionStart/SessionEnd, Stop, e todos os 12 eventos do ciclo de vida são configurados de forma idêntica.

Três Regras para Lógica de Hook Multiplataforma

Dentro de cada ficheiro .mjs, três hábitos mantêm a lógica portável independentemente do OS que a corra.

Usa os.homedir() em Vez de Variáveis de Plataforma

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");

Mantém $HOME, $env:USERPROFILE, e %USERPROFILE% fora do código. Deixa o helper escolher o certo.

Usa os.tmpdir() para Caminhos de Ficheiros Temporários

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");

Não uses /tmp ou $env:TEMP à mão.

Usa path.join() para Toda a Construção de Caminhos de Ficheiro

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

Para de juntar caminhos com / ou \\ à mão. O Node.js já sabe o separador certo para qualquer OS onde o hook corra.

Permissões que Cobrem Ambas as Plataformas

O bloco permissions no settings.json deve ter o nome Windows e o nome Unix lado a lado:

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

Seja qual for o comando não instalado na máquina atual, fica em silêncio. Listar ambos não tem custo, e o teu hook escolhe o que realmente existe sem acionar um diálogo de permissão. Para automação mais profunda neste lado, consulta o guia de Permission Hook.

Exemplo Completo: Logger de Ficheiros Multiplataforma

Um hook completo, portável tal como está. O trabalho é um logger de ficheiros. Qualquer escrita ou edição que o Claude faça é adicionada a um log:

#!/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);

Regista-o no teu settings.json:

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

Mesmo comportamento em Windows 11, Arch Linux e macOS Sequoia. Zero wrappers.

Depuração Quando um OS Parte

Tens um hook que corre numa máquina e falha na seguinte? Percorre esta lista de cima para baixo:

  1. Separadores de caminho hardcoded. Pesquisa em todos os ficheiros .mjs por / ou \\ a aparecer dentro de um caminho. Passa esses casos para path.join().
  2. Referências a variáveis de ambiente. Procura process.env.HOME, process.env.USERPROFILE, ou process.env.TEMP e substitui cada um por os.homedir() ou os.tmpdir().
  3. Comandos específicos de shell no settings.json. Qualquer entrada command que mencione bash, cmd, powershell, ou sh parte em todo o lado exceto no seu OS de origem. Aponta para node.

Dispara o hook manualmente para que a falha não se esconda:

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

Um 0 num OS e outra coisa no seguinte aponta-te para o tratamento de caminhos no ficheiro .mjs, nunca para a entrada de hook no settings.

Checklist de Lançamento

Percorre esta lista antes de um rollout de equipa ou lançamento público:

  • Cada command no settings.json aponta para node, não cmd, powershell, ou bash
  • Os diretórios home vêm de os.homedir(), nunca de $HOME ou %USERPROFILE%
  • Os caminhos temporários vêm de os.tmpdir(), nunca de /tmp ou $env:TEMP
  • Os caminhos são construídos com path.join(), não com separadores escritos à mão
  • As permissões listam tanto os equivalentes Windows como Unix
  • O comando statusLine resolve para node, não para powershell

Um ficheiro. Três plataformas. Zero manutenção.

Os hooks do Claude Code funcionam no Windows?

Sim. Chama-os através de node em vez de uma shell que só existe num OS, e correm igual em Windows, Linux e macOS. Node.js é um requisito obrigatório do Claude Code em todas as plataformas, por isso node está sempre no $PATH. Coloca node .claude/hooks/your-hook.mjs no settings.json e tens comportamento idêntico nas três.

Posso usar Python em vez de Node.js para hooks?

Python também funciona, desde que todos os colegas já tenham um interpretador na máquina. No campo command, usa python3 em vez de python, porque certas distribuições Linux nunca incluem um python simples. Node.js continua a ser a escolha mais segura: o Claude Code garante-o em todas as plataformas; Python não.

Como lidar com os finais de linha entre plataformas?

Na maior parte não precisas. readFileSync e writeFileSync já normalizam os finais. Cada hook lê JSON do stdin, e o parser JSON não se importa se as newlines são CRLF ou LF. A exceção é qualquer hook que emita o seu próprio script de shell. Para esse caso, escreve \n e deixa o resto para a configuração autocrlf do Git.

Continue in Hooks

  • Hooks de Setup do Claude Code
    Combina scripts, agentes e documentação em hooks de setup do Claude Code. Um comando corre um script determinístico, passa o output para um agente de diagnóstico, e regista documentação viva.
  • Hooks de Backup de Contexto para o Claude Code
    Um hook de backup de contexto do Claude Code baseado em StatusLine. Escreve snapshots estruturados a cada 10K tokens para que a compactação automática nunca apague erros, assinaturas nem decisões.
  • Guia de Hooks
    Hooks do Claude Code do princípio ao fim: exit codes, output JSON, comandos assíncronos, endpoints HTTP, matchers PreToolUse e PostToolUse, padrões para produção.
  • Hook de Permissões do Claude Code
    Instala um hook de permissões em três camadas para o Claude Code: aprovação instantânea para chamadas seguras, recusa instantânea para as perigosas, e verificação LLM para a zona cinzenta. Sem flag de skip.
  • Agentes Claude Code Auto-Validantes
    Agentes Claude Code auto-validantes: liga hooks PostToolUse de lint, hooks Stop e sub-agentes revisores em modo só-leitura às definições dos agentes para que output de má qualidade nunca seja entregue.
  • Hooks de Ciclo de Vida de Sessão do Claude Code
    Quatro hooks de ciclo de vida de sessão do Claude Code: executa init a pedido, injeta contexto do projeto no SessionStart, faz backup de transcripts e regista limpeza no exit do SessionEnd.

More from Toolkit

  • Atalhos de Teclado
    Configure o keybindings.json do Claude Code: 17 contextos, sintaxe de teclas, sequências de acordes, combinações de modificadores e como desvincular qualquer atalho padrão instantaneamente.
  • Guia da Status Line
    Configure uma status line no Claude Code para ver o nome do modelo, branch do git, custo da sessão e uso do contexto. Configuração via settings.json, input JSON, scripts em bash, Python e Node.js.
  • Otimização de SEO e GEO com IA
    Um resumo sobre Generative Engine Optimization: como fazer com que o teu conteúdo seja citado dentro das respostas do ChatGPT, Claude e Perplexity, em vez de apenas aparecer no Google.
  • Claude Code vs Cursor em 2026
    Uma comparação lado a lado entre Claude Code e Cursor em 2026: modelos de agente, janelas de contexto, planos de preço e como cada ferramenta se encaixa em diferentes fluxos de trabalho.

Pare de configurar. Comece a construir.

Templates SaaS com orquestração de IA.

On this page

Por Que os Hooks Partem Quando o OS Muda
O Padrão Universal no settings.json
Três Regras para Lógica de Hook Multiplataforma
Usa os.homedir() em Vez de Variáveis de Plataforma
Usa os.tmpdir() para Caminhos de Ficheiros Temporários
Usa path.join() para Toda a Construção de Caminhos de Ficheiro
Permissões que Cobrem Ambas as Plataformas
Exemplo Completo: Logger de Ficheiros Multiplataforma
Depuração Quando um OS Parte
Checklist de Lançamento
Os hooks do Claude Code funcionam no Windows?
Posso usar Python em vez de Node.js para hooks?
Como lidar com os finais de linha entre plataformas?

Pare de configurar. Comece a construir.

Templates SaaS com orquestração de IA.