Skip to content

Instantly share code, notes, and snippets.

@programadorEmerson
Created January 27, 2026 17:27
Show Gist options
  • Select an option

  • Save programadorEmerson/f058264c62922ace5fef12f1f9805b70 to your computer and use it in GitHub Desktop.

Select an option

Save programadorEmerson/f058264c62922ace5fef12f1f9805b70 to your computer and use it in GitHub Desktop.
Claude Code Hooks - Guia Prático de Implementação

Claude Code Hooks - Guia Prático de Implementação

Guia completo para implementar hooks de persistência de estado no Claude Code, garantindo recuperação automática após compactações de contexto.


Por que você precisa disso?

O Claude Code tem um limite de contexto. Quando você está no meio de uma tarefa complexa (implementando uma feature, debugando, refatorando), o contexto enche e o Claude compacta automaticamente - resumindo toda a conversa em poucas linhas.

O problema? Após a compactação, o Claude "esquece" o que estava fazendo. Você precisa explicar tudo de novo.

A solução? Hooks que salvam o estado antes da compactação e recuperam depois. O Claude continua exatamente de onde parou, sem você precisar fazer nada.

Resultado: Tarefas longas funcionam sem interrupção, mesmo com múltiplas compactações.


Sumário

  1. O Problema (Antes vs Depois)
  2. Exemplo Real de Sessão
  3. Estrutura de Arquivos
  4. Passo 1: Criar Diretórios
  5. Passo 2: Criar Hook PreCompact
  6. Passo 3: Criar Hook PostCompact
  7. Passo 4: Configurar Hooks Globais
  8. Passo 5: Configurar Hooks do Projeto (Opcional)
  9. Passo 6: Dar Permissões
  10. Passo 7: Testar
  11. Diferenças macOS vs Linux
  12. Integração com MCP Memory
  13. Troubleshooting
  14. Referência Rápida

1. O Problema (Antes vs Depois)

Sem Hooks (Frustrante)

Você: "Implemente o sistema de autenticação completo"

Claude: Vou implementar em 5 partes:
        1. ✅ AuthService criado
        2. ✅ AuthController criado
        3. ✅ JWT configurado
        4. 🔄 Implementando guards...

        [COMPACTAÇÃO AUTOMÁTICA - contexto cheio]

Claude: Olá! Como posso ajudar você hoje?

Você: 😤 "Você estava implementando autenticação! Faltam os guards!"

Claude: Desculpe, não tenho contexto sobre isso. Pode me explicar o que precisa?

Com Hooks (Mágico)

Você: "Implemente o sistema de autenticação completo"

Claude: Vou implementar em 5 partes:
        1. ✅ AuthService criado
        2. ✅ AuthController criado
        3. ✅ JWT configurado
        4. 🔄 Implementando guards...

        [COMPACTAÇÃO AUTOMÁTICA - contexto cheio]
        [Hook PreCompact] → Salva: "step:4, próximo: guards, arquivos: auth.service.ts..."
        [Hook PostCompact] → Recupera checkpoint + instrui Claude

Claude: 🔄 Sessão retomada após compactação.

        Continuando implementação de autenticação:
        - Etapas 1-3 completas
        - Próximo: Implementar guards (etapa 4)

        Criando JwtAuthGuard...

2. Exemplo Real de Sessão

Veja como aparece no terminal quando os hooks funcionam:

Momento da Compactação (PreCompact)

╭─────────────────────────────────────────────────────────────────╮
│ ⚠️  Context window full. Compacting conversation...             │
╰─────────────────────────────────────────────────────────────────╯

PreCompact hook executing...
✓ Work in progress detected
✓ Checkpoint saved: ~/.claude/checkpoints/session-abc123.json

Retorno da Compactação (PostCompact)

