Claude Code Solo
~25 min Intermediário Parte 6

W1: Claude Code Solo

O workflow mais direto. Sem plugins, sem instalações adicionais. O desenvolvedor e o Claude Code como único par — com toda a disciplina de qualidade aplicada manualmente.

Quando usar

O workflow Solo é o ponto de entrada natural para quem está começando com Claude Code ou para cenários onde a ausência de ferramentas externas é uma vantagem — não uma limitação. A escolha correta começa pelo entendimento do fit.

Fit — Use quando

  • Dev solo ou pequeno projeto pessoal
  • Prototipagem rápida ou POC
  • Feature isolada e bem definida
  • Refactoring pontual com escopo claro
  • Ambiente corporativo restrito (sem npm global)
  • Onboarding inicial no Claude Code

Misfit — Evite quando

  • Time com 3+ engenheiros paralelos
  • Múltiplos milestones interdependentes
  • Precisa de memória cross-session automatizada
  • Codebase com mais de 50 arquivos envolvidos
  • Necessita de sub-agentes paralelos
  • Contexto > 80K tokens recorrentemente
Disciplina, não simplicidade
Solo não significa sem qualidade. Significa que você é o único orquestrador. Toda a disciplina — TDD, SOLID, OWASP, arquitetura hexagonal — é aplicada manualmente, via CLAUDE.md e prompts precisos. A ausência de automação não é licença para atalhos.

Diagrama do workflow

O ciclo completo do W1 passa por seis etapas principais. O TDD loop e o testing gate são obrigatórios — não opcionais — independentemente do tamanho da feature.

flowchart TD A[Dev descreve feature/bug] --> B[Claude lê codebase\nMapeia impacto] B --> C[PLAN.md — proposta de plano] C --> D{Dev revisa plano} D -->|Ajusta| C D -->|Aprova| E[TDD Loop] E --> E1[Red: escreve teste] E1 --> E2[Green: implementa mínimo] E2 --> E3[Refactor: limpa] E3 --> E4{> 70K tokens?} E4 -->|Sim| E5[/compact] E5 --> E E4 -->|Não| F[Auto-review] F --> F1[Clean Code + SOLID] F1 --> F2[OWASP scan] F2 --> G[Testing Gate] G --> G1[vitest unit] G1 --> G2[vitest integration] G2 --> G3[cypress run] G3 --> G4{k6 load?} G4 -->|Mudança de API| G5[k6 run] G4 -->|Não necessário| H G5 --> H[gh pr create] H --> I[Deploy / Merge]

Ciclo completo do W1. O loop TDD repete por iteração de funcionalidade; /compact é acionado quando o contexto ultrapassa 70K tokens.

Passo a passo

Cada fase tem entradas, saídas e comandos reais. Execute na ordem — pular fases acumula débito técnico que se paga com juros.

Fase 1 — Discovery

Antes de qualquer implementação, o Claude precisa mapear o codebase. Isso é inegociável: um Claude sem contexto produz código que não se encaixa.

# Abre Claude Code na raiz do projeto
claude

# Prompt inicial — forneça contexto antes de pedir ação
# "Leia os arquivos src/domain/, src/adapters/ e CLAUDE.md.
#  Depois liste os arquivos que serão impactados por [feature X].
#  Não escreva código ainda."

Saída esperada: lista de arquivos impactados, dependências identificadas, riscos mapeados.

Fase 2 — Planning

Crie o PLAN.md manualmente ou peça ao Claude para rascunhá-lo. Você revisa e aprova antes de qualquer linha de código ser escrita.

# Prompt para gerar PLAN.md
# "Com base no mapeamento anterior, crie um PLAN.md com:
#   - Objetivo em uma frase
#   - Lista de arquivos a criar/modificar
#   - Sequência de implementação (domain first)
#   - Testes que precisam ser escritos
#   - Riscos e mitigações
#  Salve em PLAN.md na raiz."

Gate de aprovação: leia o PLAN.md, faça ajustes, só avance quando o plano estiver correto. Plano errado = implementação errada.

Fase 3 — TDD Loop

Red → Green → Refactor. O Claude escreve o teste antes da implementação. Se o teste não falha primeiro, o teste está errado.

# Prompt para iniciar TDD
# "Seguindo o PLAN.md, escreva APENAS o teste unitário para
#  [UseCase X]. Use vitest. O arquivo deve ser
#  src/domain/__tests__/[use-case].unit.test.ts.
#  Não implemente o use case ainda."

