A production-grade autonomous coding agent, rebuilt in Python.
Inspired by Claude Code, fully open-source.
Claude Code proved that an AI agent can be a real pair programmer β reading your codebase, running commands, editing files, and looping until the job is done. But it's closed-source, Node.js-only, and tightly coupled to Anthropic's platform.
Open Claude Python asks: what would it take to build that same experience, in Python, with public data and open protocols?
The answer is an architecture centered around a powerful agentic tool loop β stream LLM responses, detect tool calls, execute them, feed results back, and repeat β combined with a permission system, memory, MCP protocol support, and a rich TUI.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Textual TUI β
β (Rich terminal interface) β
ββββββββββββββββ¬βββββββββββββββββββββββββββββ¬βββββββββββββββββββ€
β Slash Cmds β Permission Dialogs β Design System β
β /help /bug β allow / deny / ask β tokens & theme β
ββββββββββββββββ΄βββββββββββββββββββββββββββββ΄βββββββββββββββββββ€
β Query Engine β
β stream β parse β tool_use β execute β loop β
β (multi-turn agentic core, up to N turns) β
ββββββββββββ¬βββββββββββ¬ββββββββββββ¬βββββββββββ¬ββββββββββββββββββ€
β Tools β MCP β Memory β Hooks β Coordinator β
β Read β proto β session β pre/postβ multi-agent β
β Write β client β auto β tool β orchestration β
β Edit β server β extract β notif β β
β Bash β β dream β β β
β Grep β β β β β
β Glob β β β β β
β Web* β β β β β
ββββββββββββ΄βββββββββββ΄ββββββββββββ΄βββββββββββ΄ββββββββββββββββββ€
β Services Layer β
β API Client β OAuth β Settings β Compact β Session Memory β
β AutoDream β Extract Memories β Policy Limits β Analytics β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Anthropic SDK (async) β
β streaming + tool_use + extended thinking β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The heart of the system. The QueryEngine runs a multi-turn loop:
- Stream an LLM response with tool definitions attached
- Parse content blocks β text, thinking, tool_use
- Execute each tool call (with permission checks)
- Feed tool results back into the conversation
- Repeat until
end_turnor max turns reached
Each turn yields StreamEvent objects so the UI can render in real-time.
Every tool inherits from Tool (ABC) and implements:
class MyTool(Tool):
name = "MyTool" # model-facing identifier
input_schema = MyInput # Pydantic model for validation
description = "..." # included in API tool definition
async def call(self, input_data: MyInput) -> str:
... # execute and return result stringBuilt-in tools: Read, Write, Edit, Bash, Grep, Glob, WebFetch, WebSearch, NotebookEdit, AgentTool (sub-agent spawning), MCPTool (proxy to MCP servers).
Before any tool executes, it passes through a multi-stage permission pipeline:
Rule Parser β Auto Mode State β Classifier β Interactive Ask β Execute / Deny
Rules come from .claude/settings.json, support glob patterns, and can be set to allow, deny, or ask per tool and path.
Three layers of persistent memory:
| Layer | Purpose | Trigger |
|---|---|---|
| Session Memory | Auto-summarize current conversation | After N messages |
| Memory Extract | Extract key facts to markdown files | Background, periodic |
| AutoDream | Consolidate memories across sessions | Time-gated (24h) + session threshold |
All memories stored as markdown with frontmatter in .claude/memory/.
Full Model Context Protocol support β connect to external tool/data servers, authenticate via OAuth, and proxy tool calls transparently.
| Layer | Choice | Why |
|---|---|---|
| CLI | Typer | Type-safe CLI with auto-docs |
| TUI | Textual | Async terminal UI framework |
| Output | Rich | Beautiful terminal formatting |
| LLM | anthropic | Official async SDK, streaming + tool_use |
| Schema | Pydantic v2 | Input validation, JSON schema generation |
| MCP | mcp | Model Context Protocol client/server |
| HTTP | httpx | Async HTTP with retries |
| Storage | keyring | OS-level secure credential storage |
| I/O | aiofiles | Async file operations |
src/open_claude/
βββ query/ # Core agentic engine
β βββ engine.py # QueryEngine β stream + tool loop
β βββ streaming.py # SSE stream parser
β βββ message_builder.py # Message normalization
β βββ types.py # StreamEvent, TokenUsage, QueryResult
βββ tools/ # Tool implementations
β βββ base.py # Tool ABC + registry
β βββ shared/ # Shared tool utilities
βββ components/ # Textual UI components
β βββ ui/ # Chat app, message widgets
β βββ permissions/ # Permission dialogs
β βββ design_system/ # Design tokens & theme
βββ services/ # Core services
β βββ api/ # API client, retry, errors
β βββ compact/ # Context compression
β βββ session_memory/ # Auto session summarization
β βββ auto_dream/ # Cross-session memory consolidation
β βββ extract_memories/ # Memory extraction
β βββ mcp/ # MCP server management
β βββ settings/ # Settings loader
βββ commands/ # Slash commands
βββ context/ # Prompt building, git context, CLAUDE.md
βββ coordinator/ # Multi-agent orchestration
βββ hooks/ # Hook system (pre/post tool)
βββ schemas/ # Pydantic data schemas
βββ utils/
β βββ permissions/ # Permission pipeline
β βββ memory/ # Memory file management
β βββ mcp/ # MCP utilities
βββ constants/ # Prompts, defaults
- Python 3.12+
- uv (recommended) or pip
# Clone
git clone https://github.com/your-org/open-claude-python.git
cd open-claude-python
# Install dependencies
uv sync
# Set your API key
export ANTHROPIC_API_KEY="sk-..."
# Launch
uv run claude-pyimport asyncio
from anthropic import AsyncAnthropic
from open_claude.query.engine import QueryEngine
async def main():
client = AsyncAnthropic()
engine = QueryEngine(client)
messages = [{"role": "user", "content": "Read pyproject.toml and summarize it"}]
async for event in engine.query_with_tool_loop(messages, tools=my_tool_defs, tool_executor=executor):
if event.type == "text":
print(event.content, end="", flush=True)
asyncio.run(main())# Install with dev dependencies
uv sync --group dev
# Run tests
uv run pytest
# Type check
uv run mypy src/open_claude
# Lint
uv run ruff check src/open_claude
# Format
uv run ruff format src/open_claude~11,000 lines of Python across 153 files. Benchmarked against the original Claude Code (TypeScript) with 53+ tools, 87+ commands, and ~148 component files.
Detailed progress docs:
docs/base.md
| Module | Status | Completion | Details |
|---|---|---|---|
| Context Builder | Mostly done | 75% | CLAUDE.md, git context, environment, prompt assembly |
| Permission System | Partial | 55% | Pipeline, rules, interactive UI; missing AI classifier & remote approval |
| CLI | Partial | 60% | Typer app, MCP/memory sub-apps; missing 79+ commands |
| MCP Protocol | Partial | 50% | Connection, config, auth, 3 transports; missing enterprise controls |
| LLM Query Engine | Partial | 45% | Agentic loop, streaming, multi-provider; missing concurrent tool orchestration |
| TUI (Textual) | Partial | 40% | Chat app, message widgets, permissions; missing design system & Markdown |
| Config System | Partial | 40% | 3-layer settings; missing 2 layers + enterprise policy |
| Tools | Partial | 30% | 7/53+ tools done; core file ops covered |
| Hooks | Skeleton | 5% | Only tool_permission context factory; full lifecycle system missing |
| Memory | Skeleton | 0% | All directories empty -- file memory, AutoDream, session memory |
| Advanced Features | Not started | 0% | Coordinator, Skills, Plugins, Vim, Voice, SSH, Proactive, etc. |
Done β core file operations and MCP proxy:
| Tool | File | Notes |
|---|---|---|
Read |
file_read_tool/ |
File read with offset/limit, Jupyter notebook support |
Write |
file_write_tool/ |
Create/overwrite, auto-mkdir |
Edit |
file_edit_tool/ |
Exact string replacement, uniqueness check, replace_all |
Bash |
bash_tool/ |
Subprocess execution, timeout, background mode, dangerous command block |
Glob |
glob_tool/ |
Pattern matching, mtime sort, VCS dir exclusion |
Grep |
grep_tool/ |
ripgrep binary + Python fallback, multi output mode, context lines |
MCPTool |
mcp_tool/ |
Proxy to MCP servers, JSON SchemaβPydantic conversion |
Skeleton (empty directory):
| Tool | Priority |
|---|---|
WebFetch |
P0 |
WebSearch |
P0 |
NotebookEdit |
P0 |
AgentTool (sub-agent) |
P1 |
Not started (42+ tools): EnterPlanMode/ExitPlanMode, EnterWorktree/ExitWorktree, TodoWrite, TaskCreate/Get/Update/List/Stop, ListMcpResources, ReadMcpResource, AskUserQuestion, CronCreate/Delete/List, TeamCreate, SendMessage, LSPTool, SleepTool, SkillTool, PowerShellTool, ToolSearchTool, ConfigTool, etc.
| Status | Commands |
|---|---|
| Done | /help, /clear, /commit, /config, /cost, /mcp, /permissions |
| Stub | /compact (command exists, but compact service not implemented) |
| Missing | /model, /diff, /doctor, /init, /login, /memory, /plugin, /fast, /plan, /export, /hooks, /buddy, /agents, /bridge, /vim, /voice, etc. |
| Gap | Impact | Priority |
|---|---|---|
Tool concurrent orchestration (partitionToolCalls) |
All tools run serially; TS runs read-only tools in parallel | P0 |
Context compaction (compact) |
No auto-compression when nearing token limit | P0 |
| Memory system (entire) | No file memory, no AutoDream, no session memory | P1 |
AI Bash classifier (yoloClassifier) |
No auto-safety-classification of shell commands | P1 |
| Hooks lifecycle (20+ events) | No pre/post tool hooks, no input/output modification | P1 |
| Agent Tool (sub-agent spawning) | No multi-agent delegation | P1 |
| Multi-agent coordinator | No swarm/parallel agent execution | P2 |
Context Builder ββββββββββββββββββββ 75%
Permission ββββββββββββββββββββ 55%
CLI ββββββββββββββββββββ 60%
MCP ββββββββββββββββββββ 50%
Query Engine ββββββββββββββββββββ 45%
TUI ββββββββββββββββββββ 40%
Config ββββββββββββββββββββ 40%
Tools ββββββββββββββββββββ 30% (7/53+)
Hooks ββββββββββββββββββββ 5%
Memory ββββββββββββββββββββ 0%
Advanced ββββββββββββββββββββ 0%
Contributions welcome β see docs/base.md for the full feature-by-feature matrix.
MIT
