#Creating skills

78 messages · Page 1 of 1 (latest)

mighty frost
#

Created your own SKILL.md . Added to the folder /.openclaw/skills/{skill_name}/SKILL.MD . I restarted gateway, and it says on the host that the skill requires installation (but there are no buttons). On the node, the companion says that missing binaries: open, and the cli doesn't have my skill at all

coral lintelBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

atomic egretBOT
river lakeBOT
#

I think the main issue is the filename.

SKILL.md is case-sensitive.
If you created ~/.openclaw/skills/<skill_name>/SKILL.MD, OpenClaw will usually not discover it on Linux/macOS. Rename it to:

~/.openclaw/skills/<skill_name>/SKILL.md

A few other gotchas here:

  1. “requires installation” but no buttons

    • That usually means your skill has metadata.openclaw.requires...
    • but does not have metadata.openclaw.install
    • missing requirements can be shown without any install action
  2. missing binaries: open on the node

#
  • open is a macOS-only binary
    • if that node is Linux, use xdg-open instead, or gate the skill with:
      metadata: {"openclaw":{"os":["darwin"]}}
      
  1. CLI doesn’t list the skill
    • most common causes:
      • wrong filename case (SKILL.MD vs SKILL.md)
      • invalid frontmatter
      • wrong folder

Minimum valid frontmatter:

---
#

If you paste your SKILL.md, I can sanity-check it fast.

mighty frost
#
---
name: seo-page-builder
description: Build an SEO-optimized HTML page from a user topic and an existing donor page. Use when the user wants competitor research, SEO structure and keywords, article text generation, or a new page assembled from an existing page design.
metadata:
  openclaw:
    os: ["darwin"]
    requires:
      bins:
        - curl
        - unzip
        - open
      anyBins:
        - node
    emoji: "🚀"
---
  1. How to install open on macos
  2. How to enable slash command
river lakeBOT
#

A few things are colliding here.

  1. You do not install open on macOS

    • open is built into macOS, normally at /usr/bin/open
    • so if OpenClaw says missing binaries: open, that usually means:
      • that machine is not actually macOS
      • or the node host has a weird PATH

    Quick check on the Mac/node host:

    which open
    echo $PATH
    
  2. Your metadata format is wrong for skills

    • for OpenClaw skills, metadata should be a single-line JSON/JSON5 object, not nested YAML
#

So use this instead:

---
name: seo-page-builder
description: Build an SEO-optimized HTML page from a user topic and an existing donor page.
metadata: {"openclaw":{"os":["darwin"],"requires":{"bins":["curl","unzip","open"],"anyBins":["node"]},"emoji":"🚀"}}
user-invocable: true
---
  1. Filename matters

    • it must be exactly SKILL.md
    • not SKILL.MD
  2. Why there are no install buttons

    • buttons only show up if you define metadata.openclaw.install
#
  • requires alone only marks the skill as missing requirements
  1. Slash commands
    • once the skill is loaded, the generic command should work:
      /skill seo-page-builder
      
    • the direct native command on Discord will be sanitized, so this name becomes:
      /seo_page_builder
      
    • if native skill commands are disabled, enable:
      {
        commands: { nativeSkills: true },
        channels: { discord: { commands: { nativeSkills: true } } }
      }
mighty frost
#

Agent answer:

I got stuck with accessing the Mac node: I can't open a browser on your Mac from this session, and the skill is tied specifically to ChatGPT in the browser and further assembly via Mac/Codex.

{
"command": "open -a 'Google Chrome' 'https://chat.openai.com'",
"host": "node",
"node": "MacBook Pro",
"security": "allowlist",
"ask": "on-miss",
"yieldMs": 5000
}
{
"status": "error",
"tool": "exec",
"error": "exec node not allowed (bound to 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480)"
}

I have two nodes on one macbook.
6f1e541dd94c5a90db49d8576c0ad17f744401155486d440b737ce8cbe63f40c (Mac app):
client: openclaw-macos/node · device: Mac · hw: MacBookPro18,1 · browser, canvas, screen. perms: [accessibility=yes, appleScript=yes, camera=no, location=no, microphone=yes, notifications=yes, screenRecording=yes, speechRecognition=yes] · ui v2026.4.11

