Why
Working implementation: #660
Related to: #581
OpenSpec currently assumes a flat spec structure (specs/{capability}/spec.md) where each capability is a direct subdirectory under specs/. This works for simple projects but becomes limiting as projects grow. Teams need hierarchical organization for:
- Domain-driven design: Grouping specs by bounded context (
specs/payments/checkout/spec.md, specs/auth/oauth/spec.md)
- Monorepos: Organizing specs by package or scope (
specs/packages/core/spec.md)
- Cross-cutting concerns: Separating global specs from feature-specific ones (
specs/_global/testing/spec.md vs specs/features/export/spec.md)
- Team namespaces: Large teams organizing specs by ownership (
specs/team-platform/infra/spec.md)
- Scale: Projects with 50+ specs become unmanageable in a flat structure
Commands like openspec list --specs, validation, sync, and archive fail to discover or work with hierarchically organized specs, forcing teams to use workarounds or manual processes.
What Changes
- Core spec discovery: Implement recursive search for
spec.md files at any depth, replacing the current single-level directory scan
- Capability naming: Change capability identifier from directory name to full relative path from
specs/ (e.g., _global/testing instead of just testing)
- Delta mapping: Enable 1:1 path-based mapping between change deltas and main specs using replicated directory structure
- Configuration: Add optional
specStructure section in openspec/config.yaml or globally in ~/.config/openspec/config.json to control structure mode, depth limits, and validation behavior
structure: 'flat' | 'hierarchical' | 'auto' (default: auto - auto-detect)
maxDepth: Maximum hierarchy depth (default: 4, recommended: 2-3)
allowMixed: Allow mixing flat and hierarchical specs (default: true)
validatePaths: Enforce naming conventions (default: true)
- Display: Update
list and view commands to show hierarchical specs
- Validation: Add validation rules to prevent orphaned specs (no spec.md at intermediate levels), enforce depth limits (warn at 4, hard limit at 10), and check naming conventions (lowercase alphanumeric with hyphens/underscores)
- Backward compatibility: Auto-detect flat vs hierarchical structure and support both transparently
- Templates: Update all skill prompts and templates to reference specs using relative paths
- Commands: Adapt
list, validate, sync, archive commands to work with hierarchical paths
Benefits:
- Better organization: Group related specs by domain, team, or concern rather than forcing flat structure
- Domain-driven design: Natural alignment with bounded contexts and domain models
- Monorepo support: Organize specs by package, scope, or workspace
- Scalability: Projects with 50+ specs remain navigable and maintainable
- Team collaboration: Large teams can namespace their specs to avoid conflicts
- Cross-cutting separation: Distinguish global concerns (
_global/, shared/, utils/) from feature-specific specs
- Code alignment: Spec structure can mirror code structure when beneficial
- No workarounds: Eliminates need for custom schemas or hacks
- Optional strictness: Configuration for validation during migrations or in large teams
- Zero configuration: Works automatically with auto-detection, no setup required
- Full compatibility: Existing flat projects continue working unchanged
Examples
Directory structures
Flat (current behavior):
openspec/specs/
auth/spec.md
api/spec.md
payments/spec.md
notifications/spec.md
Hierarchical (new):
openspec/specs/
_global/
testing/spec.md # cross-cutting: testing standards
security/spec.md # cross-cutting: security requirements
monitoring/spec.md # cross-cutting: monitoring
platform/
services/
api/spec.md # service: API
auth/spec.md # service: authentication
database/spec.md # service: database
infrastructure/
deployment/spec.md # infra: deployment
scaling/spec.md # infra: scaling
frontend/
components/
forms/spec.md
navigation/spec.md
state-management/spec.md
Mixed (flat + hierarchical coexist):
openspec/specs/
auth/spec.md # flat (depth 1)
payments/spec.md # flat (depth 1)
_global/
testing/spec.md # hierarchical (depth 2)
security/spec.md # hierarchical (depth 2)
platform/
services/
api/spec.md # hierarchical (depth 3)
Change deltas mirror main structure 1:1
openspec/changes/add-rate-limiting/
proposal.md
specs/
platform/
services/
api/spec.md # delta for platform/services/api
_global/
security/spec.md # delta for _global/security
CLI works with full paths
openspec validate platform/services/api # validate a deep spec
openspec validate _global/testing # validate a global spec
openspec validate --specs # validate all (auto-discovers)
openspec list --specs # list all with grouping
Output example (openspec list --specs)
Specs:
_global/adr-workflow 18 requirements
_global/architecture 12 requirements
_global/testing 8 requirements
dev/mcp-server 23 requirements
dev/mcp-context-builder 14 requirements
pel/expression-language 6 requirements
Configuration (optional, works without it)
In openspec/config.yaml:
specStructure:
structure: auto # auto | flat | hierarchical
maxDepth: 4 # max nesting depth (1-10)
allowMixed: true # allow flat + hierarchical together
validatePaths: true # enforce naming conventions
Or globally in ~/.config/openspec/config.json:
{
"specStructure": {
"structure": "auto",
"maxDepth": 4,
"allowMixed": true,
"validatePaths": true
}
}
Why
Working implementation: #660
Related to: #581
OpenSpec currently assumes a flat spec structure (
specs/{capability}/spec.md) where each capability is a direct subdirectory underspecs/. This works for simple projects but becomes limiting as projects grow. Teams need hierarchical organization for:specs/payments/checkout/spec.md,specs/auth/oauth/spec.md)specs/packages/core/spec.md)specs/_global/testing/spec.mdvsspecs/features/export/spec.md)specs/team-platform/infra/spec.md)Commands like
openspec list --specs, validation, sync, and archive fail to discover or work with hierarchically organized specs, forcing teams to use workarounds or manual processes.What Changes
spec.mdfiles at any depth, replacing the current single-level directory scanspecs/(e.g.,_global/testinginstead of justtesting)specStructuresection inopenspec/config.yamlor globally in~/.config/openspec/config.jsonto control structure mode, depth limits, and validation behaviorstructure:'flat'|'hierarchical'|'auto'(default:auto- auto-detect)maxDepth: Maximum hierarchy depth (default:4, recommended:2-3)allowMixed: Allow mixing flat and hierarchical specs (default:true)validatePaths: Enforce naming conventions (default:true)listandviewcommands to show hierarchical specslist,validate,sync,archivecommands to work with hierarchical pathsBenefits:
_global/,shared/,utils/) from feature-specific specsExamples
Directory structures
Flat (current behavior):
Hierarchical (new):
Mixed (flat + hierarchical coexist):
Change deltas mirror main structure 1:1
CLI works with full paths
Output example (
openspec list --specs)Configuration (optional, works without it)
In
openspec/config.yaml:Or globally in
~/.config/openspec/config.json:{ "specStructure": { "structure": "auto", "maxDepth": 4, "allowMixed": true, "validatePaths": true } }