╭─────────────────────────────────────────────────────────────────╮
│ 🔄 SESSÃO RETOMADA APÓS COMPACTAÇÃO                             │
│                                                                 │
│ 🔴 CHECKPOINT DETECTADO! Havia trabalho em andamento.           │
│                                                                 │
│ ⚠️  AÇÃO OBRIGATÓRIA - Execute AGORA:                           │
│                                                                 │
│ 1. mcp__memory__search_nodes                                    │
│    query: "in-progress"                                         │
│                                                                 │
│ 2. Se encontrar entidade(s):                                    │
│    mcp__memory__open_nodes                                      │
│    names: [entidades encontradas]                               │
│                                                                 │
│ 📋 CONTEXTO DO CHECKPOINT:                                      │
│ execution:: issue-123 step:3 specialist auth implementation...  │
│                                                                 │
│ 4. CONTINUE de onde parou!                                      │
╰─────────────────────────────────────────────────────────────────╯

Logs Gerados

~/.claude/logs/pre-compact.log:

[2026-01-27T10:30:00-03:00] PreCompact triggered - trigger: auto, session: abc123
[2026-01-27T10:30:00-03:00] Work in progress detected!
[2026-01-27T10:30:00-03:00] Checkpoint saved: /Users/you/.claude/checkpoints/session-abc123.json

~/.claude/logs/post-compact.log:

[2026-01-27T10:30:05-03:00] SessionStart triggered - source: compact, session: def456
[2026-01-27T10:30:05-03:00] Compact resume detected, checking for checkpoint
[2026-01-27T10:30:05-03:00] Using recent checkpoint (age: 5s)
[2026-01-27T10:30:05-03:00] Recovery instructions sent WITH checkpoint context

Checkpoint Salvo

~/.claude/checkpoints/session-abc123.json:

{
  "session_id": "abc123",
  "trigger": "auto",
  "timestamp": "2026-01-27T10:30:00-03:00",
  "transcript_path": "/Users/you/.claude/projects/.../abc123.jsonl",
  "work_in_progress": true,
  "context_snapshot": "execution:: issue-123 step:3 auth-specialist status:in-progress file:src/auth/auth.service.ts next-step:criar-guards..."
}

3. Estrutura de Arquivos

Após a implementação, você terá:

~/.claude/                                    ← GLOBAL (todos os projetos)
├── settings.json                             ← Configuração dos hooks
├── checkpoints/                              ← Onde checkpoints são salvos
│   └── session-{id}.json
├── logs/                                     ← Logs para debug
│   ├── pre-compact.log
│   └── post-compact.log
└── hooks/
    ├── pre-compact.sh                        ← Hook que salva estado
    └── post-compact.sh                       ← Hook que recupera estado

/seu-projeto/.claude/                         ← LOCAL (opcional, por projeto)
├── settings.local.json                       ← Configuração local
└── hooks/
    ├── pre-compact.sh                        ← Hook customizado
    └── post-compact.sh

4. Passo 1: Criar Diretórios

macOS e Linux

mkdir -p ~/.claude/hooks
mkdir -p ~/.claude/checkpoints
mkdir -p ~/.claude/logs

5. Passo 2: Criar Hook PreCompact

Arquivo: ~/.claude/hooks/pre-compact.sh

Crie o arquivo e cole o conteúdo abaixo:

#!/bin/bash
# =============================================================================
# Hook: PreCompact - Salva estado antes da compactação
# =============================================================================
# Compatível com: macOS e Linux
# Dependência: jq (brew install jq / apt install jq)
# =============================================================================

set -e

# -----------------------------------------------------------------------------
# 1. LER INPUT DO CLAUDE CODE (recebido via stdin em formato JSON)
# -----------------------------------------------------------------------------
INPUT=$(cat)

SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty')
TRIGGER=$(echo "$INPUT" | jq -r '.trigger // "unknown"')

# -----------------------------------------------------------------------------
# 2. CONFIGURAR PATHS
# -----------------------------------------------------------------------------
CHECKPOINT_DIR="$HOME/.claude/checkpoints"
LOG_FILE="$HOME/.claude/logs/pre-compact.log"

mkdir -p "$CHECKPOINT_DIR"
mkdir -p "$(dirname "$LOG_FILE")"

# Log de execução
echo "[$(date -Iseconds)] PreCompact triggered - trigger: $TRIGGER, session: $SESSION_ID" >> "$LOG_FILE"

