Skip to content

feat(openclaw)!: bundle all 13 skills in the npm tarball (0.4.0)#20

Merged
paulgnz merged 1 commit into
mainfrom
feat/tier-c-skills-in-npm
May 13, 2026
Merged

feat(openclaw)!: bundle all 13 skills in the npm tarball (0.4.0)#20
paulgnz merged 1 commit into
mainfrom
feat/tier-c-skills-in-npm

Conversation

@paulgnz
Copy link
Copy Markdown
Collaborator

@paulgnz paulgnz commented May 13, 2026

Breaking change: skills now live under openclaw/skills/ and ship pre-built inside @xpr-agents/openclaw. Bumps to 0.4.0.

Why

Two latent bugs both blocked by the same architectural issue:

  1. Harness users got 72 tools, ZERO domain skills. Skills lived under openclaw/starter/agent/skills/ — outside openclaw/package.json's files glob — so npm install @xpr-agents/openclaw shipped only the plugin code, no DeFi / NFT / lending / etc. handlers. Pinata operators silently lost ~150 domain tools.

  2. Non-Docker standalone deploys silently lost most skills. The agent runner does require() on <skill>/src/index.ts when no dist/ exists, but production launches via plain node dist/index.js with no ts-node hook. dist/ is gitignored, so npx create-xpr-agent users got skills only for the 4 folders that happened to have a stale committed dist/. The other 8 fell silently into the [skill] Failed to load: ... catch block.

This PR fixes both at once by making skills first-class members of the npm package.

What moves

  • 12 domain skill folders: openclaw/starter/agent/skills/{creative, web-scraping, code-sandbox, structured-data, defi, nft, tax, lending, governance, xmd, smart-contracts, shellbook}openclaw/skills/<name>
  • xpr-agent-operator already lived at openclaw/skills/; duplicate copy under starter/agent/skills/ deleted

What gets built

  • New openclaw/scripts/build-skills.mjs compiles each skill's src/index.tsdist/index.js using the exact flags the Dockerfile previously used (notably without --strict — skills use dynamic await import('@xpr-agents/openclaw') which resolves to any and would fail strict null checks)
  • openclaw/package.json build now runs build:plugin then build:skills; clean clears skills/*/dist; prepublishOnly runs the full pipeline so npm-publish always ships fresh dist
  • The 5 skills that import @xpr-agents/openclaw for createCliApi (defi, governance, lending, nft, xmd) get a single // @ts-ignore on the dynamic-import line — the package can't self-reference at compile time, but Node resolves it fine at runtime via the consumer's node_modules

What the runner does differently

  • openclaw/starter/agent/src/index.ts swaps the 12 hardcoded path.resolve(__dirname, '../skills/<name>') lines for one resolveSkillDir(name) helper that uses require.resolve('@xpr-agents/openclaw/package.json') and falls back to a repo-relative path for monorepo dev
  • xpr-agent-operator SKILL.md candidate list reorders to put the npm-package path first (previously last)
  • /deliverables/:jobId route require()s the skill's dist/ entry, not its TS source — fixes the silent fall-through on non-Docker installs

What the Dockerfile drops

Removed the 12-line tower of per-skill npx tsc ... commands. npm install now pulls in pre-built dist/ from the npm package, so the Dockerfile is just npm install && npm run build.

What the manifest declares

openclaw.plugin.json skills array goes from 1 entry to 13. Harnesses that auto-load skills from the manifest pick up all domain skills automatically.

What changes for users

Before (0.3.x) After (0.4.0)
Harness install (npm install @xpr-agents/openclaw) 72 tools, 0 skills 72 tools, 13 skills
Standalone (npx create-xpr-agent) 72 tools + 4 randomly-shipped skills 72 tools + 13 skills
ClawHub installs Required for any domain capability Now additive, not required

Added runtime dependency

  • @shellbook/sdk@^0.2.4 — required by the shellbook skill's import { Shellbook } from '@shellbook/sdk'. Previously hoisted from the agent runner's node_modules; now declared on the package that ships the skill.

Verification

  • ✅ All 13 skills compile under npm run build:skills
  • ✅ All 80 openclaw tests pass
  • ✅ All 225 SDK tests pass
  • ✅ All 81 indexer tests pass
  • ✅ Runtime resolver probe confirms all 13 skill directories resolve via require.resolve('@xpr-agents/openclaw/package.json') with skill.json + SKILL.md + dist/index.js present

After merge: publish @xpr-agents/openclaw@0.4.0 to npm so harness users get the bundled skills.

BREAKING: skills now live under `openclaw/skills/` and ship pre-built
inside `@xpr-agents/openclaw`. The previous layout had skills under
`openclaw/starter/agent/skills/` outside the npm `files` glob, so
harness users who installed the plugin via npm got 72 tools but ZERO
skills. And non-Docker standalone deployments silently lost any skill
without a committed `dist/` (the agent runner does `require()` on
`src/index.ts` and Node has no ts-node hook at runtime).

This commit fixes both at once.

## What moves

- 12 domain skill folders: `openclaw/starter/agent/skills/{creative,
  web-scraping, code-sandbox, structured-data, defi, nft, tax, lending,
  governance, xmd, smart-contracts, shellbook}` →
  `openclaw/skills/<name>`
- `xpr-agent-operator` already lived at `openclaw/skills/`, so its
  duplicate copy under `starter/agent/skills/` is deleted

## What gets built

- New `openclaw/scripts/build-skills.mjs` compiles each skill's
  `src/index.ts` → `dist/index.js` using the exact compile flags the
  Dockerfile previously used (no `--strict` — skills use dynamic
  `await import('@xpr-agents/openclaw')` which resolves to `any` and
  would fail strict null checks)
- `openclaw/package.json` `build` now runs `build:plugin` then
  `build:skills`; `clean` clears `skills/*/dist`; `prepublishOnly` runs
  the full pipeline so npm-publish always ships fresh dist
- The 5 skills that import `@xpr-agents/openclaw` for `createCliApi`
  (defi, governance, lending, nft, xmd) get a `// @ts-ignore` on the
  dynamic-import line — the package can't self-reference at compile
  time, but Node resolves it fine at runtime through the consumer's
  node_modules

