Claude Code

Claude Project Status: como eu resolvi o problema de contexto entre projetos no Claude Code


$ claude plugin add kursku/claude-project-status
 Plugin installed: claude-project-status v1.0.0
  3 skills, 1 hook, 3 scripts

Um comando. A partir de agora, toda sessão do Claude Code sabe onde você parou na última vez.

O cenário que motivou o plugin

Eu gerencio 8 projetos simultâneos com Claude Code. Um SaaS, um blog, automações para clientes, um ebook, um curso. Toda vez que trocava de projeto, perdia 3-5 minutos explicando o contexto: “estamos na fase X, a última decisão foi Y, as próximas tarefas são Z”.

Multiplica isso por 4-5 trocas de contexto por dia. São 15-25 minutos diários gastos repetindo informação que o Claude deveria saber.

O CLAUDE.md resolve parte do problema — ele é lido automaticamente em toda sessão. Mas é um arquivo estático. Não captura o estado dinâmico: em que fase o projeto está agora, o que foi decidido ontem, qual a próxima tarefa concreta.

O Claude Project Status preenche essa lacuna.

O que o plugin faz

Três coisas:

  1. Mantém um STATUS block machine-readable no CLAUDE.md de cada projeto
  2. Acumula um SUMMARY.md com o log de decisões de cada sessão
  3. Gera um dashboard central (~/PROJECTS.md) com a visão de todos os projetos

Tudo orquestrado por 3 comandos (/update-status, /dashboard, /prioritize) e um hook automático que detecta quando você editou arquivos numa sessão.

STATUS block — o estado vivo do projeto

O coração do plugin é um bloco YAML dentro de um HTML comment, posicionado no topo do CLAUDE.md:

<!-- STATUS
projeto: meu-saas
fase: MVP - Autenticação
proximas_tarefas:
  - implementar OAuth flow com Google
  - adicionar session management com refresh tokens
  - testes de integração no middleware
ultima_decisao: JWT ao invés de sessions — scaling stateless sem Redis
ultima_sessao: 2026-05-26
prioridade: alta
-->

Por que um HTML comment? Duas razões:

  1. Invisível no render — o GitHub, editores Markdown e qualquer viewer ignora comments. O CLAUDE.md continua legível para humanos.
  2. Lido pelo Claude automaticamente — o Claude Code carrega o CLAUDE.md inteiro no início de cada sessão. O STATUS block está lá, em texto plano, sem precisar de nenhuma integração extra.

O resultado prático: você abre um projeto e o Claude já sabe a fase atual, as tarefas pendentes e a última decisão tomada. Zero explicação manual.

Campos do STATUS block

CampoTipoPropósito
projetostringNome do projeto (usado no dashboard)
fasestringFase atual — formato livre, ex: “MVP - Auth”, “Refactor - Data layer”
proximas_tarefaslista YAML2-3 tarefas concretas e acionáveis
ultima_decisaostringA decisão mais relevante da última sessão + motivo
ultima_sessaodata ISOQuando o projeto foi tocado pela última vez
prioridadeenumalta, média ou baixa

O formato é deliberadamente simples. Sem IDs, sem timestamps complexos, sem nested objects. Qualquer pessoa (ou LLM) lê e entende em 2 segundos.

SUMMARY.md — o changelog de decisões

Git log registra o que mudou no código. O SUMMARY.md registra por que mudou e para onde vai:

## 2026-05-26
- Implementado middleware de autenticação com JWT + refresh token rotation
- Decisão: refresh tokens com rotação automática (segurança > simplicidade)
- Decisão: rate limiting por IP no login (100 req/15min)
- Próximo: testes de integração e endpoint de logout

## 2026-05-24
- Setup inicial: Next.js 15 + Drizzle ORM + PostgreSQL
- Decisão: PostgreSQL ao invés de SQLite (multi-tenant desde o início)
- Decisão: Drizzle ao invés de Prisma (type-safety sem code generation)
- Próximo: schema de usuários e middleware de auth

## 2026-05-22
- Definição de escopo do MVP: auth + CRUD de projetos + billing básico
- Decisão: Stripe ao invés de implementação própria (compliance PCI)
- Próximo: setup do projeto e escolha de ORM

Cada entrada é append-only. O arquivo cresce com o tempo e se torna uma timeline navegável do projeto. Quando você precisa lembrar por que uma decisão foi tomada há 3 semanas, está aqui — não num chat perdido ou numa memória vaga.

O Claude também lê o SUMMARY.md quando precisa de contexto histórico. Se você perguntar “por que escolhemos JWT?”, ele encontra a resposta sem você precisar explicar de novo.

Dashboard central — a visão de helicóptero

O script generate-dashboard.js escaneia todos os diretórios configurados, encontra projetos com STATUS blocks, e gera um arquivo Markdown centralizado:

# Projects Dashboard
_Updated: 2026-05-26 14:30_

---

## meu-saas — 🔴 alta
**Phase:** MVP - Auth
**Last session:** 2026-05-26
**Last decision:** JWT para scaling stateless
**Next tasks:**
- implementar OAuth flow com Google
- adicionar session management com refresh tokens

## api-clientes — 🔴 alta
**Phase:** Integração - Webhooks
**Last session:** 2026-05-19
**Last decision:** retry exponencial com dead letter queue
**Next tasks:**
- implementar DLQ no BullMQ
- dashboard de webhooks falhados

## blog — 🟢 baixa
**Phase:** Content - SEO
**Last session:** 2026-05-20
**Last decision:** migrar de MDX para MD puro
**Next tasks:**
- otimizar imagens com sharp
- adicionar sitemap dinâmico

---

## Priorities
_Awaiting analysis — run `/prioritize` for updated suggestions._

Projetos ordenados por prioridade. Indicadores visuais por cor. Um olhar e você sabe: o que está quente, o que está parado, onde investir tempo.

Instalação

Via plugin marketplace

claude plugin add kursku/claude-project-status

O Claude Code resolve o repositório, baixa os arquivos, registra skills, commands e hooks automaticamente.

Instalação manual (para quem quer controle total)

# Clone
git clone https://github.com/kursku/claude-project-status.git

# Copie skills
mkdir -p ~/.claude/skills
cp -r claude-project-status/skills/update-status ~/.claude/skills/
cp -r claude-project-status/skills/dashboard ~/.claude/skills/
cp -r claude-project-status/skills/prioritize ~/.claude/skills/

# Copie scripts
mkdir -p ~/.claude/scripts
cp claude-project-status/scripts/*.js ~/.claude/scripts/

Depois, configure o hook Stop no ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "type": "command",
        "command": "node ~/.claude/scripts/session-summary.js"
      }
    ]
  }
}

E defina os diretórios a escanear em ~/.project-status.json:

{
  "scanDirs": [
    "~/projects",
    "~/work",
    "~/freelance"
  ]
}

Os três comandos em detalhe

/update-status — salvar o estado

O comando que você roda no final de cada sessão. Internamente, ele executa 7 passos:

  1. Lê o CLAUDE.md do diretório atual
  2. Analisa a sessão corrente — identifica fase, tarefas, decisões
  3. Atualiza (ou cria) o <!-- STATUS ... --> block no topo do arquivo
  4. Cria o CLAUDE.md se não existir
  5. Faz append no SUMMARY.md com o resumo da sessão
  6. Executa hooks pós-update (se configurados)
  7. Regenera o dashboard central

O skill que orquestra isso:

# Update Status — Skill Definition

1. Read CLAUDE.md
2. Analyze current session:
   - Current project phase
   - Next 2-3 concrete, actionable tasks
   - Most relevant decision + why
   - Priority level: alta | média | baixa
3. Update <!-- STATUS --> block (create if missing)
4. Append to SUMMARY.md
5. Run post-update hooks
6. Regenerate dashboard
7. Confirm to user

Na prática, leva 5-10 segundos. O Claude analisa o que aconteceu na sessão, propõe o resumo, e você confirma ou ajusta.

/dashboard — visão geral

Gera o dashboard e apresenta um comentário analítico:

  • Quantos projetos estão ativos
  • Quais têm prioridade alta mas sem atividade recente (projetos “parados”)
  • Qual projeto tem mais tarefas pendentes acumuladas
  • Sugestão de onde focar agora, com justificativa de uma linha

O script por trás (generate-dashboard.js) faz o trabalho pesado: escaneia diretórios, parseia STATUS blocks com regex, ordena por prioridade, e escreve o Markdown.

/prioritize — análise de prioridades

Vai além do dashboard. Avalia cada projeto por 4 critérios:

CritérioPesoLógica
Prioridade declaradaAltoalta > média > baixa
InatividadeMédioProjetos alta-prioridade parados >7 dias sobem
MomentumMédioSessões recentes (≤3 dias) + tarefas concretas = vantagem
Volume pendenteBaixoMais tarefas = mais bloqueado

O output é um ranking com justificativa:

1. **meu-saas** — alta prioridade, 3 tarefas pendentes, última sessão ontem (momentum alto)
2. **api-clientes** — alta prioridade mas parado há 9 dias (risco de perder contexto)
3. **blog** — baixa prioridade mas 5 tarefas acumuladas (quick wins disponíveis)

E atualiza a seção ## Priorities no dashboard com a análise datada.

O hook automático — detecção passiva

O plugin registra um hook no evento Stop do Claude Code. Toda vez que uma sessão termina, o script session-summary.js roda automaticamente.

O que ele faz:

// Fluxo simplificado do session-summary.js

1. Recebe o JSON do evento Stop (inclui cwd e transcript_path)
2. Verifica se o diretório tem CLAUDE.md com STATUS block
3. Lê o transcript da sessão
4. Procura por chamadas de "Edit" ou "Write" (houve edição?)
5. Se sim: cria ~/.claude/pending-updates/<projeto>.json

O arquivo de pending:

{
  "project": "meu-saas",
  "path": "/home/user/projects/meu-saas",
  "timestamp": "2026-05-26 14:30"
}

O hook não atualiza o STATUS block sozinho — isso exigiria análise de contexto que só o Claude faz bem. Ele apenas marca que o projeto foi tocado. Na próxima vez que você rodar /dashboard ou /update-status, essa informação está disponível.

É uma rede de segurança para quem esquece de rodar /update-status no final da sessão.

Configuração avançada — hooks pós-update

O ~/.project-status.json aceita hooks que rodam após cada /update-status:

{
  "scanDirs": ["~/projects", "~/work"],
  "hooks": {
    "post-update": [
      "node ~/scripts/sync-notion.js",
      "curl -s -X POST https://hooks.slack.com/services/T.../B.../xxx -d '{\"text\":\"Project updated\"}'",
      "cd $(pwd) && git add SUMMARY.md && git commit -m 'chore: session summary' --no-verify"
    ]
  }
}

Cada hook:

  • Roda com execSync (síncrono, bloqueante)
  • Tem timeout de 30 segundos
  • Falhas são logadas mas não quebram o fluxo
  • Recebe o cwd do projeto como diretório de trabalho

Casos de uso reais:

  • Auto-commit do SUMMARY.md — mantém o histórico no git sem esforço manual
  • Webhook para Slack/Telegram — notifica a equipe que o projeto foi atualizado
  • Sync com Notion/Linear — espelha o STATUS block numa board externa
  • Backup — copia o SUMMARY.md para um diretório de backup

Arquitetura interna

O plugin inteiro são 3 scripts JavaScript (~200 linhas total), 3 skills Markdown, e 1 hook JSON:

claude-project-status/
├── .claude-plugin/
│   ├── plugin.json          # Metadata do plugin (nome, versão, keywords)
│   └── marketplace.json     # Registro no marketplace
├── commands/
│   ├── dashboard.md         # Comando /dashboard
│   ├── prioritize.md        # Comando /prioritize
│   └── update-status.md     # Comando /update-status
├── hooks/
│   └── hooks.json           # Hook Stop → session-summary.js
├── scripts/
│   ├── generate-dashboard.js  # Scan + parse + gera ~/PROJECTS.md
│   ├── session-summary.js     # Detecta edições, marca pending
│   └── run-hooks.js           # Executa hooks pós-update do usuário
└── skills/
    ├── dashboard/SKILL.md
    ├── prioritize/SKILL.md
    └── update-status/SKILL.md

Decisões de design

Zero dependências externas. Os scripts usam apenas módulos nativos do Node.js: node:fs, node:path, node:os, node:child_process. Nenhum npm install. Nenhum node_modules. O plugin funciona em qualquer máquina com Node 18+.

Arquivos como banco de dados. O estado vive em Markdown e JSON — formatos que humanos leem, git versiona, e qualquer ferramenta processa. Sem SQLite, sem Redis, sem serviço rodando em background.

Parsing com regex, não com parser YAML. O STATUS block é simples o suficiente para regex. Isso evita dependência de um parser YAML e mantém o script em ~50 linhas.

A função de parsing no generate-dashboard.js:

function parseStatusBlock(content) {
  const match = content.match(/<!--\s*STATUS\s*\n([\s\S]*?)-->/)
  if (!match) return null

  const block = match[1]
  const get = (key) => {
    const m = block.match(new RegExp(`^${key}:\\s*(.+)`, 'm'))
    return m ? m[1].trim() : ''
  }

  const tasksMatch = block.match(/proximas_tarefas:\s*\n((?:\s+-\s+.+\n?)+)/)
  const tasks = tasksMatch
    ? tasksMatch[1].split('\n')
        .filter(l => l.trim().startsWith('-'))
        .map(l => l.replace(/^\s*-\s*/, '').trim())
    : []

  return {
    projeto: get('projeto'),
    fase: get('fase'),
    prioridade: get('prioridade'),
    ultima_decisao: get('ultima_decisao'),
    ultima_sessao: get('ultima_sessao'),
    proximas_tarefas: tasks
  }
}

Cross-platform. Usa path.join e os.homedir() em vez de paths hardcoded. Funciona em macOS, Linux e Windows sem adaptação.

Idempotente. Rodar /update-status duas vezes na mesma sessão sobrescreve o STATUS block (não duplica) e faz append no SUMMARY.md apenas uma vez (o skill verifica a data).

O hook em detalhe

O hooks.json registra o script no evento Stop:

{
  "hooks": [
    {
      "matcher": "Stop",
      "hooks": [
        {
          "type": "command",
          "command": "node scripts/session-summary.js"
        }
      ]
    }
  ]
}

O script recebe o evento via stdin como JSON:

// session-summary.js — fluxo completo

let input = ''
process.stdin.on('data', chunk => { input += chunk })
process.stdin.on('end', () => {
  const data = JSON.parse(input)
  const cwd = data.cwd  // diretório do projeto

  // 1. Verifica se tem CLAUDE.md com STATUS block
  const claudeMd = path.join(cwd, 'CLAUDE.md')
  if (!fs.existsSync(claudeMd)) return
  if (!fs.readFileSync(claudeMd, 'utf8').includes('<!-- STATUS')) return

  // 2. Verifica se houve edições na sessão
  const transcript = fs.readFileSync(data.transcript_path, 'utf8')
  if (!transcript.includes('"Edit"') && !transcript.includes('"Write"')) return

  // 3. Marca como pendente
  const pendingDir = path.join(os.homedir(), '.claude', 'pending-updates')
  fs.mkdirSync(pendingDir, { recursive: true })
  fs.writeFileSync(
    path.join(pendingDir, `${path.basename(cwd)}.json`),
    JSON.stringify({ project: path.basename(cwd), path: cwd, timestamp: now })
  )
})

Leve, rápido, sem side effects visíveis ao usuário.

Fluxo de trabalho na prática

Sessão típica (5 projetos ativos)

09:00 — Abro o terminal
$ claude
> /dashboard

# Projects Dashboard
## meu-saas — 🔴 alta (last: ontem)
## api-clientes — 🔴 alta (last: 5 dias atrás) ← parado
## blog — 🟢 baixa (last: 3 dias)

