Skip to content

Commit fe234c3

Browse files
Sergio SisternesCopilot
andcommitted
feat: add openclaw as experimental skills target
Add OpenClaw (github.com/openclaw/openclaw) as an experimental deployment target for skills. Once enabled via 'apm experimental enable openclaw', users can deploy SKILL.md bundles to: project scope: .agents/skills/<name>/SKILL.md user scope: ~/.openclaw/skills/<name>/SKILL.md (--global) At project scope the output is identical to agent-skills; the --global user path (~/.openclaw/skills/) is the distinguishing capability -- it maps to OpenClaw's priority-4 managed skill loading directory. Changes: - Register ExperimentalFlag 'openclaw' in FLAGS - Add KNOWN_TARGETS['openclaw'] TargetProfile - Wire into EXPERIMENTAL_TARGETS, get_target_description(), _CROSS_TARGET_MAPS, and enable-hint UX block - Update exact-set guardian tests - Add 25 new tests (E2E, constants, flags, profile, description, cross-target-map) - Update targets-matrix docs and apm-usage commands.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d6c2928 commit fe234c3

10 files changed

Lines changed: 418 additions & 6 deletions

File tree

docs/src/content/docs/reference/targets-matrix.md

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ Skills deploy to `.agents/skills/` for Copilot, Cursor, OpenCode,
3232
Gemini, and Codex by default (see [Skills convergence](#skills-convergence)
3333
below). Claude and Windsurf keep target-native skill directories.
3434

35-
`copilot-cowork` (Microsoft 365 Copilot) and `copilot-app` (GitHub
36-
Copilot desktop App) are gated behind experimental flags and not listed
37-
above. See [Experimental](./experimental/).
35+
`copilot-cowork` (Microsoft 365 Copilot), `copilot-app` (GitHub
36+
Copilot desktop App), and `openclaw` (OpenClaw agent runtime) are
37+
gated behind experimental flags and not listed above. See
38+
[Experimental](./experimental/).
3839

3940
## Detection and resolution
4041

@@ -61,7 +62,7 @@ list before `compile` or `install`.
6162
| opencode | `.opencode/` directory |
6263
| windsurf | `.windsurf/` directory |
6364

64-
`agent-skills`, `copilot-cowork`, and `copilot-app` are never
65+
`agent-skills`, `copilot-cowork`, `copilot-app`, and `openclaw` are never
6566
auto-detected. Select them explicitly with `--target`, or list them in
6667
a project's `apm.yml` `targets:` field so contributors running plain
6768
`apm install` pick them up automatically.
@@ -177,6 +178,23 @@ Cross-client shared skills directory.
177178
- **File conventions.** `.agents/skills/<name>/SKILL.md`.
178179
- **Use case.** Author-time target for shipping a SKILL bundle that any Skills-aware client (Codex, Copilot CLI, Claude Code, etc.) can read without per-tool deployment.
179180

181+
## openclaw (experimental)
182+
183+
[OpenClaw](https://github.com/openclaw/openclaw) agent runtime.
184+
185+
- **Detection.** Never auto-detected. Select with `--target openclaw`
186+
after enabling the experimental flag.
187+
- **Enable.** `apm experimental enable openclaw`.
188+
- **Deploy directory.** `.agents/skills/` at project scope (identical to
189+
`agent-skills`); `~/.openclaw/skills/` at user scope (`--global`).
190+
- **Supported primitives.** skills only.
191+
- **File conventions.** `.agents/skills/<name>/SKILL.md` (project) or
192+
`~/.openclaw/skills/<name>/SKILL.md` (user).
193+
- **Note.** At project scope the output is identical to `agent-skills`.
194+
The `--global` user path is the distinguishing capability, deploying
195+
skills where OpenClaw reads its managed/local skill directory
196+
(priority 4 in the OpenClaw loading order).
197+
180198
## Skills convergence
181199

182200
By default, every target with a `skills` primitive deploys to `.agents/skills/<name>/SKILL.md` rather than under the target root. This matches the cross-tool agent skills convention so a single skill bundle serves every harness.

packages/apm-guide/.apm/skills/apm-usage/commands.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ Use `apm experimental enable copilot-cowork` to turn on Microsoft 365 Copilot Co
179179

180180
Use `apm experimental enable copilot-app` to turn on GitHub Copilot desktop App workflow deployment. Once enabled, prompts that carry workflow frontmatter -- any flat top-level key of `interval`, `schedule_hour`, `schedule_day` -- can be deployed to the App's SQLite store at `~/.copilot/data.db` with `apm install --target copilot-app` (project scope) or `--target copilot-app --global` (user scope). A `.prompt.md` belongs to exactly ONE surface: workflow-shape prompts go to the App DB, plain prompts go to slash-command targets. Rows always start `enabled = 0` -- you opt in from the App. `apm install / update / uninstall` preserve user state (`enabled`, `last_run_at`, schedule overrides). Override the database path with `APM_COPILOT_APP_DB=<abs-path>`. Workflows are scoped to a real Copilot App project: when the App is running APM registers the project over the App's loopback WebSocket so the project is immediately known to the webview; when the App is closed APM falls back to a direct-SQLite `BEGIN IMMEDIATE` resolver. The first install in a brand-new repo prints a one-time "restart the Copilot App once" hint (see github/github-app#5483); subsequent installs are silent. `--global` installs that carry workflow-shape prompts warn-and-proceed because workflows run with `CWD=~/.copilot` rather than a repo -- attach the row to a project from the App's Workflows tab to fix.
181181

182+
Use `apm experimental enable openclaw` to turn on OpenClaw agent runtime skill deployment. Once enabled, deploy skills with `apm install --target openclaw` (project scope, `.agents/skills/`) or `apm install --target openclaw --global` (user scope, `~/.openclaw/skills/`). At project scope, output is identical to `agent-skills`; the `--global` user path is the distinguishing capability.
183+
182184
### Cross-client skills (`agent-skills`)
183185

184186
Use `--target agent-skills` to deploy skills to `.agents/skills/` -- the cross-tool standard directory. This is useful when multiple clients (Codex, future tools) read from `.agents/skills/`. Unlike `--target all`, `agent-skills` must be requested explicitly: `apm install --target agent-skills` or `apm install --target all,agent-skills` for both. `apm compile --target agent-skills` is a no-op (skills-only target).

src/apm_cli/bundle/lockfile_enrichment.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
"agent-skills": {
5353
".github/skills/": ".agents/skills/",
5454
},
55+
"openclaw": {
56+
".github/skills/": ".agents/skills/",
57+
},
5558
}
5659

5760

src/apm_cli/core/experimental.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ class ExperimentalFlag:
107107
"See https://microsoft.github.io/apm/integrations/external-scanners/"
108108
),
109109
),
110+
"openclaw": ExperimentalFlag(
111+
name="openclaw",
112+
description="Deploy skills to OpenClaw agent runtime directories.",
113+
default=False,
114+
hint=(
115+
"Use '--target openclaw' to deploy skills to your project, "
116+
"or '--target openclaw --global' for your personal OpenClaw "
117+
"skills at ~/.openclaw/skills/."
118+
),
119+
),
110120
}
111121