76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480 (Mac exec):
client: node-host/node · core v2026.4.11 · path: /opt/homebrew, Cellar/node/25.9.0_2/bin:/usr/bin:…:/Users/user/.yarn/bin. caps: browser, system

I would like to give "Mac exec" all possible permissions and caps.

river lakeBOT
#

Short version: you can’t turn the headless Mac exec node into the full Mac app node.
Those are two different node types, and caps are exposed by the node implementation, not by a permission toggle.

What’s going on:

  1. That exec error is just node binding

    • your session is bound to 76526f... (Mac exec)
    • the tool call tried node: "MacBook Pro" (the other node)
    • so OpenClaw rejected it with:
      exec node not allowed (bound to 76526f...)
  2. “All possible permissions/caps”

    • not really possible for the headless node host
    • screen, canvas, camera/TCC-style stuff belongs to the Mac app node
    • the headless node host is mainly for system.run / system.which style exec
  3. What you can do

#
  • make the Mac exec node run commands through the Mac app

    • on the Mac node-host service, set:
      OPENCLAW_NODE_EXEC_HOST=app
      OPENCLAW_NODE_EXEC_FALLBACK=0
      
    • then restart the node host

    That’s the supported way to get exec routed through the app’s macOS/TCC context.

  1. If you want the exec node to stop prompting / be fully permissive
    • set node approvals to full/off:
      openclaw approvals set --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480 --stdin <<'EOF'
      {
        version: 1,
        defaults: {
#

security: "full",
ask: "off",
askFallback: "full"
}
}
EOF
```

  • and align requested policy too:
    openclaw config set tools.exec.host node
    openclaw config set tools.exec.node "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480"
    openclaw config set tools.exec.security full
    openclaw config set tools.exec.ask off
    
  1. If you want to target the other node instead
    • change or unset the exec binding:
#
     openclaw config unset tools.exec.node
     ```
     or bind it to the app node explicitly.

So the real answer is:

- **No**, you can’t make `Mac exec` gain every Mac app capability.
- **Yes**, you can make `Mac exec` forward `system.run` through the Mac app, which is probably what you actually want.

Docs:
- <https://docs.openclaw.ai/nodes/index>
- <https://docs.openclaw.ai/platforms/macos>
- <https://docs.openclaw.ai/cli/approvals>

If you want, paste:
#
openclaw --version
openclaw approvals get --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480

and I can tell you the exact clean setup.

mighty frost
#

Where should I insert it?
OPENCLAW_NODE_EXEC_HOST=app
OPENCLAW_NODE_EXEC_FALLBACK=0

version: OpenClaw 2026.4.12 (1c0672b)
scope: tools.exec
requested: security=full (tools.exec.security) ask=off (tools.exec.ask)
Host: security=full, ask=off, askFallback=full
Effective: security=full, ask=off
Notes: requested security applies; requested ask applies

river lakeBOT
#

Put them on the Mac that runs the node-host service, not in SKILL.md.

If Mac exec was installed with openclaw node install, the clean place is:

~/.openclaw/.env

Add:

OPENCLAW_NODE_EXEC_HOST=app
OPENCLAW_NODE_EXEC_FALLBACK=0

Then restart the node host:

#
openclaw node restart

If you run the node in the foreground instead of as a service, do it inline:

OPENCLAW_NODE_EXEC_HOST=app OPENCLAW_NODE_EXEC_FALLBACK=0 openclaw node run ...

A couple of important notes:

  • Do not put these in SKILL.md
  • Do not put them under openclaw.json
  • your approvals are already fine, this output shows security=full, ask=off, so the remaining issue is routing/host mode, not approvals

So the shortest path is:

#
  1. edit ~/.openclaw/.env on that Mac
  2. add those 2 vars
  3. run openclaw node restart

If you want, I can also give you the exact “sanity check” commands to confirm it picked them up after restart.

mighty frost
#

yes, give me

river lakeBOT
#

Yep, here’s a clean sanity-check sequence.

1) Confirm the env vars are in place on the Mac

rg 'OPENCLAW_NODE_EXEC_(HOST|FALLBACK)' ~/.openclaw/.env

You want to see:

OPENCLAW_NODE_EXEC_HOST=app
OPENCLAW_NODE_EXEC_FALLBACK=0

2) Restart the node-host service

openclaw node restart
#

3) Make sure the node comes back

openclaw nodes status

4) Inspect the exact exec node

openclaw nodes describe --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480

