Clone do Claude Code em Java 25 — agente CLI fino sobre a Messages API da Anthropic (ou Ollama local). Exercício de arquitetura sobre Java 25: records, sealed types, Structured Concurrency (preview) e AOT class loading usados no código; outros JEPs (FFM, Scoped Values, Shenandoah geracional, Stable Values) avaliados — o que é usado vs. avaliado está detalhado na doc de arquitetura.
Arquitetura, decisões de design e o que quebrou no caminho: ARCHITECTURE.md.
- Java 25 (Temurin) — via SDKMAN:
sdk install java 25.0.3-tem - Gradle 9.x — via SDKMAN:
sdk install gradle 9.5.1 - Ollama 0.24+ rodando localmente (default em
http://host.docker.internal:11434para WSL2 alcançar o host Windows) - Pelo menos um modelo baixado, ex.:
ollama pull gemma2:2b
./gradlew buildBuild executa: compilação com --enable-preview, testes JUnit 5, JaCoCo report e verificação de cobertura ≥ 95% em todos os 6 counters (INSTRUCTION, BRANCH, LINE, COMPLEXITY, METHOD, CLASS). Qualquer queda abaixo de 95% quebra o build.
REPL interativo (cores + edição de linha):
./scripts/run.shUse ./scripts/run.sh, não ./gradlew run, para o REPL: a tarefa run do Gradle redireciona stdin/stdout por pipes, então o JLine não consegue um terminal de sistema e cai para um "dumb terminal" (sem cores, edição de linha quebrada, barra de progresso do Gradle misturada à saída). O run.sh faz installDist e executa o binário direto no terminal real — como o cargo run. Aceita as mesmas flags: ./scripts/run.sh --accent roxo.
One-shot (sem REPL) — útil em pipelines e smoke tests (aqui o terminal dumb não importa):
./gradlew run --quiet --args='--prompt "Responda em PT-BR: o que é Java?"'Flags úteis:
--model gemma2:2b(default) — qualquer modelo conhecido pelo Ollama.--ollama-url http://...— endpoint custom; defaulthttp://host.docker.internal:11434.--num-gpu 0(default) — CPU-only, contornando a VRAM apertada da GTX 750 Ti.--tools— habilita Read/Write/Bash/Glob/Grep (apenas em modelos que suportam tools, ex.: llama3.2:3b; gemma2:2b rejeita com HTTP 400).--permission-mode AUTO_ACCEPT— pula o prompt y/n (necessário para--promptcom tools).
Implementado em 11 etapas — cada uma é um commit verde com build passando e cobertura ≥95%:
- Skeleton Gradle + Picocli + JLine REPL
- Cliente Anthropic conectado
- Tool dispatch + Read/Write tools
- BashTool com timeout
- Streaming SSE com render incremental
- Glob + Grep (regex Java)
- Permission modes + Gate
- Compaction de contexto
- AOT cache + medições
- Structured Concurrency em tools paralelos
- Bridge para ripgrep (subprocess
rg --json; binding FFM nativo adiado)
Setup (uma vez):
./gradlew installDist
./scripts/aot-record.sh # produces agent.aotconf
./scripts/aot-create.sh # produces agent.aotUso diário:
./scripts/aot-run.sh "$@"Benchmark de startup (hyperfine necessário):
./scripts/aot-bench.shMeta de startup: < 100ms cold-start com cache, vs ~300ms sem.