feat: skill install config sync with workspace detection#643
Conversation
compileOpenClawConfig accepts an optional installedSkillSlugs param. When provided and non-empty, each agent gets a skills field with the list. When empty or undefined the field is omitted so OpenClaw falls back to auto-discovering all skills from extraDirs (legacy compat).
Wire onSyncNeeded callback through SkillhubService so the OpenClaw config is recompiled whenever a skill finishes installing or a queued install is cancelled. Also add explicit syncAll calls in the uninstall and import routes for immediate sync on those HTTP paths.
Add "workspace" to SkillSource union and agentId field to SkillRecord for tracking agent-installed skills from clawhub. Update upsertRecord matching to use agentId for workspace source disambiguation. Add getInstalledByAgent query method and update API route schemas.
Extend SkillDirWatcher to scan per-agent workspace skill directories during syncNow(), recording workspace skills in the ledger with source: "workspace" and the appropriate agentId. Shared-dir reconciliation now excludes workspace records to prevent false uninstall marking.
…Name - Add agentId to InstalledSkill type - Add agentId and agentName to skillhub catalog response schema - CatalogManager resolves SKILL.md from workspace agent dir for workspace skills - Route handler resolves agentName from current bot config (not stored in DB) - Non-workspace skills return agentId: null, agentName: null
Add "Agent Skills" sub-tab under "Yours" tab that displays workspace skills grouped by agent name. Extends SkillSource type with "workspace" and InstalledSkill with agentId/agentName fields. Includes en/zh-CN i18n.
clawhub install creates symlinks in workspace/skills/ pointing to .agents/skills/. Node's isDirectory() returns false for symlinks, so the scanner missed them. Now checks isSymbolicLink() too.
The Installed tab now shows custom shared skills at top and workspace skills grouped by agent name below. Also fixes inspector script to detect symlinked skill directories.
- Remove separate Agent Skills tab - Show workspace skills grouped by agent below custom skills in Installed tab - Display agent ID in workspace skill group headers - Fix installed count to separate custom vs workspace
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07401a325d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…pace skills The uninstall endpoint now accepts optional source and agentId fields. For workspace skills, agentId identifies which agent's installation to remove. Shared skill uninstall (slug-only) remains backward compatible.
Deploying nexu-docs with
|
| Latest commit: |
7543d37
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6b9dca16.nexu-docs.pages.dev |
| Branch Preview URL: | https://feat-skill-install-config-sy.nexu-docs.pages.dev |
|
/cr |
|
✅ CR topic created in Feishu topic group Refly CR. |
JiwaniZakir
left a comment
There was a problem hiding this comment.
The mutable syncService variable in container.ts (initialized as null, then assigned after openclawSyncService is constructed) is a workaround for a circular dependency between SkillhubService and OpenClawSyncService. This pattern is fragile — if the callback fires before syncService is assigned (unlikely here given synchronous construction, but non-obvious), it silently no-ops. More importantly, the .catch(() => {}) in the onSyncNeeded callback completely swallows sync errors with no logging, which will make debugging sync failures difficult in production. At minimum, a console.error or structured log call should be added there.
In openclaw-config-compiler.ts, the merged array uses new Set for deduplication, which is correct, but the ordering guarantee (shared slugs before workspace slugs) is implicit — if skill loading order matters for conflict resolution downstream, that assumption should be documented or enforced explicitly.
In openapi.json, agentId and agentName are listed in the required array while also marked nullable: true. Technically valid in JSON Schema, but it means consumers must always include these fields even when their value is null. It's worth confirming this is intentional rather than agentId/agentName being truly optional fields that should be omitted from required.
Add "user" source type to the skill system so skills installed via clawhub CLI in ~/.agents/skills/ are tracked in the ledger and included in the OpenClaw allowlist. Also simplify symlink detection by relying on existsSync (which follows symlinks) instead of explicit isSymbolicLink() checks.
|
What
When skills are installed/uninstalled/imported, immediately sync the OpenClaw config with an explicit per-agent skills allowlist — so agents detect skill changes within seconds instead of relying on the unreliable extraDirs file watcher.
Why
The bug: Skill files were installed to disk, but OpenClaw never loaded them. The agent couldn't detect new skills for 31+ minutes because:
syncAll()triggered after skill install/uninstall/importskillsallowlist on agentsextraDirs)Additionally, when agents install skills via
clawhub installin conversation, those workspace skills were invisible to Nexu's skill ledger, config allowlist, and UI.How
Phase 1: Shared Skill Config Sync
skills?: string[]to agent config schema (OpenClaw already supports it)skillsfieldsyncAll()triggered after every install/uninstall/import viaonSyncNeededcallbackskillsfield is omitted so OpenClaw auto-discovers all skills fromextraDirsPhase 2: Workspace Skills & Upgrade Compatibility
"workspace"source andagentIdfieldWorkspaceSkillScannerscansagents/*/skills/directories per agentSkillDirWatcherreconciles workspace skills on startup (populates ledger from disk)clawhub installcreates symlinks in workspace)agentIdandagentNameon installed skillsPhase 3: UI
Key design decisions
[...new Set([...sharedSlugs, ...workspaceSlugs])]— each agent gets shared skills + its own workspace skillsagentNameresolved at request time (not stored in DB) so renames propagate instantlyAffected areas
Checklist
pnpm typecheckpassespnpm lintpasses (changed files clean; pre-existing failures unrelated)pnpm testpasses (105 tests pass; 13 pre-existing failures on main)pnpm generate-typesrun (API schema changes)anytypes introducedTest plan
Automated tests (30+ new)
Manual tests (all passed on packaged build)
Notes for reviewers
scripts/test-skill-sync.mjsis a diagnostic inspector for manual testing — runnode scripts/test-skill-sync.mjsto see ledger, config, and workspace state at a glanceopenclaw-config-writer.test.ts,openclaw-sync.test.ts,route-compat.test.ts, andmodel-provider-service.test.tsare onmain— not introduced by this PR