5) Check that the Mac can resolve open

openclaw nodes invoke --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480 --command system.which --params '{"name":"open"}'

You should get something like /usr/bin/open.

#

6) Confirm your exec binding is pointed at the right node

openclaw config get tools.exec.node

If it’s wrong, set it:

openclaw config set tools.exec.node "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480"

7) End-to-end test from chat

Then in chat, ask the agent to run something tiny on the node, for example:

run `which open && sw_vers` with host=node
#

If you want, paste the output of steps 4 and 5 and I’ll tell you immediately whether it’s wired correctly.

mighty frost
#

openclaw nodes describe --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480
ID │ 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480 Name │ MacBook Pro Client │ node-host/node Version │ core v2026.4.11 PATH │ /opt/homebrew/Cellar/node/25.9.0_2/bin:/usr/bin:/bin:/opt/homebrew/opt/node/bin:/Users/user/.nvm:/Users/user/.local/bin:/Users/user/.npm-global/bin:/Users/user/bin:/Users/user/.volta/bin:/Users/user/.asdf/shims:/Users/user/.bun/bin:/Users/user/Library/Application Support/fnm/aliases/default/bin:/Users/user/.fnm/aliases/default/bin:/Users/user/Library/pnpm:/Users/user/.local/share/pnpm:/opt/homebrew/bin:/usr/local/bin:/Users/user/.yarn/bin
Status │ paired · connected Caps │ browser, system

  1. nodes invoke failed: GatewayClientRequestError: INVALID_REQUEST: Error: INVALID_REQUEST: bins required
river lakeBOT
#

Nice, this actually tells us a lot.

Your node looks healthy:

  • it’s paired + connected
  • PATH includes /usr/bin
  • so open should be available on that Mac

The nodes invoke failure is just the wrong payload shape.
For system.which, this runtime expects bins, not name.

Try this:

openclaw nodes invoke --node 76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480 --command system.which --params '{"bins":["open","curl","unzip","node"]}'
#

If that returns paths, then the node side is fine and the problem is back in the skill itself.

At that point, double-check these 3 things:

  1. filename is exactly:

    ~/.openclaw/skills/seo-page-builder/SKILL.md
    

    not SKILL.MD

  2. metadata is inline JSON5, for example:

    ---
    name: seo-page-builder
    description: Build an SEO-optimized HTML page from a user topic and an existing donor page.
    metadata: {"openclaw":{"os":["darwin"],"requires":{"bins":["curl","unzip","open"],"anyBins":["node"]},"emoji":"🚀"}}
    
#
   user-invocable: true
   ---
  1. start a new session or restart the gateway again

So, I’m pretty confident now that the missing-binary issue is not your Mac exec node, it’s the skill discovery/parsing path. If you paste the output of that system.which call, I can confirm it.

mighty frost
#

Agent answer:

I tried, but the problem is the same: The Mac is visible as paired/connected, but the browser proxy is unavailable from this session, and exec to the desired node is not allowed here.

That is, now the blocker is not in the skill, but in the access route to the node/browser.

What can be done:

either I continue without a Mac and build the SEO page manually here,
or you fix node access first, and I immediately repeat full flow.
If you want to fix access, I can further help diagnose this as a node/browser connectivity issue.
river lakeBOT
#

Yep, that answer means you’ve moved past skill discovery and hit a runtime routing problem.

My honest take: opening ChatGPT in Chrome from a skill is the wrong shape for OpenClaw. It’s brittle, and now you’re fighting node binding + browser proxy + exec routing all at once.

So there are really two paths:

Better path, recommended

Make the skill OpenClaw-native instead of browser-driven:

  • research: web_search + web_fetch
  • inspect donor page: web_fetch or browser
  • build HTML locally
  • if you need Codex, use the ACP harness, not chat.openai.com in Chrome

That removes the whole Mac/browser binding mess.

Current path, if you keep the browser flow

#

Then yes, the blocker is now:

  • browser access on the right node
  • exec bound to the right node
  • both being usable in the same run

That’s a node/browser plumbing problem, not a SKILL.md format problem anymore.

So, good news: your skill parsing issue is basically solved.
Bad news: the skill design is still fighting the platform.

If you want, paste the full skill and I’ll rewrite it into a cleaner OpenClaw-native version that avoids the browser dependency entirely.

mighty frost
#

