You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
User-global custom skills/commands (with override precedence, like schemas) #757
OpenSpec currently lets users customize project artifact workflows via schemas, but does not provide a way to add or override tool-specific commands/skills (such as /openspec-team-apply-change) without patching project code or package templates.
This feature would introduce OS-specific global directories (e.g. ~/.config/openspec/commands, ~/.config/openspec/skills), enabling a user to define custom commands/skills that OpenSpec overlays onto generated tool integrations. If a global version and a built-in version share a name, the user's version takes precedence. These global skills/commands would be placed in the appropriate tool-specific folders (.claude/commands, .claude/skills, etc.) when running openspec init or openspec update.
Motivation
Teams and individuals often need new commands or workflow skills (e.g., a new team orchestration action) without modifying package code or copying project files.
Built-in OpenSpec templates are not extensible, so custom commands/skills must be managed separately.
A global override mechanism—mirroring schemas—lets users safely customize, share, and shadow built-in commands.
This would improve portability, shareability, and maintainability for advanced workflows and integrations.
Acceptance Criteria
User can define custom skills/commands in OS-specific global directories such as ~/.config/openspec/skills or ~/.config/openspec/commands.
Global custom skills/commands are automatically copied and overlaid on top of generated built-in commands during openspec init/openspec update.
If a global skill/command matches the name of a built-in, the global version wins (shadowing).
Skills/commands are validated before installation to avoid breaking tool integrations.
CLI tooling supports listing, discovering, and editing global vs project vs package skills.
References & Design Details
Precedence: project-local overrides (future), then user-global, then package built-in. Same name = override.
Possible directory structure:
~/.config/openspec/skills/<name>
~/.config/openspec/commands/<name>
Would support use cases like /openspec-team-apply-change and user-specific customizations.
The enrichment comment has been posted on issue #757. Here's a summary of what was included:
Existing precedent: The codebase already has a three-tier schema override system (resolver.ts:63-91) with project-local > user-global > package built-in precedence, using XDG directories (global-config.ts:66-87). This pattern directly informs how skills/commands overrides should work.
Current architecture: Skills/commands are generated from hardcoded TypeScript templates in src/core/templates/workflows/ with no external discovery mechanism. Key integration points for the feature are in skill-generation.ts, init.ts, and update.ts.
Suggested approach: Mirror the schema resolver pattern -- add getUserSkillsDir()/getUserCommandsDir() functions, create a merge layer in getSkillTemplates() that discovers user-global overrides, and validate user files against existing interfaces.
Related issues: Linked 6 related open issues including #752 (global install), #756 (user-level schemas), #689 (standard skills folder), #590 (packaged skills), #611 (context bloat), and #350 (custom paths).
Design question input: Noted that the existing workflows array in GlobalConfig already provides a disable mechanism for built-in skills, and that the SKILL.md YAML frontmatter format could serve as the canonical format for user-defined skills.
Thanks for the detailed proposal, @askpatrickw. Here's an analysis of the existing codebase to help inform implementation.
Existing Precedent: Schema Override System
OpenSpec already implements a three-tier precedence system for schemas that this feature would mirror. The resolution logic is in src/core/artifact-graph/resolver.ts:63-91:
The listSchemasWithInfo() function in resolver.ts:224-302 already tracks source: 'project' | 'user' | 'package' and which schemas shadow others. This pattern can be directly reused for skills/commands.
Current Skills/Commands Architecture
Skills and commands are generated from hardcoded TypeScript template functions in src/core/templates/workflows/ (11 workflows). There is no mechanism to discover or load external skill/command definitions.
getUserSkillsDir() / getUserCommandsDir() in global-config.ts
A getSkillTemplatesWithOverrides() function that:
Loads built-in templates from src/core/templates/workflows/
Scans user-global directory for overrides/additions
Merges with user-global taking precedence on name match
3. Integration points - The main changes would be in:
src/core/shared/skill-generation.ts - Add user-global skill discovery to getSkillTemplates()
src/core/init.ts:517-527 - Merge user-global templates before generation
src/core/update.ts:170-171 - Same merge in update flow
src/commands/schema.ts - Model for a potential openspec skill which / openspec skill list command
4. Validation - Parse and validate user-provided SKILL.md files against the SkillTemplate interface before overlay (similar to resolveSchema() in resolver.ts:109-153 which validates via Zod).
Related Issues
Several open issues are directly related or would benefit from this work:
Re: Deletion/masking - The schema system doesn't currently support disabling/tombstoning a built-in. Options:
A disabled field in ~/.config/openspec/config.json (extends GlobalConfig interface in global-config.ts:15-20)
A tombstone file convention (e.g., ~/.local/share/openspec/skills/openspec-explore/.disabled)
Leveraging the existing workflows array in GlobalConfig - users already can filter which workflows are active via openspec config profile
Option 3 is notable because the workflows filter in GlobalConfig already controls which skills get generated. A user wanting to "disable" a built-in skill could simply remove it from their workflow list. Custom skills would need a separate mechanism.
Re: Project-local overrides - The schema system already supports this tier (getProjectSchemasDir() in resolver.ts:44-46). Adding project-local skills/commands would complete the three-tier model: project > user-global > package.
Re: Skill file format - User-defined skills would need a parseable format. The existing SKILL.md with YAML frontmatter (as generated by generateSkillContent() in skill-generation.ts:127-149) could serve as the canonical format for user-defined skills too.
Activity
21st-connector commentedon Feb 24, 2026
Task completed.
The enrichment comment has been posted on issue #757. Here's a summary of what was included:
Existing precedent: The codebase already has a three-tier schema override system (
resolver.ts:63-91) with project-local > user-global > package built-in precedence, using XDG directories (global-config.ts:66-87). This pattern directly informs how skills/commands overrides should work.Current architecture: Skills/commands are generated from hardcoded TypeScript templates in
src/core/templates/workflows/with no external discovery mechanism. Key integration points for the feature are inskill-generation.ts,init.ts, andupdate.ts.Suggested approach: Mirror the schema resolver pattern -- add
getUserSkillsDir()/getUserCommandsDir()functions, create a merge layer ingetSkillTemplates()that discovers user-global overrides, and validate user files against existing interfaces.Related issues: Linked 6 related open issues including #752 (global install), #756 (user-level schemas), #689 (standard skills folder), #590 (packaged skills), #611 (context bloat), and #350 (custom paths).
Design question input: Noted that the existing
workflowsarray inGlobalConfigalready provides a disable mechanism for built-in skills, and that the SKILL.md YAML frontmatter format could serve as the canonical format for user-defined skills.View full conversation
Powered by 1Code
21st-connector commentedon Feb 24, 2026
Issue Enrichment: Codebase Analysis
Thanks for the detailed proposal, @askpatrickw. Here's an analysis of the existing codebase to help inform implementation.
Existing Precedent: Schema Override System
OpenSpec already implements a three-tier precedence system for schemas that this feature would mirror. The resolution logic is in
src/core/artifact-graph/resolver.ts:63-91:Global directory paths are defined in
src/core/global-config.ts:66-87using XDG Base Directory Specification:~/.local/share/openspec/(viaXDG_DATA_HOME)%LOCALAPPDATA%/openspec/The
listSchemasWithInfo()function inresolver.ts:224-302already trackssource: 'project' | 'user' | 'package'and which schemas shadow others. This pattern can be directly reused for skills/commands.Current Skills/Commands Architecture
Skills and commands are generated from hardcoded TypeScript template functions in
src/core/templates/workflows/(11 workflows). There is no mechanism to discover or load external skill/command definitions.Key files involved in generation:
src/core/shared/skill-generation.tsgetSkillTemplates(),getCommandContents(),generateSkillContent()src/core/command-generation/generator.tsgenerateCommands()using tool-specific adapterssrc/core/command-generation/registry.tsCommandAdapterRegistry- 24 tool adapterssrc/core/init.ts:499-597generateSkillsAndCommands()- init flowsrc/core/update.ts:170-244Generation flow:
src/core/global-config.ts)src/core/profiles.ts)SKILL.mdfiles and tool-specific command files via adaptersSkills currently use a
SkillTemplateinterface (src/core/templates/types.ts):Commands use a
CommandContentinterface (src/core/command-generation/types.ts):Suggested Implementation Approach
Based on the existing architecture, a natural approach would be:
1. Global directories (following schema pattern from
global-config.ts):2. Resolution functions (mirror
resolver.tspattern):getUserSkillsDir()/getUserCommandsDir()inglobal-config.tsgetSkillTemplatesWithOverrides()function that:src/core/templates/workflows/3. Integration points - The main changes would be in:
src/core/shared/skill-generation.ts- Add user-global skill discovery togetSkillTemplates()src/core/init.ts:517-527- Merge user-global templates before generationsrc/core/update.ts:170-171- Same merge in update flowsrc/commands/schema.ts- Model for a potentialopenspec skill which/openspec skill listcommand4. Validation - Parse and validate user-provided SKILL.md files against the
SkillTemplateinterface before overlay (similar toresolveSchema()inresolver.ts:109-153which validates via Zod).Related Issues
Several open issues are directly related or would benefit from this work:
openspec init --global: Install skills and commands to tool global directories #752 -openspec init --global: Install skills and commands to tool global directories (complementary - addresses tool-global install, this addresses user-global definitions)--useroption toopenspec schema initfor user-level schemas #756 - Add--useroption toopenspec schema initfor user-level schemas (same pattern, schema side).agent/skillsfolder for all agents that support it #689 - Proposal: use a standard.agent/skillsfolder for all agents (related standardization)openspec initOpen Design Questions
Re: Deletion/masking - The schema system doesn't currently support disabling/tombstoning a built-in. Options:
disabledfield in~/.config/openspec/config.json(extendsGlobalConfiginterface inglobal-config.ts:15-20)~/.local/share/openspec/skills/openspec-explore/.disabled)workflowsarray inGlobalConfig- users already can filter which workflows are active viaopenspec config profileOption 3 is notable because the
workflowsfilter inGlobalConfigalready controls which skills get generated. A user wanting to "disable" a built-in skill could simply remove it from their workflow list. Custom skills would need a separate mechanism.Re: Project-local overrides - The schema system already supports this tier (
getProjectSchemasDir()inresolver.ts:44-46). Adding project-local skills/commands would complete the three-tier model: project > user-global > package.Re: Skill file format - User-defined skills would need a parseable format. The existing SKILL.md with YAML frontmatter (as generated by
generateSkillContent()inskill-generation.ts:127-149) could serve as the canonical format for user-defined skills too.askpatrickw commentedon Feb 26, 2026
I no longer think this is needed. Use a tool like Skillshare to roll out skills globally across all agents and all developers.