Repository navigation
Commands and Skills are nearly duplicated after init — maintenance drift risk in team workflows #1139
Description
Commands and Skills are nearly duplicated after init — maintenance drift risk in team workflows
Problem
After running openspec init (v1.3.1), both commands/opsx/*.md and skills/openspec-*/SKILL.md are generated with nearly identical content. The only differences are:
- Frontmatter: Skills have extra metadata (
author,version,generatedBy,compatibility,description-zh) - Minor content variations: A few rules differ slightly between the two copies
This creates a real maintenance problem in team collaboration scenarios.
Reproduction
# After init, compare the two files:
diff commands/opsx/apply.md skills/openspec-apply-change/SKILL.mdResult: 167 lines vs 167 lines, with differences only in frontmatter and 2-3 rule lines.
Same for propose: 124 lines vs 123 lines.
Why this matters for teams
In our monorepo, the team needs to customize rules for our specific tech stack. The customization workflow becomes ambiguous:
- If we customize
commands/opsx/: The skills won't reflect our rules, and the nextopenspec updatemay overwrite our changes. - If we customize
skills/openspec-*/: Runningopenspec initagain or onboarding a new machine will regenerate commands without our customizations. - If we customize both: We now have two copies to keep in sync manually — which will inevitably drift.
In our case, the commands already drifted from skills after one round of team customization:
| File pair | Commands (lines) | Skills (lines) | Content drift |
|---|---|---|---|
| apply | 167 | 167 | 3 rules differ |
| propose | 124 | 123 | 2 rules differ |
The drift includes substantive rule differences — for example, commands contain team-specific enforcement rules (agent-memory checks, comment discipline, real verification commands) that are absent from skills, while skills contain additional UI spec routing logic (domestic spec loading) that commands lack.
Suggested solutions
Any of the following would work:
Option A: Skills reference commands (preferred)
Skills become thin wrappers that point to commands:
# skills/openspec-apply-change/SKILL.md
---
name: openspec-apply-change
description: Implement tasks from an OpenSpec change
---
Execute according to `.claude/commands/opsx/apply.md`.
Additional skill-specific constraints:
- [only list deltas]This is the lightest change upstream and lets teams maintain a single source of truth in commands while skills serve as a discovery/trigger layer.
Option B: Single source of truth with a generation step
openspec init generates only commands. A separate openspec sync-skills command derives skills from commands + a skills-delta.yaml config that teams maintain for skill-specific metadata and overrides.
Option C: Merge-aware update
openspec update detects local modifications and prompts the user to resolve conflicts (similar to git merge), instead of silently overwriting. This would protect both commands and skills from losing team customizations.
Environment
- OpenSpec CLI: 1.3.1
- Claude Code: latest
- Repo: pnpm monorepo with 3 apps + shared packages
- Team size: 5+ developers collaborating on the same
.claude/config
Activity
fix(templates): deduplicate apply skill and command instructions (Fis…
clay-good commentedon Aug 5, 2026
Thanks for the write-up, @panboDing. Generating both a command file and a skill file isn't a duplication bug — they're separate surfaces for different agent tools, and OpenSpec lets you choose between them.
If you don't want both files: set a delivery mode with
openspec config→ Skills only, Commands only, or Both.To customize the workflow instructions: don't edit the generated files —
openspec updateregenerates and overwrites them. Put your customizations inopenspec/config.yamlinstead, which is the single source of truth and survives updates:context— your tech stack and conventionsrules:— per-artifact rulesoperations.apply.guidance/operations.archive.guidance— advisory guidance for apply/archiveSee docs/customization.md.
Separately, your observation about the two bodies being nearly identical was fair on our end — #1515 consolidates the internal template source so the skill and command share one definition, removing the drift risk inside OpenSpec itself. That's an internal cleanup and doesn't change what's generated into your project; the guidance above is still how you customize.
Closing as answered. If there's a customization
config.yamlcan't express, please open a narrower issue with that specific gap.