I have a theme and a donor URL, but I don't have access to execute commands on my MacBook Pro from this session, so I can't honestly run seo-page-builder locally, as the skill requires.

There are 2 normal ways:

I'll try to raise a separate ACP/Codex session on node if you want me to continue on my own.
I'll give you a ready-made local command set/script that will run the entire pipeline on your Mac.
I recommend option 1 if you want to be as “turnkey" as possible. Just write: "try using ACP."

I want the skill to use the codex cli command on the node.

river lakeBOT
#

Then I would not use ACP for this.

If your requirement is specifically:

run the codex CLI on the node

then the skill should be built around exec host=node, because ACP sessions run on the host/gateway runtime, not the paired node.

So the shape should be:

  • drop browser/open
  • drop ACP
  • require codex on the node
  • instruct the model to use exec with host=node

Something closer to this:

#
---
name: seo-page-builder
description: Build an SEO-optimized HTML page from a topic and donor URL by running Codex CLI on the paired node.
metadata: {"openclaw":{"os":["darwin"],"requires":{"anyBins":["codex"],"bins":["curl","unzip"]},"emoji":"🚀"}}
user-invocable: true
---

# SEO Page Builder

When the user provides a theme and donor URL:

1. Use `web_fetch` or `curl` to inspect the donor page.
2. Use `exec` with `host=node` on the configured node.
3. Run the `codex` CLI on that node to generate/refine the page.
4. Return the resulting HTML and a short summary of what was built.
#

Important:
- Do not use browser automation unless the user explicitly asks for it.
- Do not open chat.openai.com.
- Prefer the node-host Codex CLI path.

So the key distinction is:

  • ACP = Codex harness on the gateway host
  • exec host=node = literal codex binary on the paired node

Since you want the second one, your agent’s “try using ACP” suggestion is actually the wrong path.

If you want, I can draft the full SKILL.md for the node-exec Codex version.

mighty frost
#

{
"command": "zsh -lc 'cd ~/Downloads/seo-page-builder/kak-razrabatyvat-prilozheniya && codex exec --skip-git-repo-check -C ~/Downloads/seo-page-builder/kak-razrabatyvat-prilozheniya -s workspace-write --full-auto "На основе файла competitors.md подготовь полноценный SEO-brief для страницы по теме \"Как разрабатывать приложения\". Определи идеальную структуру страницы, H1, H2 и порядок блоков, обязательные SEO-элементы, конверсионные блоки, Title, Description, Canonical, облако ключевых слов, группировку ключей: основной, LSI, коммерческие, информационные, и секцию FAQ. Сохрани результат в seo-brief.md."'",
"host": "node",
"node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
"yieldMs": 1000,
"background": true,
"timeout": 3600
}

{
"status": "error",
"tool": "exec",
"error": "TIMEOUT: node invoke timed out"
}

river lakeBOT
#

That timeout looks like a runtime hang, not a skill/discovery issue.

The first thing I’d change is this:

  • don’t wrap it in zsh -lc
  • do set pty: true for Codex
  • don’t start with the giant prompt first

Codex is exactly the kind of CLI where PTY helps.

Try this ladder

1) Smoke test the node + Codex binary

{
  "command": "which codex && codex --version",
#
  "host": "node",
  "node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
  "pty": true,
  "yieldMs": 10000,
  "timeout": 60
}

2) Smoke test the working dir

{
  "command": "pwd && ls -la",
  "workdir": "~/Downloads/seo-page-builder/kak-razrabatyvat-prilozheniya",
  "host": "node",
  "node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
#
  "pty": true,
  "yieldMs": 10000,
  "timeout": 60
}

3) Then run Codex directly, no shell wrapper

{
  "command": "codex exec --skip-git-repo-check -C . -s workspace-write --full-auto \"На основе файла competitors.md подготовь полноценный SEO-brief... Сохрани результат в seo-brief.md.\"",
  "workdir": "~/Downloads/seo-page-builder/kak-razrabatyvat-prilozheniya",
  "host": "node",
  "node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
  "pty": true,
  "yieldMs": 20000,
#
  "timeout": 3600
}

Why

TIMEOUT: node invoke timed out usually means the node never returned from system.run, often because:

  • the CLI wants a TTY
  • first-run Codex auth/setup is blocking
  • shell startup/profile is hanging
  • the shell wrapper is making the invocation brittle

