🔌 Instalar Claude Code + Codex CLI
2 CLIs essenciais. Use plano (não API key) pra economizar.
# Claude Code
npm install -g @anthropic-ai/claude-code
claude login
# Codex CLI (OpenAI)
npm install -g @openai/codex
codex login💡 VPS sem browser?
Use OAuth headless: claude login --no-browser. Te dá URL pra abrir em outro device, retorna code.
📁 Estrutura de pastas
Layout cebola — separação clara entre contratos e implementações.
meu-agente/
├── pyproject.toml
├── CLAUDE.md # Identidade
├── README.md
├── start.sh # Wizard
├── doc/ # Specs antes de código
│ └── architecture.md
├── src/agente/
│ ├── __init__.py
│ ├── providers/ # base.py + openrouter.py
│ ├── channels/ # base.py + telegram.py
│ ├── memory/ # base.py + sqlite.py
│ ├── tools/ # base.py + shell.py + web.py
│ └── agent.py # Wire-up
├── tests/
│ └── test_smoke.py
└── .claude/skills/📜 CLAUDE.md mínimo viável
30 linhas, não 300. Cresce sob demanda.
# CLAUDE.md
## Project Overview
Agente pessoal em Python 3.11+. Telegram + OpenRouter + SQLite FTS5.
## Commands
- `./start.sh` — wizard de setup
- `python -m agente` — roda bot
- `pytest tests/ -v` — testes
## Interface Contracts
Toda dependência externa atrás de ABC:
- Provider (LLM)
- Channel (I/O humano)
- Memory (persistência)
- Tool (capacidade)
## Identity
Agente assistente pessoal. Pt-BR. Direto, sem floreios.
Confidencialidade: nunca mande dados fora sem confirmação.🔐 Wizard de credenciais (start.sh)
6 perguntas, encripta com Fernet, grava em ~/.app/.secrets.
#!/usr/bin/env bash
set -e
mkdir -p ~/.meu-agente
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
if [ ! -f ~/.meu-agente/config.json ]; then
python -m meu_agente.wizard
fi
python -m meu_agente🧪 Primeiro teste passando
pytest + asyncio. Smoke test antes do primeiro feature.
# tests/test_smoke.py
import pytest
def test_import():
import meu_agente
assert meu_agente
@pytest.mark.asyncio
async def test_provider_contract():
from meu_agente.providers.base import Provider
assert hasattr(Provider, 'chat')pyproject.toml essencial: pytest-asyncio = "*" + [tool.pytest.ini_options] asyncio_mode = "auto"
🚀 Primeira invocação do LLM
Provar que tudo conecta. 15 linhas Python e você fala com o modelo.
import httpx, asyncio, os
async def hello():
async with httpx.AsyncClient(timeout=30) as cli:
r = await cli.post(
"https://openrouter.ai/api/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_KEY']}"},
json={
"model": "anthropic/claude-haiku-4.5",
"messages": [{"role": "user", "content": "Diga oi em pt-BR."}]
}
)
print(r.json()["choices"][0]["message"]["content"])
asyncio.run(hello())💡 Por que OpenRouter
1 chave, 147 modelos. Troca de Claude pra GPT em 1 string. Excelente pra experimentar.
📝 Resumo do módulo
Próximo módulo:
2.2 — Contratos limpos (Provider/Channel/Memory/Tool)