# Verificar que o teste falha (RED)
npx vitest run src/domain/__tests__/[use-case].unit.test.ts

# Prompt para implementação mínima (GREEN)
# "Agora implemente o mínimo necessário em
#  src/domain/[use-case].ts para os testes passarem.
#  Sem over-engineering."

npx vitest run src/domain/__tests__/[use-case].unit.test.ts

# Prompt para refactor (REFACTOR)
# "Refatore src/domain/[use-case].ts aplicando SOLID:
#  - S: responsabilidade única
#  - D: dependa de interfaces, não implementações concretas
#  Execute os testes depois de cada mudança."

npx vitest run src/domain/__tests__/[use-case].unit.test.ts

Fase 4 — Auto-review

Antes de qualquer teste de integração, instrua o Claude a revisar o código produzido. Esta é a fase mais subestimada — e a que mais pega bugs sutis.

# Prompt de auto-review
# "Revise os arquivos modificados nesta sessão e verifique:
#   1. SOLID: alguma violação?
#   2. OWASP A01-A10: algum vetor de ataque presente?
#      - A01: controle de acesso adequado?
#      - A03: algum input sem validação/parametrização?
#      - A07: autenticação e sessão seguros?
#   3. Clean Code: funções > 20 linhas? Nomes obscuros?
#   4. Arquitetura hexagonal: domain tem dependência de infra?
#  Liste os problemas encontrados antes de corrigir."

Fase 5 — Testing Gate

Todos os quatro níveis devem passar antes do PR. Não existe "só unit tests por enquanto".

# Unit tests — domínio isolado
npx vitest run --testPathPattern='*.unit.test'

# Integration tests — com DB real (Docker)
docker compose up -d db
npx vitest run --testPathPattern='*.integration.test'

# E2E — jornadas críticas
npx cypress run --headless

# Load test — obrigatório se houve mudança de API
k6 run k6/load.js

# Stress test — novo endpoint ou rota crítica
k6 run k6/stress.js

# Audit de segurança de dependências
npm audit --audit-level=high

Fase 6 — Deploy

PR criado via CLI com descrição gerada pelo Claude. Merge após CI verde.

# Cria branch de feature
git checkout -b feat/[feature-name]
git add -p   # revisão interativa — nunca git add .
git commit -m "feat: [descrição concisa da mudança]"

# Prompt para descrição do PR
# "Gere uma descrição de PR em markdown para as mudanças
#  desta sessão. Inclua: motivação, mudanças, como testar,
#  checklist de segurança OWASP."

gh pr create --title "feat: [feature-name]" --body "$(cat pr-description.md)"

# Acompanhar CI
gh pr checks --watch

CLAUDE.md mínimo para W1

Este é o CLAUDE.md de referência para o workflow Solo. As diretivas aqui substituem instruções ad hoc em cada prompt — codifique uma vez, aplique sempre. Adapte ao stack do seu projeto.

# CLAUDE.md — W1: Claude Code Solo

## Stack
- Runtime: Node.js 22 + TypeScript 5 strict mode
- Framework: (adapte ao seu projeto)
- ORM: Prisma / TypeORM
- Testes: Vitest (unit + integration) + Cypress (E2E)
- Load: k6

## Comandos principais
```bash
npm run dev        # desenvolvimento local
npm run test:unit  # npx vitest run --testPathPattern='*.unit.test'
npm run test:int   # npx vitest run --testPathPattern='*.integration.test'
npm run test:e2e   # npx cypress run --headless
npm run build      # build de produção
npm audit          # auditoria de segurança
```

## Arquitetura: Hexagonal (Ports & Adapters)
- src/domain/        — entidades, use cases, value objects (SEM imports de infra)
- src/ports/         — interfaces (IUserRepository, IMailService, etc.)
- src/adapters/      — implementações concretas (HTTP, DB, Mail)
- src/app/           — composição de dependências (DI container)

Regra absoluta: domain NUNCA importa de adapters.
Dependa de interfaces (ports), nunca de implementações concretas.

## SOLID — diretivas obrigatórias
- S: cada classe/função tem UMA razão para mudar
- O: use strategy/decorator para variações, não if/else
- L: subtipos substituem base sem quebrar comportamento
- I: interfaces pequenas e específicas — nunca interface "God"
- D: construtor recebe interfaces, nunca instancia dependências diretamente

## TDD — sequência obrigatória
1. Escreve o TESTE primeiro (deve falhar — RED)
2. Implementa o MÍNIMO para passar (GREEN)
3. Refatora sem quebrar (REFACTOR)
NUNCA implementar sem teste existente e falhando primeiro.