So I’d test:

  1. which codex && codex --version
  2. pwd && ls -la
#
  1. only then the real codex exec

If step 1 hangs too, the problem is Codex on the Mac, not the skill.
If step 1 works and step 3 hangs, it’s probably TTY/auth/first-run behavior.

Paste step 1 output, that’ll narrow it down fast.

mighty frost
#

/opt/homebrew/bin/codex
codex-cli 0.118.0

river lakeBOT
#

Perfect, that’s a good sign.

So now we know:

  • the node is reachable
  • the codex binary exists
  • the remaining issue is specifically codex exec, not node access in general

Next I’d test the smallest real Codex run with PTY and no shell wrapper:

{
  "command": "codex exec --skip-git-repo-check -C . -s workspace-write --full-auto \"Reply with exactly OK\"",
  "workdir": "~/Downloads/seo-page-builder/kak-razrabatyvat-prilozheniya",
  "host": "node",
  "node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
#
  "pty": true,
  "yieldMs": 20000,
  "timeout": 600
}

If that works, then scale up to your real SEO prompt.

If that still times out, then the problem is likely one of:

  • Codex first-run/auth flow
  • Codex waiting on something interactive even with PTY
  • codex exec behavior on that node specifically

At that point I’d do one more tiny check:

#
{
  "command": "codex exec --help",
  "host": "node",
  "node": "76526ff3f25550ae6df5354e16c56dc9eafe3bfe84ffc530bed65566cdbe0480",
  "pty": true,
  "yieldMs": 10000,
  "timeout": 60
}

You’re pretty close now. The big blocker is gone, we’re just narrowing down the exact codex exec behavior.

mighty frost
#

Now next error
{
"status": "error",
"tool": "exec",
"error": "exec host not allowed (requested sandbox; configured host is node; set tools.exec.host=sandbox or auto to allow this override)."
}

river lakeBOT
#

Yep, that one makes sense.

You currently have exec pinned to host=node, and now the agent tried to call host=sandbox. OpenClaw blocks that override.

So you have 2 valid setups:

Option A, recommended for this skill

Keep it node-only and make the skill explicit:

  • tools.exec.host = "node"
  • tools.exec.node = "76526f..."
  • in SKILL.md, tell it:

For this skill, all exec calls must use host=node on the configured node. Do not use sandbox or gateway exec.

That matches your goal: run Codex on the node.

#

Option B, more flexible

Set the default back to auto:

openclaw config set tools.exec.host auto

Then the agent can use sandbox normally, and the skill can explicitly request host=node only when it needs Codex.


My recommendation: Option B globally, Option A inside the skill.

That is:

  • global default: auto
  • skill instructions: “when using Codex, force host=node
#

That avoids this exact conflict.

If you want, I can write the exact final SKILL.md text that hard-pins Codex steps to the node without breaking normal sandbox behavior.

mighty frost
#

On vps in gateway openclaw.conf:
"tools": {
"exec": {
"security": "full",
"ask": "off"
}
}
exec-approvals.json:
"defaults": {
"security": "full",
"ask": "off",
"askFallback": "full"
},

On node same, but a always get approval modal like this:
Exec approval needed
expires in 25m
/bin/sh -lc "cd /Users/user/PhpstormProjects/OpenClaw/pages && ls -la"
Host
node
Agent
main
Session
agent:main:main
Security
allowlist
Ask
on-miss

river lakeBOT
#

The modal is the clue here.

If the approval sheet says:

  • Security: allowlist
  • Ask: on-miss

then the request itself / session state is still asking for allowlist + on-miss.

So this is not coming from the node exec-approvals.json you pasted.
Something higher up is overriding your global defaults, usually one of these:

  1. A persisted /exec session override in that chat/session
  2. An agent-specific override for main
  3. Less commonly, the tool call itself is explicitly sending security=allowlist ask=on-miss

What to check

#

1) Check the current session override

In that chat, run:

/exec

If it shows allowlist / on-miss, that’s your answer.

Then set it explicitly:

/exec host=node security=full ask=off node=<your-node-id>

Or just start a fresh session with /new after fixing config.

#

2) Check agent-specific config

Look for something like this in config:

agents: {
  list: [
    {
      id: "main",
      tools: {
        exec: {
          security: "allowlist",
          ask: "on-miss"
        }
      }
    }
  ]
#
}

If that exists, it overrides your global tools.exec.

3) Check the merged policy from CLI

On the gateway, run:

openclaw approvals get --node <id>

That should show:

  • requested policy
  • host approvals policy
#
  • effective result

Most likely cause

Honestly, I’d bet on a stale /exec session override from earlier testing.
Those can survive config changes and keep forcing allowlist/on-miss.

So the short fix is:

  1. /exec in the current chat
  2. if it shows old values, set:
    /exec host=node security=full ask=off node=<id>
    
  3. or use /new

If you paste the output of /exec, I can tell you in one message where it’s coming from.

mighty frost
#

"agents": {
"main": {
"allowlist": [
{
"id": "6716da38-f65e-4d7c-a98c-8dead8926d9c",
"pattern": "/bin/ls",
"source": "allow-always",
"lastUsedAt": 1776330646132,
"lastUsedCommand": "/bin/sh -lc "ls -lah /Users/user/PhpstormProjects/OpenClaw/skills/seo-page-builder/scripts/ && echo '---' && sed -n '1,220p' /Users/user/PhpstormProjects/OpenClaw/skills/seo-page-builder/scripts/codex-step.sh"",
"lastResolvedPath": "/bin/ls"
},
{
"id": "8d6476af-75fa-4228-a672-e63e5ba84bd6",
"pattern": "/usr/bin/which",
"source": "allow-always",
"lastUsedAt": 1776341019793
},
{
"id": "fc24e304-649e-4365-aae2-d455161a3dc9",
"pattern": "=command:e251ac2da3174643",
"source": "allow-always",
"lastUsedAt": 1776341073738
},
{
"id": "f19c0cde-8c4e-440b-bc33-0eccc0ff7b88",
"pattern": "=command:39c36c5291981f67",
"source": "allow-always",
"lastUsedAt": 1776341221431
},
{
"id": "4bbf111d-d903-494c-ac5a-ee84e1fdc2e7",
"pattern": "=command:2b2275860f0253dd",
"source": "allow-always",
"lastUsedAt": 1776341223994
},
{
"id": "0f26ef5e-d20e-49e3-a8c5-74812a56a729",
"pattern": "=command:cede0f1499e77098",
"source": "allow-always",
"lastUsedAt": 1776341232551
},
{
"id": "d36c6524-3657-49a5-8d13-573b0f313498",
"pattern": "=command:2415e5aa250a75e2",
"source": "allow-always",
"lastUsedAt": 1776341386246
},

  ]
}
river lakeBOT
#

Yep, this snippet is not the thing forcing the modal.

What you pasted is just the node’s stored allowlist entries for agent main:

  • source: "allow-always"
  • pattern: "/bin/ls"
  • pattern: "=command:..."

Those are basically remembered approvals / command fingerprints.

They do not by themselves mean:

  • security = allowlist
  • ask = on-miss

So the approval modal is still being driven by one of these instead:

#
  1. current session /exec override
  2. agent config override for main under tools.exec
  3. explicit params on the actual exec tool call

That’s why the modal says Security allowlist / Ask on-miss even though your defaults are full / off.

Important detail

If exec is called with explicit params like:

{
  "security": "allowlist",
  "ask": "on-miss"
}

then that will absolutely override your nice global defaults.

#

So the next thing to inspect is:

  • the actual exec tool call payload
  • or the merged policy view, not the raw allowlist file

Best checks:

openclaw approvals get --node <id>

and in the chat/session:

/exec

If you want, paste either of those and I’ll tell you exactly where the allowlist/on-miss is coming from. Right now, the allowlist block you sent is normal and not the root cause.

mighty frost
#

what do I need to prescribe so that I don't ask for permission anymore?

river lakeBOT
#

To stop permission prompts completely, you need all 3 layers aligned to YOLO:

1) Node host approvals file

On the node:

openclaw approvals set --node <id> --stdin <<'EOF'
{
  version: 1,
  defaults: {
    security: "full",
    ask: "off",
    askFallback: "full"
  }
}
EOF
#

2) Gateway requested exec policy

On the gateway:

openclaw config set tools.exec.host node
openclaw config set tools.exec.node "<id>"
openclaw config set tools.exec.security full
openclaw config set tools.exec.ask off

3) No narrower override anywhere

This is the part that usually bites people.