112122

src/apm_cli/core/target_detection.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ def get_target_description(target: UserTargetType) -> str:
300300
"gemini": "GEMINI.md + .gemini/commands/ + .gemini/skills/ + .gemini/settings.json (MCP/hooks)",
301301
"windsurf": "AGENTS.md + .windsurf/rules/ + .windsurf/skills/ + .windsurf/workflows/ + .windsurf/hooks.json",
302302
"agent-skills": ".agents/skills/ only (cross-client shared skills -- no agents, hooks, or commands)",
303+
"openclaw": ".agents/skills/ (project) or ~/.openclaw/skills/ (--global) -- experimental",
303304
"all": "AGENTS.md + CLAUDE.md + GEMINI.md + .github/copilot-instructions.md + .github/ + .claude/ + .cursor/ + .opencode/ + .codex/ + .gemini/ + .windsurf/ + .agents/",
304305
"minimal": "AGENTS.md only (create .github/, .claude/, or .gemini/ for full integration)",
305306
}
@@ -320,7 +321,7 @@ def get_target_description(target: UserTargetType) -> str:
320321
#: ``is_enabled()`` in ``core/experimental.py`` and ``_flag_gated()`` in
321322
#: ``integration/targets.py``. They are NOT included in the
322323
#: ``parse_target_arg("all")`` expansion -- explicit opt-in only.
323-
EXPERIMENTAL_TARGETS: frozenset[str] = frozenset({"copilot-cowork", "copilot-app"})
324+
EXPERIMENTAL_TARGETS: frozenset[str] = frozenset({"copilot-cowork", "copilot-app", "openclaw"})
324325

