AI Coding Guides Deep Dives
Python-native • Multi-provider • Daemon + kernel • MCP • Autonomous loops

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.

(Alright, ad over. Back to the serious technical analysis.)

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.

1
User or bridge turn arrives

CLI, Telegram, Slack, WeChat, or web UI routes the interaction toward a session identifier rather than mutating a single global chat object.

2
get_session_ctx(session_id)

Creates or returns a RuntimeContext carrying callbacks, streaming hooks, bridge send functions, proactive timers, and plan-mode state.

3
Agent loop runs against that context

The generator-style agent loop emits text, thinking, tool start/end, permission requests, and turn-done events without mixing state from other sessions.

4
Context survives long enough for bridges and web mode

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