docs/design/daemon-skill-toggle.md
Expose the CLI /skills panel's workspace enable/disable behavior through daemon REST and the TypeScript SDK, including immediate refresh of active ACP sessions.
POST /workspace/skills/:name/enablePOST /workspaces/:workspace/skills/:name/enable{ "enabled": boolean }DaemonClient.setWorkspaceSkillEnabled and WorkspaceDaemonClient.setWorkspaceSkillEnabledworkspace_skill_toggleThe response contains the canonical skill name, requested state, whether persistence changed, activation state, and session refresh counts. applied means every active session refreshed, deferred means no ACP child was running, and partial means at least one session failed to refresh after persistence committed.
The API changes workspace skills.disabled and skills.enabled as needed. Skill lookup is case-insensitive, but the canonical discovered name is persisted. Enabling a default-disabled skill writes an explicit opt-in; disabling it removes the opt-in and writes a hard workspace disable. Updating one target removes target duplicates and case variants without deleting orphan entries for unavailable skills. A second identical request is a no-op.
The route rejects states the CLI panel cannot toggle:
404 skill_not_found;userInvocable === false: 409 skill_not_toggleable;409 skill_not_toggleable;409 skill_not_toggleable with the locking scope;403 untrusted_workspace.The scope lock check and workspace read-modify-write happen inside the daemon's per-workspace settings lock. A failed write stops before refresh and event publication.
disable-model-invocationskills.disabled is an operator hard denylist merged as a case-insensitive union across scopes. skills.defaultDisabled supplies overridable defaults and skills.enabled supplies explicit opt-ins, with disabled > enabled > defaultDisabled precedence. Effective disables remove matching skill slash commands and model-visible skill entries, and execution-time validation rejects the skill. The daemon endpoint writes the workspace members of disabled and enabled.
disable-model-invocation is SKILL.md metadata. It hides a skill from model invocation while preserving direct user invocation. The existing managed-skill ACP operation edits that metadata and is intentionally not reused by this API.
qwen/control/workspace/skills/refresh.available_commands_update, and notifies SkillManager consumers.settings_changed event for each changed skill-settings key.An in-flight model request cannot be rewritten. Subsequent skill execution checks, command snapshots, and model contexts read the new state.
disabled > enabled > defaultDisabled precedence.userInvocable.settings_changed consumers observe each committed skills.disabled or skills.enabled value; there is no new event type.deferred; the next child loads the setting at startup.partial.deferred; other refresh failures are reported as partial.