openclaw - ✅(Solved) Fix [Feature]: Skill author-defined setup hook (run skill-supplied script on install/update) [3 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#80213Fetched 2026-05-11 03:17:31
View on GitHub
Comments
2
Participants
3
Timeline
13
Reactions
2
Author
Timeline (top)
referenced ×6cross-referenced ×4commented ×2labeled ×1

Add a setup.script hook in SKILL.md frontmatter that runs a skill-supplied script after skills.install and skills.update succeed, with a defined env contract — closing the gap between today's predefined install kinds (brew | node | go | uv | download) and skills that need post-install setup logic.

Root Cause

All three exist because no upstream setup.script hook exists. When this proposal lands, the same scripts/install.sh (which calls mcporter vault set per openclaw/mcporter#156) becomes the setup.script value — zero skill-content changes — and all three workarounds collapse onto the upstream-native surface.

Fix Action

Fix / Workaround

The wrapper-script workaround (per-call idempotent init) has four costs:

  • Affected users/systems: skill authors needing install-time setup; downstream projects orchestrating skill installs (e.g. integration platforms that auto-enable skills on user actions). Every skill that wraps an OAuth-protected MCP server via mcporter hits this — Linear, Sentry, Notion, GitHub-MCP, and the growing set of hosted MCP services.
  • Severity: blocks any skill that needs install-time vault seeding, config rendering, or per-installation credential setup from being a clean upstream skill — forces a per-call wrapper or a custom out-of-band install flow.
  • Frequency: every skill in the class above. With openclaw/mcporter#156 just shipped (the mcporter vault set CLI that was added specifically for this use case), the immediate-term impact is that every new MCP-OAuth skill repeats the same wrapper-script workaround to invoke that CLI.
  • Consequence: a downstream OpenClaw consumer building MCP-OAuth integrations currently tracks three parallel install-hook execution mechanisms in an internal design doc, none of which use upstream-native primitives:
    • tools.invoke {exec} over the gateway WS RPC — designed but blocked by #54391 (exec not in the WS RPC tool catalog; closed COMPLETED without resolution and locked).
    • /bash slash command via chat.send — works for command execution, but the command body persists to gateway logs and persisted session history, disqualifying it for credentials.
    • A custom hosting-platform-side HTTPS endpoint that runs the script outside the OpenClaw gateway entirely — design-only, sidesteps the gateway entirely.

All three exist because no upstream setup.script hook exists. When this proposal lands, the same scripts/install.sh (which calls mcporter vault set per openclaw/mcporter#156) becomes the setup.script value — zero skill-content changes — and all three workarounds collapse onto the upstream-native surface.

PR fix notes

PR #80266: fix #80213: [Feature]: Skill author-defined setup hook (run skill-supplied script on install/update)

Description (problem / solution / changelog)

Summary

Fixes #80213

Issue

Feature: Skill author-defined setup hook (run skill-supplied script on install/update)

Changes

  • Add setup.script frontmatter hook that runs a skill-supplied script after skills.install and skills.update succeed
  • Parse metadata.openclaw.setup.script and optional timeoutMs from SKILL.md frontmatter
  • Run setup hook after archive installs (ClawHub) via installPackageDir afterInstall callback
  • Wire setup hook into the existing skills.install metadata installer flow
  • Pass only declared environment to hook scripts (SKILL_DIR, OPENCLAW_HOOK_KIND, allowlisted requires.env, minimal PATH)

Changed Files

CHANGELOG.md                          |   1 +
 src/agents/skills-archive-install.ts  |  19 +++
 src/agents/skills-install.ts          |  17 +++
 src/agents/skills-setup.test.ts       | 237 ++++++++++++++++++++++++++++++++++
 src/agents/skills-setup.ts            | 157 ++++++++++++++++++++++
 src/agents/skills/frontmatter.test.ts |  62 +++++++++
 src/agents/skills/frontmatter.ts      |  24 ++++
 src/agents/skills/types.ts            |   6 +
 src/process/exec.ts                   |   4 +
 9 files changed, 527 insertions(+), 1 deletion(-)

Real behavior proof

  • Behavior or issue addressed: Skill author-defined setup hook that runs a skill-supplied script after skills.install and skills.update succeed. The setup script receives SKILL_DIR, OPENCLAW_HOOK_KIND, and allowlisted requires.env variables. Only declared environment is passed to hook scripts (plus minimal PATH for shell resolution) — no ambient process secrets leak. On update, if setup fails, the previous skill version is preserved via afterInstall rollback.
  • Real environment tested: Linux x86_64, Node.js v22.22.0, pnpm v10.33.2, local OpenClaw build from feat/issue-80213 branch with P1/P2 fixes applied
  • Exact steps or command run after this patch:
    1. Built the project: pnpm build (exit code 0)
    2. Ran full changed check: pnpm check:changed — core typecheck passed (45s), lint passed, conflict markers passed
    3. Ran setup hook tests: pnpm test src/agents/skills-setup.test.ts — 14/14 passed (success, failure, timeout, env vars, path traversal, non-executable fallback)
    4. Ran frontmatter tests: pnpm test src/agents/skills/frontmatter.test.ts — 15/15 passed (parse setup.script, timeoutMs, reject .. and absolute paths)
    5. Ran archive install tests: pnpm test src/agents/skills-archive-install.test.ts — 5/5 passed (afterInstall integration)
    6. Ran metadata installer tests: pnpm test src/agents/skills-install.test.ts — 9/9 passed (skills.install flow with setup hook)
    7. Ran exec tests: pnpm test src/process/exec.test.ts — 9/9 passed (baseEnv parameter addition)
    8. Ran installer fallback tests: pnpm test src/agents/skills-install-fallback.test.ts — 4/4 passed
  • Evidence after fix:
    $ pnpm test src/agents/skills-setup.test.ts src/agents/skills/frontmatter.test.ts \
             src/agents/skills-archive-install.test.ts src/agents/skills-install.test.ts \
             src/process/exec.test.ts src/agents/skills-install-fallback.test.ts
    
    Test Files  6 passed (6)
         Tests  56 passed (56)
    
    $ pnpm check:changed
      4.94s  ok  conflict markers
     45.23s  ok  typecheck core
    117.06s  ok  typecheck core tests
  • Observed result after fix:
    • P1 FIXED: Setup scripts receive only declared environment (SKILL_DIR, OPENCLAW_HOOK_KIND, allowlisted requires.env) plus minimal PATH for shell resolution. No ambient process secrets leak. baseEnv: {} ensures runCommandWithTimeout does not merge process.env.
    • P2 FIXED (rollback): Setup hook runs inside installPackageDir's afterInstall callback, which executes before backup/publish. If the hook fails, the staged tree is discarded without affecting the existing install.
    • P2 FIXED (metadata flow): installSkill now invokes runSkillSetupHook after the install command succeeds, so skills installed via metadata.openclaw.install also run their declared setup script.
  • What was not tested: Full ClawHub remote roundtrip (requires ClawHub API credentials). The archive install path is exercised through installExtractedSkillRoot integration tests which call the same code path used by installSkillArchiveFromPath.

Security Impact

  • New permissions/capabilities? Yes — adds install-time skill-supplied script execution. Scoped to allowlisted env contract.
  • Secrets/tokens handling changed? Yes — P1 fix ensures setup hooks cannot read ambient process secrets.
  • New/changed network calls? No
  • Command/tool execution surface changed? Yes — new child_process execution path for setup scripts with timeout and path-traversal guards.
  • Data access scope changed? No

🤖 Generated with Claude Code

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/canvas/src/host/a2ui/.bundle.hash (modified, +1/-1)
  • src/agents/skills-archive-install.ts (modified, +13/-0)
  • src/agents/skills-install.ts (modified, +40/-2)
  • src/agents/skills-setup.test.ts (added, +237/-0)
  • src/agents/skills-setup.ts (added, +158/-0)
  • src/agents/skills/frontmatter.test.ts (modified, +62/-0)
  • src/agents/skills/frontmatter.ts (modified, +24/-0)
  • src/agents/skills/types.ts (modified, +6/-0)
  • src/process/exec.ts (modified, +2/-1)

PR #80270: feat(skills): add author-defined setup hook for post-install scripts

Description (problem / solution / changelog)

Closes #80213

Summary

Skill authors can now define a setup block in SKILL.md to run a bundle-relative script after installation completes. The hook receives a minimal environment (SKILL_DIR, OPENCLAW_HOOK_KIND, forwarded requires.env keys) and has a configurable timeout.

Frontmatter example:

---
metadata: {"openclaw":{"install":[{"id":"deps","kind":"node","package":"my-pkg"}],"setup":{"script":"scripts/post-install.sh","timeoutMs":120000}}}
---

Changes

4 commits — each independently testable:

  1. aa6523fa09types.ts: Add SkillSetupHook type + setup? field on OpenClawSkillMetadata
  2. a6860ae0bffrontmatter.ts: Parse setup.script with safety normalization (blocks absolute paths, .., shell special chars)
  3. 20576c1d93skills-install.ts: Execute hook after successful install; inject env contract; path escape guard
  4. 3772484b05skills-install.test.ts: 4 integration tests; lint-clean (curly rule compliant)

Real Behavior Proof

Behavior or issue addressed: Skill authors have no way to run post-install configuration scripts (e.g. creating config directories, setting permissions, running first-time setup). This adds a setup.script hook that runs after openclaw skills install completes successfully.

Real environment tested: Node 22 / Linux (DGX Spark), openclaw CLI, branch feat/skill-setup-hook-80213.

Exact steps or command run after this patch:

pnpm vitest run src/agents/skills-install.test.ts

Verifies: (1) hook called with SKILL_DIR + OPENCLAW_HOOK_KIND=install + forwarded env keys, (2) hook not called on install failure, (3) hook failure propagates as ok: false, (4) path traversal is blocked.

Evidence after fix: Terminal output from running pnpm vitest run src/agents/skills-install.test.ts on branch feat/skill-setup-hook-80213:

 Test Files  2 passed (2)
       Tests  26 passed (26)
    Duration  1.39s

All 26 pass: 22 existing (no regressions) + 4 new setup-hook integration tests.

Observed result after fix: SkillSetupHook is parsed from SKILL.md, executed via runCommandWithTimeout after successful install, with isolated env (SKILL_DIR, OPENCLAW_HOOK_KIND, requires.env forwarding). Non-zero exit propagates as install failure. Path-traversal scripts rejected both at parse time (frontmatter) and at runtime (path escape guard).

What was not tested: Update path (hookKind: "update") — no updateSkill surface exists yet. Multi-platform (macOS/Windows) shell execution — the hook runs the script directly (not via shell), so platform differences are minimal but not separately validated.

Changed files

  • src/agents/skills-install.test.ts (modified, +206/-0)
  • src/agents/skills-install.ts (modified, +63/-2)
  • src/agents/skills/frontmatter.ts (modified, +37/-0)
  • src/agents/skills/types.ts (modified, +8/-0)

PR #80276: feat(skills): add author-defined setup hook for post-install scripts

Description (problem / solution / changelog)

Closes #80213

Summary

Skill authors can now define a setup block in SKILL.md to run a bundle-relative script after installation completes. The hook receives a minimal environment (SKILL_DIR, OPENCLAW_HOOK_KIND, forwarded requires.env keys) and has a configurable timeout.

Frontmatter example:

---
metadata: {"openclaw":{"install":[{"id":"deps","kind":"node","package":"my-pkg"}],"setup":{"script":"scripts/post-install.sh","timeoutMs":120000}}}
---

Changes

5 commits — each independently testable:

  1. aa6523fa09types.ts: Add SkillSetupHook type + setup? field on OpenClawSkillMetadata
  2. a6860ae0bffrontmatter.ts: Parse setup.script with safety normalization (blocks absolute paths, .., shell special chars)
  3. 20576c1d93skills-install.ts: Execute hook after successful install; inject env contract; path escape guard
  4. 3772484b05skills-install.test.ts: 4 integration tests; fe91d02d3c lint-clean (curly rule)

Real Behavior Proof

Behavior or issue addressed: Skill authors have no way to run post-install configuration scripts (e.g. creating config directories, setting permissions, running first-time setup). This adds a setup.script hook that runs after openclaw skills install completes successfully.

Real environment tested: Node 22 / Linux, openclaw CLI, branch feat/skill-setup-hook-80213.

Exact steps or command run after this patch:

pnpm vitest run src/agents/skills-install.test.ts

Verifies: (1) hook called with SKILL_DIR + OPENCLAW_HOOK_KIND=install + forwarded env keys, (2) hook not called on install failure, (3) hook failure propagates as ok: false, (4) path traversal is blocked.

Evidence after fix: Terminal output from running pnpm vitest run src/agents/skills-install.test.ts on branch feat/skill-setup-hook-80213:

 Test Files  2 passed (2)
       Tests  26 passed (26)
    Duration  1.39s

All 26 pass: 22 existing (no regressions) + 4 new setup-hook integration tests.

Observed result after fix: SkillSetupHook is parsed from SKILL.md, executed via runCommandWithTimeout after successful install, with isolated env (SKILL_DIR, OPENCLAW_HOOK_KIND, requires.env forwarding). Non-zero exit propagates as install failure. Path-traversal scripts rejected both at parse time (frontmatter) and at runtime (path escape guard).

What was not tested: Update path (hookKind: "update") — no updateSkill surface exists yet. Multi-platform (macOS/Windows) shell execution — the hook runs the script directly (not via shell), so platform differences are minimal but not separately validated.

Changed files

  • src/agents/skills-install.test.ts (modified, +214/-0)
  • src/agents/skills-install.ts (modified, +63/-2)
  • src/agents/skills/frontmatter.ts (modified, +37/-0)
  • src/agents/skills/types.ts (modified, +8/-0)

Code Example

metadata:
  openclaw:
    setup:
      script: scripts/install.sh   # bundle-relative path
      timeoutMs: 60000             # default suggestion
RAW_BUFFERClick to expand / collapse

Summary

Add a setup.script hook in SKILL.md frontmatter that runs a skill-supplied script after skills.install and skills.update succeed, with a defined env contract — closing the gap between today's predefined install kinds (brew | node | go | uv | download) and skills that need post-install setup logic.

Problem to solve

Concrete driving example: the mcporter OAuth-skill class. The recently-shipped openclaw/mcporter#156 (Add mcporter vault set <server> to seed credentials non-interactively, closed COMPLETED 2026-05-09 via a64e29b) added mcporter vault set <server> --tokens-file/--stdin and mcporter vault clear <server> CLIs precisely so downstream consumers can seed mcporter's OAuth credential vault non-interactively. The motivating use case is OpenClaw skills that wrap OAuth-protected MCP servers (Linear's mcp.linear.app, Sentry, Notion, etc.) — every such skill needs to run mcporter vault set once, with the user's OAuth tokens in env, after skills.install and before the first agent invocation.

openclaw/mcporter#156 solves the target side of that chain: how to write the credentials into mcporter's vault without reproducing internal vault-key format. It does not solve the caller side: how does that one-time mcporter vault set invocation actually get triggered with the credentials in env? Today, OpenClaw has no answer — there's no skill-author hook that runs after skills.install with a defined env contract. The skill ends up shipping a wrapper script that the agent invokes instead of the underlying tool, and the wrapper re-checks "have I already seeded the vault?" on every single agent call.

General problem. Skills routinely need one-time setup beyond binary install: seed a vault file (mcporter and others), render a config, register a wrapper, write a manifest, generate per-installation credentials. Today the install array supports only the predefined kinds at src/agents/skills/types.ts (SkillInstallSpec.kind = "brew" | "node" | "go" | "uv" | "download"), and SKILL.md frontmatter has no surface for "run this script after the dependencies are installed."

The wrapper-script workaround (per-call idempotent init) has four costs:

  • Per-call overhead even when the no-op path is fast.
  • Boilerplate duplicated across skills.
  • Setup runs in the agent's tool-call context, not in a known install-time context — failures surface as "tool failed" instead of "skill install failed."
  • No structured way to declare "this script needs these env vars at setup time" — the wrapper inspects its own env at every call.

Distinct from before_install. This proposal is not a duplicate of the recently-merged before_install hook (PR #56050, 2026-03-29), which is a plugin author hook for install-time policy/scan/vetting decisions. before_install answers "should this install proceed?"; this proposal answers "now that the install proceeded, run the skill's own setup script." Skill authors today have no upstream surface for the second question.

Proposed solution

Add a setup hook to SKILL.md frontmatter:

metadata:
  openclaw:
    setup:
      script: scripts/install.sh   # bundle-relative path
      timeoutMs: 60000             # default suggestion

OpenClaw runs the script after skills.install and skills.update succeed, with a known env contract:

  • SKILL_DIR — absolute bundle directory.
  • OPENCLAW_HOOK_KINDinstall or update.
  • All env vars listed in metadata.openclaw.requires.env (subject to the existing sanitizer rules at src/agents/skills/env-overrides.ts).

Failure of the hook (non-zero exit code, or timeout) fails the install. Hooks are optional — skills with no setup.script behave exactly as today.

Scope (initial): install + update only. A teardown counterpart could ship later if skills.uninstall lands — open PR #69319 is the canonical work item for that (issue #69299 was bot-closed 2026-04-26 as duplicate-of-#69319, not maintainer-rejected). Until that PR merges, no teardown field is proposed here.

Sanitizer interaction: the existing sanitizer drops sensitive-named env vars (_TOKEN, _KEY, _SECRET, etc.) unless they're in requires.env. The setup hook receives credentials only via the same allowlist. (The known dual-purpose conflict in requires.env — eligibility gate + sanitizer allowlist — is tracked separately in #59078; orthogonal to this proposal.)

Alternatives considered

  • Add another install kind (e.g. kind: "exec" running a bundled script). Reuses the existing array but conflates dependency installation with application setup; failures, ordering, and rollback semantics differ between the two. A separate setup.script field keeps the responsibility split clear.
  • Extend before_install to support skill-author handlers. before_install is a plugin-registered hook by design (handlers come from plugins, not from the installed skill itself). Re-purposing it for skill-author execution would change its trust model — plugin handlers run with plugin authority; skill-supplied scripts should not inherit that.
  • Persist the wrapper-script pattern (the current state). Documented as the only path today, but four downstream costs above. Doesn't scale across the ecosystem.

Impact

  • Affected users/systems: skill authors needing install-time setup; downstream projects orchestrating skill installs (e.g. integration platforms that auto-enable skills on user actions). Every skill that wraps an OAuth-protected MCP server via mcporter hits this — Linear, Sentry, Notion, GitHub-MCP, and the growing set of hosted MCP services.

  • Severity: blocks any skill that needs install-time vault seeding, config rendering, or per-installation credential setup from being a clean upstream skill — forces a per-call wrapper or a custom out-of-band install flow.

  • Frequency: every skill in the class above. With openclaw/mcporter#156 just shipped (the mcporter vault set CLI that was added specifically for this use case), the immediate-term impact is that every new MCP-OAuth skill repeats the same wrapper-script workaround to invoke that CLI.

  • Consequence: a downstream OpenClaw consumer building MCP-OAuth integrations currently tracks three parallel install-hook execution mechanisms in an internal design doc, none of which use upstream-native primitives:

    • tools.invoke {exec} over the gateway WS RPC — designed but blocked by #54391 (exec not in the WS RPC tool catalog; closed COMPLETED without resolution and locked).
    • /bash slash command via chat.send — works for command execution, but the command body persists to gateway logs and persisted session history, disqualifying it for credentials.
    • A custom hosting-platform-side HTTPS endpoint that runs the script outside the OpenClaw gateway entirely — design-only, sidesteps the gateway entirely.

    All three exist because no upstream setup.script hook exists. When this proposal lands, the same scripts/install.sh (which calls mcporter vault set per openclaw/mcporter#156) becomes the setup.script value — zero skill-content changes — and all three workarounds collapse onto the upstream-native surface.

Evidence/examples

Adjacent issues confirming the gap is real and recurrent:

  • #23926 (open) — skill:pre-install/post-install Hook Events. Plugin-author event-listener angle of the same gap.
  • #46780 (open) — Skill Lifecycle Hooks beforeExecute/afterExecute. Per-tool-call hooks; different lifecycle moment but same "no skill-author hook surface" pattern.
  • #43454 (open) — Gateway lifecycle hooks. Different layer (gateway, not skill); included for completeness.
  • #18677, #45031 (both open) — security-scan hooks for skill:install. Vetting use case; orthogonal to setup-execution use case.
  • #12219 (open) — Skill Permission Manifest Standard. Different layer.

Adjacent closures, PRs in flight, and what they imply:

  • #56050 merged 2026-03-29 — before_install policy hook for plugin authors. Establishes the install-time hook infrastructure this proposal builds on, but covers only policy/scan, not skill-author execution.
  • #61557 closed NOT_PLANNED 2026-04-25 — skill:install hook for security vetting. Suggests upstream considers vetting to belong in before_install. This proposal is distinct: skill-author execution, not third-party vetting.
  • #69299 closed 2026-04-26 by clawsweeper[bot] as duplicate-of-PR #69319 (gateway: register skills.uninstall RPC (mirror of skills.install), body Fixes #69299). PR #69319 is OPEN — uninstall RPC is in flight, not rejected. Scoping consequence for this proposal: initial scope is install/update only; a teardown field can be added later if/when #69319 (or equivalent) merges.

Today's wrapper-script workaround example: scripts/invoke.sh in any MCP-OAuth skill, where every agent invocation pays the cost of an idempotency check + sidecar comparison just to decide whether to re-run setup. Setup runs in the agent's tool-call context with no structured env contract.

Additional information

  • Backward compatible: skills with no setup.script field behave exactly as today.
  • Implementation could reuse the existing before_install infrastructure for the runner, restricted to skill-author scripts under ${SKILL_DIR} and gated by the SKILL.md frontmatter declaration.
  • Out of scope (deliberately, to keep the proposal focused):
    • Uninstall hook (defer to PR #69319 skills.uninstall; add a teardown field if/when that lands).
    • Per-tool-call hooks (covered by #46780).
    • Policy/vetting (covered by before_install).
    • Plugin-author event listeners (covered by #23926).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Feature]: Skill author-defined setup hook (run skill-supplied script on install/update) [3 pull requests, 2 comments, 3 participants]