Let Claw Write Code: exec, Patches, and Approvals
💡 One-sentence summary: write code with OpenClaw and build a local coding workflow where "commands can run, patches can be reviewed, and a human gates what lands" — exec runs commands, apply_patch produces patches, and the approval policy guards the boundary.
What You'll Be Able to Do After This Tutorial
- Have Claw actually run commands like
npm testin your workspace, and understand why they fail. - Have Claw use
apply_patchto modify multiple files and code sections at once, producing structured patches. - Configure the
tools.exec.modeapproval policy so high-risk commands run only after being confirmed one by one. - Enable Code Mode when needed, letting the model write small JavaScript programs to search and invoke tools.
Why OpenClaw Instead of Web-based AI?
| Capability | Web-based AI | OpenClaw |
|---|---|---|
| Running commands | ❌ Can only give suggestions; you copy and paste yourself | ✅ exec Executes within the allowed scope of the selected host or sandbox file system |
| Multi-file changes | ❌ One file pasted at a time, easy to miss things | ✅ apply_patch One patch strings together additions, edits, moves, and deletions |
| Safety gating | ❌ No local policy to speak of | ✅ Three layers of gating: policy + allowlist + optional user approval |
| Self-hosting | ❌ Code must be uploaded to someone else's server | ✅ Gateway runs on your machine; commands stay in the local workspace |
Your Current Pain Points
- Every time you ask AI to change code, it's "paste code → copy back into the editor → run tests manually," shuttling back and forth.
- The AI's changes are scattered across multiple conversation segments, and you don't know which files it actually modified.
- You want AI to run commands directly, but you're afraid it will execute something it shouldn't.
When to Use This Approach
- Fixing a bug requires changing source code, adding tests, and running a verification pass all at once.
- A refactoring involves moving or renaming files across multiple files.
- You want both "running commands" and "modifying files" to happen on your own machine, with every step reviewable.
🎒 Before You Start
- Gateway is already running on your machine and the model provider is connected (Node 24.16.0+ or 26.1.0+).
- Think through your workspace boundaries:
execexecutes within the allowed scope of the selected host or sandbox file system, and commands can create, edit, and delete files. - Set the approval bar: OpenClaw 2.0 approvals bind to the exact request, command, session, and person — what's approved is "this one command this one time," not a blanket pass for the whole tool.
Follow Along
Step 1: Run Commands with exec
Why: let Claw run commands first — that's the foundation for the code changes and verification that follow.
Say to Claw directly:
Run npm test in the workspace, and summarize the failed test names and error messages for me.You should see: foreground commands return output directly once completed. Only when exec indicates the command is still running and provides sessionId should you take over with process — an ID printed by the command itself is just ordinary output, not a process handle. When a command fails, the message field carries a brief diagnosis, separate from the command output in aggregated.
Step 2: Generate and Apply Patches
Why: structured patches are more centralized and reviewable than "rewriting files by concatenating strings," and can cover multiple files at once.
Say to Claw:
Use apply_patch to fix the tests that just failed: change foo in src/index.ts from 1 to 2,
and add an assertion in tests/foo.test.ts.You should see: Claw calls apply_patch, which takes a single required input parameter, with the patch format as follows:
*** Begin Patch
*** Add File: path/to/file.txt
+line 1
+line 2
*** Update File: src/app.ts
@@
-old line
+new line
*** Update File: src/old-name.ts
*** Move to: src/new-name.ts
*** End of File
*** Delete File: obsolete.txt
*** End PatchThe corresponding JSON call looks like:
{
"tool": "apply_patch",
"input": "*** Begin Patch\n*** Update File: src/index.ts\n@@\n-const foo = 1\n+const foo = 2\n*** End Patch"
}*** Move to: is written on the line after the corresponding *** Update File: header; *** End of File marks that the hunk extends to the end of the file. Patch paths support both relative paths (relative to the workspace directory) and absolute paths.
::: Tip 💡 This is the unique value of OpenClaw apply_patch is a subtool of exec and is enabled by default. tools.exec.applyPatch.workspaceOnly defaults to false; setting it to true restricts patches to the workspace; you can also use tools.exec.applyPatch.allowModels to limit which models can use it. Note: setting tools.exec.mode to "full" does not lift this workspace boundary. :::
Step 3: Approve before landing
Why: the command is about to actually modify your machine, so a human signs off at this step.
High-risk commands go through approval before execution: exec approval is a three-layer check of policy + allowlist + (optional) user approval, and a command runs only if all three agree. Patch writes do not go through this approval panel; instead they are constrained by tool policy, workspaceOnly, and the session permission mode (full lifts restrictions, guarded/workspace tighten them, and read-only withholds the tool entirely).
You should see: choosing Allow Once on the approval panel (or pressing Command-Return) authorizes only this single execution; Always Allow Here appears only when the policy allows persistent approvals, and confirming it saves a persistent allow rule bound to the exact command arguments and the working directory at approval time.
Step 4: Configure the approval policy
Why: the default policy may not match your standards, so pin it down with configuration fields.
Use tools.exec.mode in the configuration to set the main policy:
| Value | Behavior |
|---|---|
deny | Blocks host exec |
allowlist | Only runs commands in the allowlist, without asking |
ask | Allowlist policy + ask on miss |
auto | Runs immediately on a hit; on a miss you can allow (once), deny (reason returned to the agent), or ask (manual approval) |
full | Bypasses the regular policy prompt |
Companion fields: exec.ask (off/on-miss/always, default off), askFallback (fallback when no UI is reachable or on timeout, defaulting to deny), tools.exec.strictInlineEval (classifies inline evaluation forms like python -c and node -e as requiring approval), tools.exec.commandHighlighting (affects only approval panel highlighting).
You should see: after changing the configuration, the effective policy takes the stricter of tools.exec.* and the approvals default—approvals only tighten, never loosen, the policy derived from configuration.
Step 5: Enable Code Mode when needed
Why: with many tools, the model faces many schemas too; Code Mode lets it write small JavaScript programs to search, describe, and invoke the tool catalog.
How to enable: tools.codeMode defaults to the "auto" tier and takes effect only for models marked as Code Mode preferred; choose the global setting in Settings → Agents & Tools → Labs → Code Mode, and you can also activate overrides at the global / agent / model levels.
You should see: once enabled, the model sees only a few tools such as exec and wait, and exec accepts a JSON { code } payload—note that the command here is a JavaScript alias for code, not a shell command.
📋 Magic Prompt
🔧 Run tests and fix
Expected result: Claw first runs the tests to locate failures, then fixes them with patches, never touching paths outside the workspace.
Role: local coding assistant
Task: run npm test in the workspace, find the failing tests, and fix the source code or tests with apply_patch
Input information:
### Required ###
【Error messages of the failing tests】
### Optional ###
【List of files that must not be modified?】
Output specification: first give a one-sentence reason for the failure, then the patch content, and finally rerun the tests and paste the results
Constraints:
✅ Use only apply_patch to modify files
✅ Keep patch paths inside the【workspace directory】
❌ Do not rewrite entire files with exec
❌ Do not modify any path outside the workspace🚀 Refactoring move
Expected result: renaming and reference updates completed in a single patch.
Role: refactoring assistant
Task: rename src/old-name.ts to src/new-name.ts and update all references
Input information:
### Required ###
【Old file path】【New file path】
### Optional ###
【Directory scope that needs synchronized updates?】
Output specification: one apply_patch patch, using Move to to complete the rename
Constraints:
✅ Put the rename and reference updates in the same patch
✅ Run a build once afterward to verify
❌ Do not leave the old file behind
❌ Do not modify unrelated filesCheckpoint ✅
- Did the command really finish? On headless node hosts, commands terminated by system signals include the signal name in the result; having printed output before termination does not mean the command succeeded.
- Should long tasks run in the background? On Linux, background commands managed by the Gateway can enable durable execution and survive Gateway restarts.
- Is there enough memory? On Linux, Gateway-managed exec has a default memory limit: the smaller of one quarter of host memory (or the cgroup constraint) and half of the memory remaining after the Gateway's own resident usage, with no configuration needed.
Pitfall reminders
execis a mutable shell surface: disablingwrite,edit, andapply_patchdoes not makeexecread-only. Don't rely on "turning off tools" as a fallback—configure a sandbox when one is needed.- Remote
host=nodeexecution goes through synchronoussystem.runand does not create aprocesssession; whenprocessis forbidden, local exec runs synchronously, ignoringyieldMsandbackground, and durable execution is rejected. tools.fs.workspaceOnlyandtools.exec.applyPatch.workspaceOnlyeach independently includeapply_patch; clearing one may leave the other still in effect.
Lesson summary
Writing code with OpenClaw, in this lesson you have completed the full chain: exec runs commands in the local workspace and brings back failure diagnostics, apply_patch modifies multiple files at once with structured patches, the approval policy (tools.exec.mode + allowlist + user confirmation) guards high-risk commands, and Code Mode gives the model a cheaper invocation path when there are many tools. Patch writes do not go through the approval panel; they are constrained by workspaceOnly, the session permission mode, and sandbox boundaries—the two tracks each govern their own domain, so don't mix them up.
Next lesson preview
With the code changed, the next step is to have Claw watch the repository: GitHub on duty: PR summaries and automated issue handling. To tighten tool permissions, read Security hardening (part two): tool permissions and sandboxes; to run coding with more economical domestic models, see Integrating DeepSeek: hands-on configuration for the V4 series models.