Make sure you do not still have one of these:

  • a session override from /exec
  • an agent-specific override under agents.list[].tools.exec
#
  • explicit tool-call params like:
    "security": "allowlist",
    "ask": "on-miss"
    

If you do, they can still force prompts.

So in the current chat/session, reset it explicitly:

/exec host=node security=full ask=off node=<id>

or just start a fresh /new after changing config.


#

Short version

You want the final effective state to be:

  • host = node
  • security = full
  • ask = off

both in:

  • the node approvals file
  • the gateway tools.exec.* config
  • the current session/tool call

If you still get a modal after that, then the actual exec call is explicitly sending allowlist/on-miss.

If you want, I can give you one exact “known-good” config snippet for both the gateway and node.

mighty frost
#

approvals on node:
│ Path │ ~/.openclaw/exec-approvals.json
│ Exists │ yes
│ Version │ 1
│ Socket │ default
│ Defaults │ security=full, ask=off, askFallback=full
│ Agents │ 0
│ Allowlist │ 0

tools.exec │ security=full (tools. │ security=full (~/.openclaw/exec-approvals.json defaults.security) │ security=full │ requested
│ │ exec.security) │ ask=off (~/.openclaw/exec-approvals.json defaults.ask) │ ask=off │ security applies; │
│ │ ask=off (tools.exec. │ askFallback=full (~/.openclaw/exec-approvals.json defaults.askFallback) │ │ requested ask │
│ │ ask) │ │ │ applies

I still get request for permission.
Exec approval needed
/bin/sh -lc "printf 'cwd=%s\n' "$PWD"; which codex || true; ls -ld /Users/user/PhpstormProjects/OpenClaw/pages /Users/user/PhpstormProjects/OpenClaw/skills/seo-page-builder/scripts 2>/dev/null"
Hostnode
Agent
main
Security
allowlist
Ask
on-miss

river lakeBOT
#

Ah, I think I see the mismatch now.

You previously set:

OPENCLAW_NODE_EXEC_HOST=app

That means system.run is being forwarded through the macOS companion app, not executed directly by the headless node-host.

So:

  • openclaw approvals get --node ... is showing you the node-host policy
  • but the modal you’re seeing is coming from the macOS app exec host

And per docs, when exec is routed through the app:

#
  • prompts + output stay in the app
  • system.run is controlled by the macOS app Exec approvals

So you have 2 options

Option 1, keep OPENCLAW_NODE_EXEC_HOST=app

Then fix the macOS app approvals:

  • open the macOS app
  • go to Settings → Exec approvals
  • set:
    • Security = full
    • Ask = off

Then restart the app (and honestly the node host too).

Option 2, simpler for debugging

#

Remove this env var:

OPENCLAW_NODE_EXEC_HOST=app

Then restart the node host.

That will keep execution on the headless node-host, where your full/off policy is already showing correctly.


So the short answer is:

you’re checking the node-host policy, but the prompt is coming from the Mac app policy.

That’s why they don’t match.

#

If you want, I can give you the exact “debug-safe” setup I’d use here, with one recommendation for either:

  • pure node-host exec
  • or app-routed exec
mighty frost
#

No, I deleted it from env.

river lakeBOT
#

Got it, but deleting it from .env is not enough if the processes were already running.

You need to make sure the old env is no longer live in the running node/app process.

Do this next

  1. Restart the node host
openclaw node restart
  1. Fully quit and reopen the macOS app

    • don’t just close the window, actually quit it
  2. If it still behaves the same, do a clean reinstall of the node service:

#
openclaw node uninstall
openclaw node install --force --host <gateway-host> --port 18789 --display-name "MacBook Pro"
openclaw node restart

Why

A running launchd/service process can keep the old env until restart.
So “I removed it from .env” does not prove the active process stopped using it.

If it still prompts after that

Then I’d stop blaming env and look at the actual exec request payload again, because something may still be explicitly sending:

"security": "allowlist",
"ask": "on-miss"
#

So the order is:

  1. restart node host
  2. restart mac app
  3. if needed, reinstall node service
  4. if still broken, inspect the actual exec tool call again

If you want, I can give you the exact shortest verification sequence after restart so we can prove which process path is active.

late steeple
#

Hello. I am a Senior Software Engineer. I think I can help you resolve your issue. If you have any questions or need assistance with project development, please contact me via DM.