## OWASP Top 10 — checklist de cada feature
- A01: toda rota verifica autenticação + autorização (RBAC)
- A02: secrets apenas em env vars — nunca hardcoded
- A03: queries sempre parametrizadas — proibido string concatenation
- A04: threat model na fase de design
- A06: npm audit como gate pré-PR
- A07: JWT validado em cada request; tokens expiram em 15min (access) / 7d (refresh)

## Context window discipline
- Máximo de 80K tokens ativos no orquestrador
- Execute /compact entre fases (após planning, após implementação, após review)
- Handoffs via PLAN.md e CONTEXT.md — nunca in-memory
- Destrua a sessão após cada fase completa se contexto > 60K

## Proibições
- Nunca usar `any` em TypeScript
- Nunca fazer `git add .` — sempre `git add -p`
- Nunca implementar sem teste falhando primeiro
- Nunca commitar com npm audit de alta severidade aberto
- Nunca fazer strings SQL por concatenação

Como aplicar TDD neste workflow

TDD em pair programming com Claude Code tem uma dinâmica específica: o Claude escreve tanto o teste quanto a implementação — mas em fases separadas, com validação humana entre elas. A instrução abaixo é o prompt exato que dispara o ciclo correto.

Instrução exata para o Claude
Adicione ao CLAUDE.md ou use como prompt a cada nova funcionalidade:
"Para cada funcionalidade que implementares: (1) escreva o teste unitario primeiro e confirme que ele falha; (2) implemente o minimo necessario para o teste passar; (3) refatore aplicando SOLID. Mostre o resultado de cada etapa antes de avancar."

Exemplo concreto: JWT Authentication

Feature: adicionar autenticacao JWT com refresh token ao dominio de usuarios.

Passo 1 — Claude escreve o teste (RED)

// src/domain/__tests__/auth.unit.test.ts
import { describe, it, expect, vi } from 'vitest'
import { AuthService } from '../auth.domain'
import type { ITokenRepository } from '../../ports/ITokenRepository'
import type { IUserRepository } from '../../ports/IUserRepository'

describe('AuthService', () => {
  const mockUserRepo: IUserRepository = {
    findByEmail: vi.fn(),
    save: vi.fn(),
  }
  const mockTokenRepo: ITokenRepository = {
    save: vi.fn(),
    findByRefreshToken: vi.fn(),
    revoke: vi.fn(),
  }

  it('should return access and refresh tokens on valid credentials', async () => {
    const hashedPassword = '$2b$10$validhash'
    mockUserRepo.findByEmail = vi.fn().mockResolvedValue({
      id: 'user-123',
      email: 'dev@example.com',
      passwordHash: hashedPassword,
      role: 'developer',
    })

    const sut = new AuthService(mockUserRepo, mockTokenRepo)
    const result = await sut.login('dev@example.com', 'correct-password')

    expect(result.accessToken).toBeDefined()
    expect(result.refreshToken).toBeDefined()
    expect(result.expiresIn).toBe(900) // 15 minutos
  })

  it('should throw UnauthorizedError on invalid password', async () => {
    mockUserRepo.findByEmail = vi.fn().mockResolvedValue({
      id: 'user-123',
      email: 'dev@example.com',
      passwordHash: '$2b$10$validhash',
      role: 'developer',
    })

    const sut = new AuthService(mockUserRepo, mockTokenRepo)
    await expect(sut.login('dev@example.com', 'wrong-password'))
      .rejects.toThrow('UnauthorizedError')
  })

  it('should throw UnauthorizedError on unknown email', async () => {
    mockUserRepo.findByEmail = vi.fn().mockResolvedValue(null)

    const sut = new AuthService(mockUserRepo, mockTokenRepo)
    await expect(sut.login('unknown@example.com', 'any-password'))
      .rejects.toThrow('UnauthorizedError')
  })
})
# Confirmar RED — deve falhar (AuthService nao existe ainda)
npx vitest run src/domain/__tests__/auth.unit.test.ts
# FAIL: Cannot find module '../auth.domain'

Passo 2 — Claude implementa o dominio (GREEN)

// src/domain/auth.domain.ts
import bcrypt from 'bcrypt'
import jwt from 'jsonwebtoken'
import type { IUserRepository } from '../ports/IUserRepository'
import type { ITokenRepository } from '../ports/ITokenRepository'

export class UnauthorizedError extends Error {
  constructor() { super('UnauthorizedError'); this.name = 'UnauthorizedError' }
}