# -----------------------------------------------------------------------------
# 3. VERIFICAR SE EXISTE TRANSCRIPT
# -----------------------------------------------------------------------------
if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then
    echo "[$(date -Iseconds)] No transcript found at: $TRANSCRIPT_PATH" >> "$LOG_FILE"
    exit 0
fi

# -----------------------------------------------------------------------------
# 4. DETECTAR TRABALHO EM ANDAMENTO
# -----------------------------------------------------------------------------
# Padrões que indicam que Claude estava no meio de alguma tarefa
EXECUTION_PATTERNS="in-progress|status:in-progress|step:[0-9]+:|next-step:|Task.*subagent|execution::|specialist|implementation|validation-pending"

if grep -qiE "$EXECUTION_PATTERNS" "$TRANSCRIPT_PATH" 2>/dev/null; then
    echo "[$(date -Iseconds)] Work in progress detected!" >> "$LOG_FILE"

    # -------------------------------------------------------------------------
    # 5. EXTRAIR CONTEXTO RELEVANTE DO TRANSCRIPT
    # -------------------------------------------------------------------------
    # Pega as últimas 300 linhas, filtra as relevantes, sanitiza caracteres
    CONTEXT_RAW=$(tail -300 "$TRANSCRIPT_PATH" | \
        grep -iE "execution|specialist|agent|skill|step|fase|etapa|in-progress|status|Task|issue|#[0-9]+" | \
        tail -50 | \
        sed 's/["\]/ /g' | \
        tr '\n' ' ' | \
        cut -c1-1500)

    # -------------------------------------------------------------------------
    # 6. SALVAR CHECKPOINT (usando jq para garantir JSON válido)
    # -------------------------------------------------------------------------
    CHECKPOINT_FILE="$CHECKPOINT_DIR/session-$SESSION_ID.json"

    jq -n \
      --arg sid "$SESSION_ID" \
      --arg trigger "$TRIGGER" \
      --arg ts "$(date -Iseconds)" \
      --arg tp "$TRANSCRIPT_PATH" \
      --arg ctx "$CONTEXT_RAW" \
      '{
        session_id: $sid,
        trigger: $trigger,
        timestamp: $ts,
        transcript_path: $tp,
        work_in_progress: true,
        context_snapshot: $ctx
      }' > "$CHECKPOINT_FILE"

    echo "[$(date -Iseconds)] Checkpoint saved: $CHECKPOINT_FILE" >> "$LOG_FILE"

    # -------------------------------------------------------------------------
    # 7. RETORNAR MENSAGEM PARA CLAUDE (opcional)
    # -------------------------------------------------------------------------
    cat << 'EOF'
{
  "hookSpecificOutput": {
    "hookEventName": "PreCompact",
    "additionalContext": "⚠️ COMPACTAÇÃO EM ANDAMENTO\n\nUm checkpoint foi salvo automaticamente."
  }
}
EOF
else
    echo "[$(date -Iseconds)] No work in progress detected" >> "$LOG_FILE"
    # Remove checkpoint antigo se não há trabalho pendente
    rm -f "$CHECKPOINT_DIR/session-$SESSION_ID.json" 2>/dev/null
fi

exit 0

6. Passo 3: Criar Hook PostCompact

Arquivo: ~/.claude/hooks/post-compact.sh

Crie o arquivo e cole o conteúdo abaixo:

#!/bin/bash
# =============================================================================
# Hook: PostCompact (SessionStart:compact) - Recupera estado após compactação
# =============================================================================
# Compatível com: macOS e Linux
# Dependência: jq (brew install jq / apt install jq)
# =============================================================================

set -e

# -----------------------------------------------------------------------------
# 1. LER INPUT DO CLAUDE CODE
# -----------------------------------------------------------------------------
INPUT=$(cat)

SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
SOURCE=$(echo "$INPUT" | jq -r '.source // empty')

# -----------------------------------------------------------------------------
# 2. CONFIGURAR PATHS
# -----------------------------------------------------------------------------
CHECKPOINT_DIR="$HOME/.claude/checkpoints"
LOG_FILE="$HOME/.claude/logs/post-compact.log"

