AI Coding Guides Deep Dives
Direct Write • Exact Edit • Kernel Diff • Notebook cells • Sandbox rails

CheetahClaws: A Mixed-Mode Editing Stack with Real Guardrails

CheetahClaws does not route every file mutation through one grand edit protocol. Instead it combines straightforward whole-file writes, exact string replacement, capability-gated kernel tools, notebook cell edits, unified diffs, and path-security checks. It is less doctrinaire than Reasonix and less minimal than ADK-Rust, but also more obviously useful in day-to-day coding work.

Why It Belongs in a File-Editing Blog

CheetahClaws is interesting because it refuses to pretend there is only one way an agent should edit code. The repo keeps an older REPL-facing file tool layer, adds a newer capability-gated kernel layer, and then supplements both with notebook editing, diff tooling, checkpoint backups, and shell safety checks.

That makes it a strong contrast case. Some harnesses chase one elegant mutation idea: SEARCH/REPLACE blocks, hash anchors, AST-native rewrites, or provider-native editors. CheetahClaws goes the other direction: build several explicit mutation tools, show the diff, enforce path rules, and let the agent choose the right one.

Two Editing Planes, Not One

Plane Main files Editing style
Legacy REPL tool path tools/fs.py, tools/__init__.py Human-oriented string results, direct write/edit helpers, diff feedback, permission-mode prompts
Kernel tool path cc_kernel/tools/builtin.py, cc_kernel/tools/registry.py, cc_kernel/tools/diff_tool.py Structured dict responses, per-agent capability checks, explicit fs grants, stricter write semantics
Specialized mutation tools tools/notebook.py, checkpoint/store.py Notebook cell replacement/insert/delete plus pre-edit backups and restore snapshots
🪛

The repo chooses explicit tools over one magic matcher

This is the key framing. CheetahClaws is not trying to teach every model one house edit grammar. It gives the model whole-file write, exact-string edit, diff comparison, notebook edit, and bash-assisted mutation options, then fences them with permissions and path checks.

Legacy Read / Write / Edit: direct and very readable

The classic filesystem tools live in tools/fs.py. They are refreshingly plain:

Tool Behavior Important constraint
_read() Reads a file and returns numbered lines Errors if path is missing or is a directory
_write() Writes the whole file and returns a unified diff for updates Auto-creates parent directories; returns "No changes" if identical
_edit() Exact string replacement with optional replace_all Refuses zero or ambiguous matches and tells the model to provide a more exact block

The exact-edit behavior is stricter than it first looks. The tool normalizes line endings to count matches, preserves pure CRLF files on write-back, and rejects edits when the old string appears more than once unless the caller explicitly asks for replace_all=true.

Python
count = content_norm.count(old_norm)
if count == 0:
    return "Error: old_string not found..."
if count > 1 and not replace_all:
    return "Error: old_string appears N times..."

new_content_norm = content_norm.replace(old_norm, new_norm, 1)

After a successful edit, the tool returns a unified diff immediately. That is an underrated UX choice: the mutation surface is simple, but it still makes the change legible to both user and model.

Kernel tools: capability checks before the handler runs

The newer kernel layer is tighter. The dispatcher first checks whether the agent PID is allowed to use the named tool at all, then verifies each filesystem path against the agent's grants before invoking the handler. That turns editing from "can the current prompt call this function?" into "did the runtime explicitly grant this process write access to this path?"

Python
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)

The built-in kernel Write is also stricter than the legacy helper: it refuses to create missing parent directories automatically. That is a real design difference. The older REPL path optimizes for convenience; the kernel path optimizes for explicit authority and narrower side effects.

⚠️

There is no single canonical write path

That is both power and complexity. If you are auditing the repo, you have to understand which layer is active: legacy tool registry, kernel built-ins, or a specialized editor like notebook mutation. CheetahClaws is more transparent than magical, but it does ask you to keep the layers straight.

Diffs, notebooks, and checkpoints round out the editing story

CheetahClaws has a proper standalone diff tool in the kernel path. It can compare two files or two strings, caps output at 2 MB, and validates context-line count. That means "show me the delta" is a first-class operation, not just a side effect of a write helper.

Notebook editing is separate and direct. NotebookEdit replaces, inserts, or deletes cells in .ipynb files, supports either notebook cell IDs or cell-N shorthands, and resets execution outputs when a code cell is replaced. This is a nice sign that the repo treats coding artifacts as more than plain text files.

Finally, checkpoint storage backs up files before edits and stores snapshot metadata so a session can restore earlier states. The path naming is slightly funny (~/.nano_claude/checkpoints/), but the mechanism is real: snapshot JSON, per-file backup versions, and a size cap so giant files are skipped rather than copied blindly.

Security rails around editing

Guardrail What it does
Permission mode Write, Edit, Bash, and NotebookEdit ask for approval unless accept-all is active
allowed_root Refuses edits outside the configured root or worktree path
Credential denylist Blocks access to SSH private keys, AWS creds, GnuPG data, Docker auth, /etc/shadow, and similar secret stores
Bash hard denylist Rejects destructive commands like rm -rf /, mkfs, raw disk writes, and fork bombs even under accept-all
MCP env sanitization Prevents MCP configs from smuggling dangerous env like LD_PRELOAD or PYTHONPATH into spawned processes

The security posture is not "sandbox everything forever." It is more honest than that. The docs say the system is designed around a trusted operator on one host, then adds stronger fences when bridges, daemon mode, plugins, or web deployment enter the picture. For a personal agent harness, that is a pragmatic stance.

How it compares

Repo Main editing idea How CheetahClaws differs
ADK-Rust Thin wrappers over provider-native editing surfaces CheetahClaws keeps more local mutation logic and more runtime-side safety checks
Reasonix One strict SEARCH/REPLACE block protocol CheetahClaws spreads edits across direct write, exact string edit, diff, notebook, and shell-assisted paths
Oh My Pi Compact hashline anchors and prompt-assisted rebasing CheetahClaws is less specialized, more general-purpose, and more obviously layered with permissions and service architecture
Codex / Claude Code Patch-oriented mutation surfaces CheetahClaws feels more like a toolbox of explicit Python tools than a single patch language

What I Would Steal from It

Diffs after normal edits

Returning a unified diff as part of the normal write/edit result makes mutations much easier to audit without inventing an elaborate edit protocol.

Capability checks for the service path

The kernel dispatcher cleanly separates "can this process call the tool?" from "did the host OS allow the write?" That is exactly the right abstraction for daemonized agents.

Notebook editing as a first-class tool

Treating notebooks as structured documents instead of plain JSON text is a small but meaningful sign of maturity.

Pragmatic security docs

The repo says what is trusted, what is denied, and which env vars disable the guardrails. That clarity is better than vague "secure by default" marketing.