325326
#: Stable targets excluded from "all" expansion (cross-client deploy
326327
#: locations). Unlike EXPERIMENTAL_TARGETS, these are GA -- they just do

src/apm_cli/install/phases/targets.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,30 @@ def run(ctx: InstallContext) -> None:
324324
# restart is needed; the SQLite path is the fallback for the
325325
# App-closed case (still the common case during install).
326326

327+
# ------------------------------------------------------------------
328+
# OpenClaw target gating: explicit --target openclaw with the flag
329+
# OFF must hint at the experimental enable command.
330+
# ------------------------------------------------------------------
331+
_user_asked_openclaw = False
332+
if _explicit:
333+
if isinstance(_explicit, list):
334+
_user_asked_openclaw = "openclaw" in _explicit
335+
else:
336+
_user_asked_openclaw = _explicit == "openclaw"
337+
338+
if _user_asked_openclaw:
339+
_openclaw_resolved = any(t.name == "openclaw" for t in _targets)
340+
if not _openclaw_resolved:
341+
from apm_cli.core.experimental import is_enabled as _is_flag_on
342+
343+
if not _is_flag_on("openclaw"):
344+
if ctx.logger:
345+
ctx.logger.progress(
346+
"The 'openclaw' target requires an experimental flag. "
347+
"Run: apm experimental enable openclaw",
348+
symbol="info",
349+
)
350+
327351
# ------------------------------------------------------------------
328352
# v2 resolution (#1154): signal-based provenance and strict errors.
329353
# Runs AFTER the legacy resolver and cowork gates so existing

src/apm_cli/integration/targets.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,31 @@ def for_scope(self, user_scope: bool = False) -> TargetProfile | None:
609609
user_root_dir=".agents",
610610
generated_files=(),
611611
),
612+
# OpenClaw -- experimental, skills-only target for the OpenClaw agent
613+
# runtime (github.com/openclaw/openclaw). OpenClaw reads SKILL.md
614+
# directories from several locations; APM deploys to:
615+
# project scope: <workspace>/.agents/skills/ (agentskills.io standard,
616+
# OpenClaw priority-2 load path)
617+
# user scope: ~/.openclaw/skills/ (OpenClaw managed dir, priority-4)
618+
# At project scope the output is identical to the agent-skills target;
619+
# the --global user path is the distinguishing capability.
620+
# Ref: https://docs.openclaw.ai/tools/skills
621+
"openclaw": TargetProfile(
622+
name="openclaw",
623+
root_dir=".agents",
624+
primitives={
625+
"skills": PrimitiveMapping(
626+
"skills",
627+
"/SKILL.md",
628+
"skill_standard",
629+
),
630+
},
631+
auto_create=True,
632+
detect_by_dir=False,
633+
user_supported=True,
634+
user_root_dir=".openclaw",
635+
requires_flag="openclaw",
636+
),
612637
# Microsoft 365 Copilot (Cowork) -- experimental, user-scope only.
613638
# Skills are deployed to <OneDrive>/Documents/Cowork/skills/.
614639
# The deploy root is resolved dynamically at runtime via

0 commit comments

Comments
 (0)