> /prioritize
1. **api-clientes** — alta prioridade, parado há 5 dias, risco de perder contexto
2. **meu-saas** — alta prioridade, momentum ativo, 3 tarefas pendentes

# Decido trabalhar no api-clientes
$ cd ~/projects/api-clientes
$ claude

# O Claude já sabe:
# - Fase: Integração - Webhooks
# - Última decisão: retry exponencial com DLQ
# - Próximas tarefas: implementar DLQ, dashboard de falhas

# Trabalho por 2 horas...

> /update-status
✓ STATUS block atualizado
✓ SUMMARY.md: entrada de 2026-05-27 adicionada
✓ Dashboard regenerado (5 projetos)

Retomada após 2 semanas de pausa

Você volta de férias. 8 projetos. Não lembra de nada.

$ claude
> /prioritize

1. **meu-saas** — alta prioridade, parado há 14 dias, 3 tarefas pendentes
   (OAuth flow estava em andamento antes da pausa)
2. **api-clientes** — alta prioridade, parado há 19 dias
   (DLQ implementado parcialmente)
3. **curso** — média prioridade, parado há 16 dias
   (módulo 3 em rascunho)

Sem o plugin, você gastaria 30+ minutos relembrando o estado de cada projeto. Com ele, 10 segundos.

Comparação com alternativas

CLAUDE.md manual (sem plugin)

Funciona, mas exige disciplina para atualizar manualmente. O STATUS block fica desatualizado em 2-3 sessões. Sem dashboard, sem priorização, sem hook automático.

Notion/Linear/Jira

Ótimos para gestão de projeto em equipe. Mas o Claude não lê seu Notion no início da sessão. O contexto precisa estar no CLAUDE.md — onde o agente realmente olha.

Os hooks pós-update permitem sincronizar com essas ferramentas. Melhor dos dois mundos: contexto local para o Claude, visibilidade externa para humanos.

Memory do Claude Code

O sistema de memória do Claude Code persiste informações entre sessões, mas é genérico. Não tem estrutura de “fase”, “próximas tarefas”, “prioridade”. Não gera dashboard. Não compara projetos entre si.

O plugin complementa a memória — não compete com ela.

Git log / commit messages

Registra o que mudou no código. Não registra decisões de design, trade-offs considerados, ou o plano para a próxima sessão. São camadas diferentes de informação.

Limitações

Transparência sobre o que o plugin não faz:

  • Não é automático — o /update-status precisa ser rodado manualmente. O hook detecta edições mas não atualiza o STATUS sozinho.
  • Scan shallow — o dashboard escaneia apenas 1 nível de profundidade nos scanDirs. Projetos em subpastas aninhadas não são encontrados automaticamente.
  • Sem UI gráfica — tudo é terminal + Markdown. Se você precisa de gráficos, use o dashboard como fonte de dados para outra ferramenta.
  • Sem sync entre máquinas — o ~/PROJECTS.md é local. Para compartilhar, commite os SUMMARY.md no git ou use hooks para sincronizar.
  • Regex-based parsing — STATUS blocks com YAML malformado (tabs misturados com espaços, caracteres especiais não-escapados) podem falhar silenciosamente.

Roadmap

Áreas planejadas para as próximas versões:

  • Scan recursivo — encontrar projetos em qualquer profundidade
  • Auto-detect por .git/ — considerar qualquer repo git como projeto potencial
  • Templates customizáveis — campos extras no STATUS block por projeto
  • Export JSON — dashboard em formato estruturado para integrações
  • Pending updates no dashboard — mostrar projetos marcados pelo hook que ainda não foram atualizados

Repositório

Open-source, licença MIT:

github.com/kursku/claude-project-status

Stack: Node.js 18+, zero dependências, ~200 linhas de código total.

Contribuições são bem-vindas — especialmente nos itens do roadmap acima.

claude plugin add kursku/claude-project-status

COMENTÁRIOS

Nenhum comentário ainda.