export interface AuthResult {
  accessToken: string
  refreshToken: string
  expiresIn: number
}

export class AuthService {
  constructor(
    private readonly userRepo: IUserRepository,    // D: depende de interface
    private readonly tokenRepo: ITokenRepository,  // D: depende de interface
  ) {}

  async login(email: string, password: string): Promise<AuthResult> {
    const user = await this.userRepo.findByEmail(email)
    if (!user) throw new UnauthorizedError()

    const valid = await bcrypt.compare(password, user.passwordHash)
    if (!valid) throw new UnauthorizedError()

    const accessToken = jwt.sign(
      { sub: user.id, role: user.role },
      process.env.JWT_SECRET!,
      { expiresIn: '15m' }
    )
    const refreshToken = crypto.randomUUID()

    await this.tokenRepo.save({ userId: user.id, refreshToken })

    return { accessToken, refreshToken, expiresIn: 900 }
  }
}
# Confirmar GREEN — todos os testes devem passar
npx vitest run src/domain/__tests__/auth.unit.test.ts
# PASS: 3 tests passed

Passo 3 — Claude refatora para SOLID (REFACTOR)

// Melhorias SOLID aplicadas pelo Claude no refactor:
// S: extrair geração de tokens para TokenFactory (responsabilidade única)
// O: comportamento de login extensível via strategy (ex: OAuth2) sem alterar AuthService
// I: IUserRepository e ITokenRepository separados (interface segregation)

// src/domain/token.factory.ts — S: responsabilidade única de geração
import jwt from 'jsonwebtoken'

export class TokenFactory {
  createAccessToken(userId: string, role: string): string {
    return jwt.sign(
      { sub: userId, role },
      process.env.JWT_SECRET!,
      { expiresIn: '15m' }
    )
  }

  createRefreshToken(): string {
    return crypto.randomUUID()
  }
}

// auth.domain.ts atualizado — delega geração ao TokenFactory
export class AuthService {
  constructor(
    private readonly userRepo: IUserRepository,
    private readonly tokenRepo: ITokenRepository,
    private readonly tokenFactory: TokenFactory,  // D: injetado
  ) {}

  async login(email: string, password: string): Promise<AuthResult> {
    const user = await this.userRepo.findByEmail(email)
    if (!user) throw new UnauthorizedError()

    const valid = await bcrypt.compare(password, user.passwordHash)
    if (!valid) throw new UnauthorizedError()

    const accessToken = this.tokenFactory.createAccessToken(user.id, user.role)
    const refreshToken = this.tokenFactory.createRefreshToken()

    await this.tokenRepo.save({ userId: user.id, refreshToken })

    return { accessToken, refreshToken, expiresIn: 900 }
  }
}
# Confirmar que refactor nao quebrou nada
npx vitest run src/domain/__tests__/auth.unit.test.ts
# PASS: 3 tests passed (com TokenFactory mockado)

Context Window Discipline

O limite pratico do Claude Code como orquestrador é 80K tokens ativos. Acima disso, a qualidade das respostas degrada — o modelo começa a "esquecer" arquivos lidos no inicio da sessao e produz código inconsistente com o codebase.

Quando executar /compact

Threshold de tokens

Contexto ultrapassa 70K tokens durante o TDD loop

Entre fases grandes

Apos planning concluido; antes de iniciar implementacao

Pre-review

Antes de iniciar a fase de auto-review OWASP+SOLID

# Verificar uso atual de tokens (estimativa via /status se disponivel)
# No Claude Code, use o comando built-in:
/compact

# O Claude resumira o contexto atual mantendo apenas
# o essencial — arquivos modificados, decisoes tomadas,
# proximo passo. Estado de longa duracao vai para arquivos.

Template CONTEXT.md para handoff entre sessoes

Quando a sessao termina antes da feature ficar pronta, o CONTEXT.md e o passaporte da proxima sessao. Sem ele, a proxima sessao recomeça do zero.

# CONTEXT.md — Handoff de Sessao

## Feature em andamento
[Nome da feature — ex: JWT Authentication]

## Estado atual
- Fase: [Discovery | Planning | TDD Loop | Auto-review | Testing Gate | Deploy]
- Ultimo commit: [hash] — [mensagem]
- Testes passando: [X unit, Y integration, Z e2e]