## What the runner does differently

- `openclaw/starter/agent/src/index.ts` swaps the 12 hardcoded
  `path.resolve(__dirname, '../skills/<name>')` lines for a
  `resolveSkillDir(name)` helper that uses
  `require.resolve('@xpr-agents/openclaw/package.json')` and falls
  back to a repo-relative path for monorepo dev
- `xpr-agent-operator` SKILL.md candidate list reorders to put the
  npm-package path first (was last)
- `/deliverables/:jobId` route now `require()`s the skill's `dist/`
  entry, not its TS source — fixes the silent fall-through on
  non-Docker installs

## What the Dockerfile drops

- Removed the 12-line tower of per-skill `npx tsc ...` commands.
  `npm install` now pulls in pre-built `dist/` from the npm package,
  so the Dockerfile just does `npm install && npm run build` like a
  normal Node service

## What the manifest declares

- `openclaw.plugin.json` `skills` array goes from 1 entry to 13.
  Harnesses that auto-load skills from the manifest will pick up all
  domain skills automatically

## What changes for harness users

- v0.3.x: install plugin → 72 tools, no skills. Domain capabilities
  (DeFi, NFT, etc.) silently absent unless you separately installed
  each ClawHub skill
- v0.4.0: install plugin → 72 tools + 13 skills, full agent
  capability out of the box. ClawHub installs are now additive, not
  required

## Verification

- All 13 skills compile under `npm run build:skills`
- All 80 openclaw tests pass
- 225 SDK tests pass; 81 indexer tests pass
- Runtime resolver probe confirms all 13 skill directories resolve via
  `require.resolve('@xpr-agents/openclaw/package.json')` with
  skill.json, SKILL.md, and dist/index.js present

## Added runtime dependency

- `@shellbook/sdk@^0.2.4` — required by the shellbook skill's
  `import { Shellbook } from '@shellbook/sdk'`. Previously hoisted
  from the agent runner's node_modules; now declared on the package
  that ships the skill
@paulgnz paulgnz merged commit 352cfd5 into main May 13, 2026
5 checks passed
@paulgnz paulgnz deleted the feat/tier-c-skills-in-npm branch May 13, 2026 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant