CodeMini is a terminal-based AI agent that talks to any OpenAI-compatible LLM and streams responses straight into your shell. It's the foundation for a fully-fledged coding assistant: today it does streaming chat over a clean, event-driven agent loop; the roadmap below covers where it's headed (tools, multi-turn sessions, file editing, and more).
⚠️ Status: work in progress. The core agent loop and streaming client are functional. Tool use, interactive sessions, and code-editing capabilities are not implemented yet.
- 🖥️ Single-shot CLI — ask a question, get a streamed answer
- 🔌 Provider-agnostic — works with any OpenAI-compatible API (OpenRouter, OpenAI, local servers, etc.) via
BASE_URL/API_KEY - 📡 Real-time streaming — tokens render as they arrive using Rich
- 🧱 Event-driven architecture — the agent emits a typed stream of events (
agent_start,text_delta,text_complete,agent_error,agent_end), keeping the LLM, agent, and UI layers cleanly decoupled - ♻️ Resilient client — automatic retries with exponential backoff on rate-limit and connection errors
- 📊 Token accounting — tracks prompt / completion / cached token usage per response
CodeMini is split into three decoupled layers connected by a stream of events:
┌───────────────────────────────────────────────┐
user input ──► │ main.py (Click CLI → CLI class) │
└───────────────────────┬───────────────────────┘
│ message
▼
┌───────────────────────────────────────────────┐
│ agent/agent.py (Agent — async agentic loop) │
│ emits AgentEvent stream │
└───────────────────────┬───────────────────────┘
│ StreamEvent
▼
┌───────────────────────────────────────────────┐
│ client/llm_client.py (OpenAI-compatible) │
│ streaming + retries + token usage │
└───────────────────────────────────────────────┘
AgentEvents ──► ui/renderer.py (Rich console rendering)
| Path | Responsibility |
|---|---|
main.py |
Click entry point. CLI class runs a single message through the agent and renders the stream. |
agent/agent.py |
Agent — the async agentic loop. Wraps the LLM client and yields typed AgentEvents. Async context manager that owns client lifecycle. |
agent/events.py |
AgentEvent / AgentEventType — the typed event protocol between the agent and the UI. |
client/llm_client.py |
LLMClient — async OpenAI-compatible wrapper. Handles streaming, retries with exponential backoff, and error classification. |
client/response.py |
Stream-layer dataclasses: StreamEvent, StreamEventType, TextDelta, TokenUsage. |
ui/renderer.py |
Renderer — renders streamed deltas and errors to the terminal via Rich. |
Agent.run()yieldsagent_start, then drives_agentic_loop()._agentic_loop()callsLLMClient.chat_completion(), which streamsStreamEvents from the provider.- Each
TEXT_DELTAis translated into anAgentEvent.text_deltaand forwarded to the renderer in real time. - On completion, the agent emits
text_completethenagent_end; errors surface asagent_error.
- Python 3.10+ (uses
X | Yunion syntax andmatch-friendly typing) - An API key for any OpenAI-compatible endpoint
Dependencies (see requirements.txt):
openai— async clientclick— CLI frameworkrich— terminal renderingtiktoken— tokenization (planned use)python-dotenv—.envloading
git clone <your-repo-url> codemini
cd codemini
python -m venv .venv
.\.venv\Scripts\Activate.ps1 # Windows (PowerShell)
# source .venv/bin/activate # macOS / Linuxpip install -r requirements.txtCreate a .env file in the project root:
BASE_URL=https://openrouter.ai/api/v1
API_KEY=your-api-key-here
BASE_URLandAPI_KEYare read at runtime byLLMClient. Any OpenAI-compatible endpoint works — OpenRouter, OpenAI directly, or a local server (e.g. Ollama, LM Studio). The default model is set inclient/llm_client.py.
Ask a single question (quote the prompt so it arrives as one argument):
python main.py "tell me about llms"The answer streams to your terminal as it's generated.
| Setting | Where | Notes |
|---|---|---|
BASE_URL |
.env |
API base URL of your provider |
API_KEY |
.env |
API key for the provider |
| Model | client/llm_client.py (chat_completion) |
Currently hard-coded; will move to config |
| Max retries | client/llm_client.py (LLMClient._max_retries) |
Defaults to 3, with exponential backoff |
CodeMini is early. Planned work toward a Claude Code–style experience:
- Interactive REPL — multi-turn conversation with persistent history
- Tool / function calling — let the agent run shell commands, read/write files, and search
- File editing — apply diffs and edits to the working tree
- Configurable model & provider — move the model out of code into config/flags
- System prompts & context injection — project-aware behavior
- Token usage display — surface the already-tracked
TokenUsagein the UI - Tests — unit coverage for the agent loop and client
- Packaging — installable
codeminiconsole script
See LICENSE.
