Skip to content

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 test in your workspace, and understand why they fail.
  • Have Claw use apply_patch to modify multiple files and code sections at once, producing structured patches.
  • Configure the tools.exec.mode approval 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? ​

CapabilityWeb-based AIOpenClaw
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 ​

  1. Gateway is already running on your machine and the model provider is connected (Node 24.16.0+ or 26.1.0+).
  2. Think through your workspace boundaries: exec executes within the allowed scope of the selected host or sandbox file system, and commands can create, edit, and delete files.
  3. 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:

text
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:

text
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:

text
*** 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 Patch

The corresponding JSON call looks like:

json
{
  "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:

ValueBehavior
denyBlocks host exec
allowlistOnly runs commands in the allowlist, without asking
askAllowlist policy + ask on miss
autoRuns immediately on a hit; on a miss you can allow (once), deny (reason returned to the agent), or ask (manual approval)
fullBypasses 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.

text
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.

text
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 files

Checkpoint ✅ ​

  • 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 ​

  • exec is a mutable shell surface: disabling write, edit, and apply_patch does not make exec read-only. Don't rely on "turning off tools" as a fallback—configure a sandbox when one is needed.
  • Remote host=node execution goes through synchronous system.run and does not create a process session; when process is forbidden, local exec runs synchronously, ignoring yieldMs and background, and durable execution is rejected.
  • tools.fs.workspaceOnly and tools.exec.applyPatch.workspaceOnly each independently include apply_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.