mkdir -p "$(dirname "$LOG_FILE")"

echo "[$(date -Iseconds)] SessionStart triggered - source: $SOURCE, session: $SESSION_ID" >> "$LOG_FILE"

# -----------------------------------------------------------------------------
# 3. VERIFICAR SE É RETORNO DE COMPACTAÇÃO
# -----------------------------------------------------------------------------
# Só executa se source=compact (não em sessões novas ou resumidas normalmente)
if [ "$SOURCE" != "compact" ]; then
    echo "[$(date -Iseconds)] Not a compact resume (source=$SOURCE), skipping" >> "$LOG_FILE"
    exit 0
fi

echo "[$(date -Iseconds)] Compact resume detected, checking for checkpoint" >> "$LOG_FILE"

# -----------------------------------------------------------------------------
# 4. BUSCAR CHECKPOINT
# -----------------------------------------------------------------------------
CHECKPOINT_FILE="$CHECKPOINT_DIR/session-$SESSION_ID.json"
CHECKPOINT_CONTEXT=""
CHECKPOINT_FOUND=false

# Tentar checkpoint da sessão atual
if [ -f "$CHECKPOINT_FILE" ]; then
    # Validar se o JSON é válido antes de processar
    if jq -e '.' "$CHECKPOINT_FILE" >/dev/null 2>&1; then
        CHECKPOINT_FOUND=true
        CHECKPOINT_CONTEXT=$(jq -r '.context_snapshot // empty' "$CHECKPOINT_FILE" 2>/dev/null | head -c 1000)
        echo "[$(date -Iseconds)] Checkpoint found for current session" >> "$LOG_FILE"
        rm -f "$CHECKPOINT_FILE" 2>/dev/null
    else
        echo "[$(date -Iseconds)] ERROR: Checkpoint JSON invalid, removing" >> "$LOG_FILE"
        rm -f "$CHECKPOINT_FILE" 2>/dev/null
    fi
fi

# Fallback: buscar checkpoint mais recente (session_id pode mudar)
if [ "$CHECKPOINT_FOUND" = false ]; then
    LATEST_CHECKPOINT=$(ls -t "$CHECKPOINT_DIR"/session-*.json 2>/dev/null | head -1)

    if [ -n "$LATEST_CHECKPOINT" ]; then
        if jq -e '.' "$LATEST_CHECKPOINT" >/dev/null 2>&1; then
            # Verificar idade do arquivo (máximo 10 minutos = 600 segundos)
            # Compatível com macOS (stat -f) e Linux (stat -c)
            if [[ "$OSTYPE" == "darwin"* ]]; then
                FILE_TIME=$(stat -f %m "$LATEST_CHECKPOINT" 2>/dev/null || echo 0)
            else
                FILE_TIME=$(stat -c %Y "$LATEST_CHECKPOINT" 2>/dev/null || echo 0)
            fi

            CURRENT_TIME=$(date +%s)
            CHECKPOINT_AGE=$((CURRENT_TIME - FILE_TIME))

            if [ "$CHECKPOINT_AGE" -lt 600 ]; then
                CHECKPOINT_FOUND=true
                CHECKPOINT_CONTEXT=$(jq -r '.context_snapshot // empty' "$LATEST_CHECKPOINT" 2>/dev/null | head -c 1000)
                echo "[$(date -Iseconds)] Using recent checkpoint (age: ${CHECKPOINT_AGE}s)" >> "$LOG_FILE"
                rm -f "$LATEST_CHECKPOINT" 2>/dev/null
            fi
        fi
    fi
fi