## Arquivos modificados nesta sessao
- src/domain/auth.domain.ts — AuthService implementado (GREEN)
- src/domain/token.factory.ts — TokenFactory extraido (REFACTOR)
- src/ports/ITokenRepository.ts — interface criada
- src/domain/__tests__/auth.unit.test.ts — 3 testes, todos passando

## Decisoes tomadas
- Optamos por TokenFactory separado (SOLID-S) em vez de metodo privado
- JWT expira em 15min (access) e refresh e UUID v4 sem expiracao automatica
- Refresh token revogado no DB ao usar (one-time use)

## Proximo passo
Implementar o adapter HTTP: src/adapters/http/auth.routes.ts
Teste de integracao: src/adapters/__tests__/auth.integration.test.ts
Deve cobrir: POST /auth/login, POST /auth/refresh, POST /auth/logout

## Blockers / Riscos
- Nenhum blocker identificado
- Risco: JWT_SECRET nao configurado em .env.test — verificar antes dos integration tests

## Como retomar
```bash
claude
# "Leia CONTEXT.md, PLAN.md e os arquivos listados em 'Arquivos modificados'.
#  Estamos na fase de Testing Gate. Escreva o teste de integracao
#  para auth.routes.ts conforme descrito em Proximo passo."
```

Armadilhas

Tres armadilhas recorrentes no W1. Cada uma tem um padrao de sintoma, uma causa raiz e uma correcao especifica.

Armadilha 1 — Implementacao sem contexto do codebase
Sintoma: Claude gera codigo funcionalmente correto mas que duplica funcionalidade existente, usa convencoes erradas ou viola a arquitetura do projeto.
Causa: O primeiro prompt pedia implementacao direta sem dar contexto. O Claude inventou uma estrutura plausivel mas incompativel.
Correcao: Faca a Fase 1 (Discovery) obrigatoria. Prompt padrao: "Leia os arquivos relevantes e mapeie o impacto. NAO escreva codigo ainda." Codifique isso no CLAUDE.md como diretiva.
Armadilha 2 — Contexto degradado por falta de /compact
Sintoma: Nas iteracoes 4-5 do TDD loop, o Claude comeca a esquecer arquivos lidos no inicio da sessao, repete decisoes ja tomadas ou gera codigo inconsistente com o que foi implementado antes.
Causa: Contexto acima de 80K tokens sem compactacao. O modelo nao descarta tokens — eles ficam presentes mas com peso de atencao reduzido.
Correcao: Execute /compact ao cruzar 70K tokens e sempre entre fases grandes (planning → implementacao, implementacao → review). Adicione ao CLAUDE.md: "Execute /compact entre fases e quando contexto ultrapassar 70K tokens."
Armadilha 3 — Implementacao antes do teste (TDD invertido)
Sintoma: O Claude entrega codigo que funciona mas os testes escritos depois passam mesmo com bugs sutis — porque foram escritos para descrever o comportamento do codigo, nao o comportamento esperado.
Causa: O prompt nao exigiu RED primeiro. O Claude otimiza para entregar valor rapido e pula o RED naturalmente se nao houver instrucao explicita.
Correcao: Torne o RED verificavel: "Escreva o teste, execute-o, mostre a saida de falha, so entao implemente." Sem ver a saida de falha, o ciclo TDD nao ocorreu. Adicione ao CLAUDE.md como diretiva implicita de qualquer implementacao.

Hooks neste workflow

No W1 Solo, os hooks são a única camada determinística de qualidade — não há processo externo validando. Configure em .claude/settings.json:

Por que hooks aqui: No workflow solo, você é o único orquestrador. Hooks substituem o code-reviewer humano e garantem que nenhum código quebrado ou inseguro avança.

settings.json mínimo para W1

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{"type": "command", "command": "node scripts/quality-gate.mjs \"$CLAUDE_TOOL_INPUT_FILE_PATH\""}]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{"type": "command", "command": "node scripts/bash-guard.mjs"}]
      }
    ]
  }
}

O que o quality-gate.mjs verifica

GateTriggerO que bloqueia
Secret detectionqualquer Write/EditAPI keys, passwords, tokens no código
ESLint + tsc.ts/.js modificadoerros de tipo + violations de linting
vitest runqualquer source filetestes falhando após a mudança
npm auditpackage.json modificadovulnerabilidades high/critical
Limitação: Hooks garantem que os testes passam — não que foram escritos antes da implementação. O TDD order depende do CLAUDE.md e da sua disciplina. O hook fecha o gate de qualidade, não ensina o processo.

O script scripts/quality-gate.mjs está documentado em detalhe no Módulo 22 — Fundamentos.