CheetahClaws: The Python-Native Agent OS Remix
CheetahClaws starts from a familiar ambition — "Claude Code, but open and hackable" — then keeps going. The repo mixes a readable Python REPL, a plugin-style tool registry, a capability-gated kernel, a daemon with RPC and SSE, MCP transports, bridge integrations, autonomous runners, and persistent memory. The result is less a single coding loop than a steadily expanding agent platform that still remembers its terminal roots.
What CheetahClaws is trying to be
The repo describes CheetahClaws as a fast, production-ready, Python-native personal AI assistant for any model. That is already a broader framing than "coding CLI." The top-level entrypoint exposes slash commands for MCP, plugins, memory, tasks, web mode, background agents, bridges, trading, research labs, subscriptions, TTS, voice, and daemon control. It is openly inspired by Claude Code and OpenClaw, but it is not satisfied with being a minimal clone.
Architecturally, the project feels like two systems growing into one another. The original REPL path is still there: a big user-facing CLI, direct Python tool functions, bridge integrations, and a central tool registry. On top of that sits a newer kernel and daemon layer with per-agent capabilities, JSON-RPC, SSE events, subprocess runners, and stricter built-in tools. CheetahClaws is interesting precisely because it has not chosen one side and deleted the other.
The project is an open platform first, a polished doctrine second
Many agent repos are opinionated end products: one prompt shape, one model routing philosophy, one execution model. CheetahClaws reads more like a personal agent platform under continuous expansion. That gives it reach — providers, bridges, daemon mode, memory, labs, plugins — but also means the architecture preserves multiple generations of ideas instead of collapsing them into one canonical path.
The core runtime: session-scoped context instead of global state
The most important stabilizing abstraction is RuntimeContext.
Each REPL session, bridge conversation, or daemon-originated interaction gets a
session-specific context object that holds callbacks, bridge state, web state,
plan-mode fields, proactive polling state, and the live AgentState.
That is a practical answer to a classic Python-agent problem: once a CLI grows
bridges, background threads, and multiple clients, module globals become a race.
CLI, Telegram, Slack, WeChat, or web UI routes the interaction toward a session identifier rather than mutating a single global chat object.
get_session_ctx(session_id)
Creates or returns a RuntimeContext carrying callbacks,
streaming hooks, bridge send functions, proactive timers, and plan-mode state.
The generator-style agent loop emits text, thinking, tool start/end, permission requests, and turn-done events without mixing state from other sessions.
Web sessions, bridge prompts, and proactive polling keep live hooks in memory while persistent history and memories are stored elsewhere.
| Subsystem | Where it lives | Why it matters |
|---|---|---|
| Live turn state | runtime.py |
Prevents bridges and background features from trampling each other |
| Conversation + token counters | agent.py / AgentState |
Keeps the actual LLM loop separated from transport glue |
| Durable history | session_store.py |
Moves long-term storage out of the live runtime object |
| User/project memory | memory/ |
Lets the system accumulate preferences and decisions without turning the REPL into a monolith |
Provider strategy: almost everything, from Claude to local Ollama
Provider breadth is one of the repo's main differentiators. The top-level provider registry maps named providers to API base URLs, model lists, context limits, and token-cost metadata. It supports Anthropic, OpenAI, Gemini, Kimi, Qwen, Zhipu, DeepSeek, MiniMax, Ollama, LM Studio, custom OpenAI-compatible endpoints, and a LiteLLM adapter for awkward enterprise/provider auth paths.
This matters because CheetahClaws is trying to be an alternative not just to one
vendor's coding tool, but to the assumption that a coding harness must be bound to
a single provider. Model strings can be auto-detected by family name or forced with
explicit prefixes such as ollama/qwen2.5-coder or
custom/my-model.
Closed APIs
Anthropic, OpenAI, Gemini, Moonshot Kimi, Alibaba Qwen, Zhipu GLM, DeepSeek, and MiniMax are first-class citizens in the registry.
Local model path
Ollama and LM Studio are treated as normal providers, not oddball plugins. That keeps "run it on my machine" as a mainstream workflow.
Custom compatibility
The custom/ and litellm/ routes extend coverage to
OpenAI-compatible services and enterprise auth situations that are painful to
hand-wire directly.
The multi-provider bet changes everything above it
Once a repo promises provider freedom, every other subsystem has to become more generic: prompt assembly, cost display, thinking-mode handling, permission flows, and background automation all need to survive wildly different model behavior. CheetahClaws embraces that complexity instead of shrinking back to one blessed backend.
The tool system: plugin registry on top, capability kernel beneath
There are really two tool stories in CheetahClaws. The first is the user-facing
plugin registry in tool_registry.py: each tool has a name, JSON schema,
Python callable, read-only flag, and concurrent-safety flag. Read-only tools are
cached per session, and write-like tools invalidate that cache automatically.
The second is the kernel path under cc_kernel/, where tools are registered
with explicit filesystem grants and dispatched through a capability check. That layer
introduces a more formal execution model: agent PID, tool grant, path grant, handler
dispatch, structured error slugs, and pure-ish tool responses over IPC.
Registry path
Best thought of as the REPL-era convenience layer. It exposes tools like Read, Write, Edit, Bash, NotebookEdit, Glob, web fetches, and research helpers with human-oriented string results and output truncation tuned for LLM context.
ToolDef(
name="Read",
schema=...,
func=_read_with_overflow_check,
read_only=True,
concurrent_safe=True
)
Kernel path
The newer execution plane. Tools are checked against per-agent capabilities, filesystem modes, and structured handler contracts before they run, which makes the system more suitable for daemonized multi-client use.
if not kernel.cap.check_tool(pid, tool.name):
return permission_denied
if not kernel.cap.check_fs(pid, path, mode):
return fs_denied
result = tool.handler(args, ctx)
| Question | Registry path answer | Kernel path answer |
|---|---|---|
| Who can call the tool? | Permission-mode + ask-user callback | Explicit per-agent capability grants |
| How is output shaped? | Human/LLM-friendly strings with truncation | Structured dict payloads with error slugs |
| What protects filesystem scope? | allowed_root + secret-path denylist |
Grant checks plus handler-side validation |
| Why keep both? | Fast feature growth and REPL ergonomics | Cleaner multi-agent and daemon architecture |
File editing: pragmatic, mixed, and more transparent than elegant
CheetahClaws does not force every mutation through one sacred edit protocol.
The legacy tools/fs.py path provides numbered reads, whole-file writes,
exact-string edits with optional replace_all, CRLF normalization, and
immediate unified-diff feedback. Notebook editing lives in its own tool and directly
rewrites Jupyter JSON. The kernel layer adds separate Read, Write, and Diff tools with
capability checks and stricter path handling.
That mixed approach is less aesthetically pure than a single SEARCH/REPLACE doctrine, but it is very practical. A user gets straightforward whole-file overwrites, exact edit retries, notebook cell mutation, path-based diffing, and shell escape hatches — all with multiple safety layers rather than one universal parser.
Direct write path
Legacy Write creates parent directories automatically and returns
a unified diff when modifying existing files. It is the "just do the thing"
mutation path.
Exact string edit path
Legacy Edit does exact-match replacement, refuses ambiguous matches
unless replace_all=true, and preserves CRLF files instead of silently
converting them.
Kernel write path
The kernel built-ins are stricter: path must already exist inside granted scope, parent directories are not auto-created, and every access is capability checked.
Notebook path
NotebookEdit targets notebook cells directly, with replace/insert/delete
modes and execution output resets for code cells.
This is a toolbox architecture, not a single edit religion
Compare CheetahClaws to Dirac or Reasonix and the contrast is obvious. Those systems make a very strong claim about how code should be changed. CheetahClaws instead says: here are several mutation surfaces, here are the safety rules around each one, and here is enough structure for the agent to choose among them.
Security boundaries: strong patches on top of a trusted-operator model
The security documentation is unusually candid about its starting assumption: one trusted operator on one host. Inside that boundary the defaults favor usability. Once the repo crosses into remote bridges, daemon mode, plugins, or multi-user web deployments, the hardening turns on: bash hard denylist, credential-path denylist, CSRF for the web UI, owner-bound terminal sessions, plugin kill switches, and MCP environment sanitization.
| Surface | Default posture | Tightening lever |
|---|---|---|
| Bash tool | Permission-gated plus hard denylist | Patterns like rm -rf /, mkfs, fork bombs, and raw disk writes are refused outright |
| File I/O | CWD-rooted plus secret-path denylist | allowed_root for stricter scoping; CHEETAHCLAWS_FS_NO_SANDBOX=1 to override |
| MCP | Dangerous env vars stripped before spawn | CHEETAHCLAWS_MCP_TRUST_ENV=1 for power users |
| Web UI | JWT cookie, CSRF, owner-bound terminal sessions | --no-auth exists, but the docs treat it as testing-only |
| Plugins | Arbitrary Python, no sandbox | CHEETAHCLAWS_DISABLE_PLUGINS and allowlists as damage-control switches |
The interesting architectural point is that CheetahClaws is not pretending these are hypothetical concerns. The repo has already accumulated the scars that create hardening features: bridge command abuse, token leakage risk, web auth, plugin trust, path escape, and daemon multi-tenancy.
Daemon, kernel, and web mode: where it turns into an agent service
The daemon layer is where CheetahClaws stops looking like "just a terminal app."
The server exposes /rpc, /events, /healthz,
and /readyz, keeps shared daemon state, runs authenticated JSON-RPC
methods, and streams asynchronous notifications over SSE. The permissions store even
has its own janitor thread. That is service architecture, not incidental glue.
Web mode runs the chat UI in a background thread from the REPL path, while the daemon can supervise runner subprocesses and bridge methods in a more controlled environment. This split means the project can act as a personal CLI, a long-lived background service, or a remotely accessed agent endpoint depending on which layer you turn on.
Why the daemon matters
Once RPC, SSE, and authenticated originators exist, agent operations can become composable service methods rather than special-case slash commands tied to one TTY.
Why the web mode matters
Starting the web server in the background from inside the REPL preserves the "one tool, many surfaces" philosophy. The browser is a client of the agent, not a separate product.
Autonomy, subagents, and memory: the repo's platform ambitions
CheetahClaws includes several forms of delegation and long-lived work. Built-in subagent
definitions include general-purpose, coder, reviewer, researcher, and tester personas.
User and project-level agent definitions can be loaded from Markdown. Autonomous runners
execute task templates over multiple iterations, auto-approve permissions in autonomous
mode, and persist per-iteration summaries under ~/.cheetahclaws/agents/.
Memory is split cleanly: session history goes to SQLite with FTS5 search, while long-term memory consolidation extracts a capped number of durable user/project facts from longer sessions. That is a practical compromise. Instead of pretending every message is semantic memory, the repo keeps a searchable transcript store and a much smaller, AI-curated memory layer on top.
Subagents
Built-in task personas plus user/project Markdown definitions. The repo treats specialized agents as configurable assets, not one-off prompts.
Autonomous runners
Template-driven loops with history logging, summary emission, stagnation detection, and optional subprocess supervision on POSIX.
Session store
SQLite + WAL + FTS5. Durable search across past conversations without dragging raw transcripts into the current context window.
Memory consolidation
Hard-capped extraction of durable preferences and project facts, rather than unlimited "memory" bloat.
How CheetahClaws compares to nearby agents in this repo set
| Agent | Main architectural move | How CheetahClaws differs |
|---|---|---|
| Claude Code | Production coding agent tightly coupled to Anthropic | CheetahClaws chases openness, Python readability, and provider freedom instead of one-vendor polish |
| OpenCode | Client-server runtime with strong architectural separation | CheetahClaws reaches toward a similar service model, but keeps far more legacy REPL DNA in the tree |
| Reasonix | Single-provider architecture optimized around one cache behavior | CheetahClaws chooses provider breadth and feature surface over a single narrow invariant |
| Dirac | Highly opinionated edit engine and checkpoint discipline | CheetahClaws uses a more pluralistic toolbox of file mutation surfaces |
| Hermes | Always-on, self-improving, multi-surface agent platform | CheetahClaws feels closer to Hermes than most coding CLIs do, but with more explicit coding-tool lineage |
Design tradeoffs
What works
The repo is ambitious without being opaque. The Python-first implementation makes major subsystems readable, the provider layer is broad, the daemon path is real, and the security docs are refreshingly concrete about what is and is not trusted.
What it costs
CheetahClaws carries multiple generations of architecture at once. That gives it feature range, but it also means there is no single, clean mental model for "the" tool path or "the" edit system.
The central tradeoff: breadth over singular elegance
If you want the cleanest possible architecture, CheetahClaws will frustrate you. The repo has a legacy filesystem tool layer, a kernel tool layer, notebook editing, daemon RPC, bridges, plugins, memory, trading, labs, and web mode all in the same project. But if you want a readable open agent that keeps absorbing useful capabilities instead of trimming itself to a minimalist manifesto, that sprawl is exactly the point.
My main takeaway
CheetahClaws is one of the clearest examples in this repo set of an agent harness evolving into a personal agent operating system. The code is still recognizably a terminal assistant, but the daemon, kernel, bridges, autonomous runners, MCP support, memory, and web surfaces keep pushing it toward a general agent runtime.
Further reading
Source material
GitHub:
SafeRL-Lab/cheetahclaws
Website:
cheetahclaws.github.io
Security guide:
docs/guides/security.md
Install: pip install cheetahclaws or
python cheetahclaws.py
Key local files: runtime.py,
tool_registry.py, tools/fs.py,
cc_kernel/tools/, cc_daemon/server.py,
multi_agent/subagent.py