# -----------------------------------------------------------------------------
# 5. RETORNAR INSTRUÇÕES DE RECUPERAÇÃO
# -----------------------------------------------------------------------------
if [ "$CHECKPOINT_FOUND" = true ]; then
    cat << EOF
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "🔄 SESSÃO RETOMADA APÓS COMPACTAÇÃO\\n\\n🔴 CHECKPOINT DETECTADO! Havia trabalho em andamento.\\n\\n⚠️ AÇÃO OBRIGATÓRIA - Execute AGORA:\\n\\n1. mcp__memory__search_nodes\\n   query: \\"in-progress\\"\\n\\n2. Se encontrar entidade(s):\\n   mcp__memory__open_nodes\\n   names: [entidades encontradas]\\n\\n3. Leia observações:\\n   - step:N:* → Última etapa\\n   - next-step:* → Continuar daqui\\n   - user-demand:* → Demanda original\\n\\n📋 CONTEXTO DO CHECKPOINT:\\n${CHECKPOINT_CONTEXT}\\n\\n4. CONTINUE de onde parou!"
  }
}
EOF
    echo "[$(date -Iseconds)] Recovery instructions sent WITH checkpoint context" >> "$LOG_FILE"
else
    cat << 'EOF'
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "🔄 SESSÃO RETOMADA APÓS COMPACTAÇÃO\n\n⚠️ VERIFICAR TRABALHO PENDENTE:\n\n1. Execute IMEDIATAMENTE:\n   mcp__memory__search_nodes\n   query: \"in-progress\"\n\n2. Se encontrar entidade(s):\n   mcp__memory__open_nodes\n   names: [nome(s) da(s) entidade(s)]\n\n3. Leia observações e CONTINUE de onde parou\n\n4. Se NÃO encontrar nada:\n   - Sessão anterior foi concluída\n   - Aguarde nova demanda"
  }
}
EOF
    echo "[$(date -Iseconds)] Recovery instructions sent (no checkpoint found)" >> "$LOG_FILE"
fi

exit 0

7. Passo 4: Configurar Hooks Globais

Arquivo: ~/.claude/settings.json

Se o arquivo já existir, adicione a seção hooks. Se não existir, crie com o conteúdo:

{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/pre-compact.sh",
            "timeout": 30
          }
        ]
      },
      {
        "matcher": "manual",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/pre-compact.sh",
            "timeout": 30
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/post-compact.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Explicação dos Campos

Campo Descrição
PreCompact Evento disparado antes da compactação
SessionStart Evento disparado ao iniciar/retomar sessão
matcher: "auto" Compactação automática (contexto cheio)
matcher: "manual" Compactação manual (comando /compact)
matcher: "compact" Sessão iniciada após compactação
timeout: 30 Tempo máximo de execução em segundos

8. Passo 5: Configurar Hooks do Projeto (Opcional)

Se quiser hooks específicos para um projeto, crie:

Arquivo: /seu-projeto/.claude/settings.local.json

{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pre-compact.sh",
            "timeout": 30
          }
        ]
      },
      {
        "matcher": "manual",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pre-compact.sh",
            "timeout": 30
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-compact.sh",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

E crie os hooks em /seu-projeto/.claude/hooks/ (pode copiar os globais ou customizar).

Variáveis de Ambiente Disponíveis

Variável Valor
$HOME Diretório home (ex: /Users/usuario ou /home/usuario)
$CLAUDE_PROJECT_DIR Raiz do projeto atual

9. Passo 6: Dar Permissões

macOS e Linux

# Hooks globais
chmod +x ~/.claude/hooks/pre-compact.sh
chmod +x ~/.claude/hooks/post-compact.sh

# Hooks do projeto (se criou)
chmod +x /seu-projeto/.claude/hooks/pre-compact.sh
chmod +x /seu-projeto/.claude/hooks/post-compact.sh

10. Passo 7: Testar

Testar Hook PreCompact

# Criar arquivo de teste simulando transcript
echo "status:in-progress step:3 implementation" > /tmp/test-transcript.txt

# Executar hook
echo '{"session_id":"test123","transcript_path":"/tmp/test-transcript.txt","trigger":"manual"}' | \
  ~/.claude/hooks/pre-compact.sh

# Verificar saída (deve mostrar JSON com hookSpecificOutput)
# Verificar checkpoint criado
cat ~/.claude/checkpoints/session-test123.json

# Verificar log
tail ~/.claude/logs/pre-compact.log

Saída esperada:

{
  "hookSpecificOutput": {
    "hookEventName": "PreCompact",
    "additionalContext": "⚠️ COMPACTAÇÃO EM ANDAMENTO\n\nUm checkpoint foi salvo automaticamente."
  }
}

Testar Hook PostCompact

# Executar hook (precisa do checkpoint do teste anterior)
echo '{"session_id":"test123","source":"compact"}' | \
  ~/.claude/hooks/post-compact.sh

# Verificar saída (deve mostrar instruções de recuperação)
# Verificar log
tail ~/.claude/logs/post-compact.log

Testar em Sessão Real

  1. Inicie o Claude Code
  2. Peça para fazer uma tarefa longa (ex: "implemente um CRUD completo")
  3. Execute /compact manualmente
  4. Verifique se as instruções de recuperação aparecem
  5. Verifique os logs: tail ~/.claude/logs/*.log

11. Diferenças macOS vs Linux

Os hooks foram escritos para funcionar em ambos os sistemas, mas há algumas diferenças importantes:

Dependência: jq

O jq é necessário para manipular JSON. Instale conforme seu sistema:

Sistema Comando de Instalação
macOS (Homebrew) brew install jq
macOS (MacPorts) sudo port install jq
Ubuntu/Debian sudo apt install jq
Fedora/RHEL sudo dnf install jq
Arch Linux sudo pacman -S jq

Comando stat (verificar idade do arquivo)

O comando stat tem sintaxe diferente:

Sistema Comando Exemplo
macOS stat -f %m arquivo Retorna timestamp de modificação
Linux stat -c %Y arquivo Retorna timestamp de modificação

Os hooks já tratam isso automaticamente com detecção de $OSTYPE:

if [[ "$OSTYPE" == "darwin"* ]]; then
    FILE_TIME=$(stat -f %m "$FILE" 2>/dev/null || echo 0)
else
    FILE_TIME=$(stat -c %Y "$FILE" 2>/dev/null || echo 0)
fi

Comando date

O formato -Iseconds funciona em ambos:

date -Iseconds
# Saída: 2026-01-27T10:30:00-03:00

Nota: Em algumas versões antigas do macOS, pode ser necessário usar gdate do GNU coreutils:

# Se date -Iseconds não funcionar no macOS:
brew install coreutils
# Depois use gdate ao invés de date

Paths

Item macOS Linux
Home /Users/usuario /home/usuario
Variável $HOME funciona em ambos $HOME funciona em ambos

Verificar seu sistema

# Qual sistema você está usando?
echo $OSTYPE
# darwin22.0 = macOS
# linux-gnu = Linux

# Verificar se jq está instalado
jq --version

# Verificar se date suporta -Iseconds
date -Iseconds

12. Integração com MCP Memory

Os hooks salvam um checkpoint rápido em arquivo, mas para estado completo use o MCP Memory.

Por que usar os dois?

Aspecto Checkpoint (Arquivo) MCP Memory
Velocidade Instantâneo Requer chamada de API
Detalhe Resumo (1500 chars) Estado completo estruturado
Persistência Deletado após uso Permanente
Buscável Não Sim (search_nodes)

Fluxo ideal:

  1. Durante execução → Salva no MCP Memory (detalhado)
  2. Na compactação → Hook salva checkpoint (resumo rápido)
  3. Após compactação → Hook instrui a buscar no MCP Memory

Salvar Estado Durante Execução

Ao trabalhar em uma tarefa, salve o progresso no Memory:

// Criar entidade para rastrear trabalho
mcp__memory__create_entities({
  entities: [{
    name: "task-execution::feature-xyz",
    entityType: "work-in-progress",
    observations: [
      "status:in-progress",
      "user-demand:Implementar feature XYZ",
      "started-at:2026-01-27T10:00:00Z"
    ]
  }]
})

// A cada etapa, adicionar observação
mcp__memory__add_observations({
  observations: [{
    entityName: "task-execution::feature-xyz",
    contents: [
      "step:1:created-service",
      "file:src/xyz.service.ts",
      "next-step:criar-controller"
    ]
  }]
})

Recuperar Estado Após Compactação

Quando o hook instrui, execute:

// 1. Buscar trabalhos em andamento
mcp__memory__search_nodes({ query: "in-progress" })

// 2. Abrir entidade específica
mcp__memory__open_nodes({ names: ["task-execution::feature-xyz"] })

// 3. Ler observações e continuar do ponto correto

Padrão de Observações Recomendado

Prefixo Uso Exemplo
status: Estado atual status:in-progress
step:N: Etapa completada step:3:service-created
next-step: Próxima ação next-step:criar-controller
user-demand: Demanda original user-demand:Implementar login
file: Arquivo criado/modificado file:src/auth.ts

13. Troubleshooting

Hooks Não Executam

Verificar:

# 1. Permissões
ls -la ~/.claude/hooks/
# Deve mostrar -rwxr-xr-x (x = executável)

# 2. jq instalado
jq --version

# 3. Sintaxe do settings.json
cat ~/.claude/settings.json | jq .
# Se der erro, o JSON está inválido

# 4. Logs
tail -50 ~/.claude/logs/pre-compact.log
tail -50 ~/.claude/logs/post-compact.log

Causas comuns:

  • Falta chmod +x nos scripts
  • jq não instalado
  • JSON inválido no settings.json
  • Path errado (usar $HOME não ~)

Checkpoint JSON Inválido

Erro: jq: parse error: Invalid numeric literal

Causa: Caracteres especiais no contexto não escapados.

Solução: O hook usa jq -n --arg que escapa automaticamente. Se ainda falhar:

# Verificar se jq está funcionando
echo '{"test": "value"}' | jq .

# Testar criação de JSON com caracteres especiais
jq -n --arg text 'texto com "aspas" e \barras' '{ content: $text }'

Checkpoint Não Encontrado

Verificar:

# Listar checkpoints
ls -la ~/.claude/checkpoints/

# Ver conteúdo
cat ~/.claude/checkpoints/session-*.json | jq .

Causas:

  • Session ID mudou entre compactações (fallback busca mais recente até 10 min)
  • Checkpoint já foi consumido (é deletado após uso)
  • Mais de 10 minutos entre compactação e retorno

Reiniciar Claude Code

Após modificar settings.json, reinicie o Claude Code para carregar as novas configurações.


14. Referência Rápida

Arquivos para Criar

Arquivo Obrigatório Descrição
~/.claude/hooks/pre-compact.sh Sim Salva estado antes de compactar
~/.claude/hooks/post-compact.sh Sim Recupera estado após compactar
~/.claude/settings.json Sim Registra os hooks (adicionar seção)
/projeto/.claude/settings.local.json Não Hooks específicos do projeto
/projeto/.claude/hooks/*.sh Não Hooks customizados do projeto

Comandos Úteis

# Criar estrutura completa
mkdir -p ~/.claude/{hooks,checkpoints,logs}

# Dar permissões
chmod +x ~/.claude/hooks/*.sh

# Ver logs em tempo real
tail -f ~/.claude/logs/pre-compact.log
tail -f ~/.claude/logs/post-compact.log

# Testar JSON do settings
cat ~/.claude/settings.json | jq .

# Listar checkpoints
ls -la ~/.claude/checkpoints/

# Limpar checkpoints antigos (mais de 1 hora)
find ~/.claude/checkpoints -name "*.json" -mmin +60 -delete

# Verificar se jq está instalado
jq --version

Eventos e Matchers

Evento Matcher Quando Dispara
PreCompact auto Compactação automática (contexto cheio)
PreCompact manual Comando /compact
SessionStart compact Após qualquer compactação
SessionStart resume Ao resumir sessão existente
SessionStart new Nova sessão iniciada

Checklist de Instalação

  • jq instalado (jq --version)
  • Diretórios criados (~/.claude/hooks, checkpoints, logs)
  • pre-compact.sh criado e com chmod +x
  • post-compact.sh criado e com chmod +x
  • settings.json atualizado com seção hooks
  • Claude Code reiniciado
  • Teste manual executado com sucesso
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment