OpenSpec Architecture: File-System Store and Spec-Driven Development Engine

OpenSpec is a spec-driven development platform built around a file-system-based store that separates system specifications from active changes, orchestrating AI-assisted workflows through a TypeScript core engine and CLI interface.

The Fission-AI/OpenSpec repository implements a spec-driven development methodology using a structured file system layout and modular TypeScript architecture. This platform sits between developers and AI assistants, managing the complete lifecycle of system changes—from proposal to implementation—through YAML and markdown specifications.

File-System Store Layout

OpenSpec architecture centers on a file-system-based store that organizes work into distinct directories separating the system state from active development.

The store maintains three primary locations:

  • openspec/specs/ — The single source of truth containing YAML and markdown files that describe the current state of the entire system.
  • openspec/changes/ — A workspace for a single change containing proposals, delta specs, design documents, tasks, and implementation artifacts.
  • openspec/changes/archive/Archived changes that have been merged; once a change completes, its delta specs fold back into specs/ and the folder moves here.

This layout enforces a clear separation between canonical specifications and work-in-progress changes, enabling the platform to track the high-level flow:


proposal → specs → design → tasks → implement

Core Architecture Components

The OpenSpec architecture consists of eight interconnected modules that handle everything from store initialization to command execution.

Root Management

The Root Management module detects, validates, and creates the OpenSpec store layout. In src/core/openspec-root.ts, the system defines constants such as OPENSPEC_ROOT_DIR and OPENSPEC_SPECS_DIR, alongside functions inspectOpenSpecRoot and ensureOpenSpecRoot that enforce the required directory structure and validate store integrity.

Global Configuration

Global user settings—including profiles and AI tool configurations—are managed through src/core/global-config.ts. This module is re-exported from src/index.ts to provide user-wide settings that persist across projects.

Artifact Graph

The Artifact Graph models relationships between specifications, designs, tasks, and other artifacts while resolving dependencies. Core files include src/core/artifact-graph/graph.ts, src/core/artifact-graph/resolver.ts, and src/core/artifact-graph/outputs.ts. This graph structure enables the system to understand how changes in one specification affect related components.

Parsers

The Parsers module converts markdown and spec files into typed objects consumed by the engine. Key implementations reside in src/core/parsers/markdown-parser.ts, src/core/parsers/change-parser.ts, and src/core/parsers/requirement-blocks.ts, transforming human-readable specifications into structured data.

Command Generation

Dynamic CLI command construction happens in the Command Generation module. The file src/core/command-generation/generator.ts builds commands like opsx:propose and opsx:apply based on the selected workflow schema, automatically registering new workflows added to src/core/schemas/.

Store and Persistence

File-system operations are abstracted through the Store module in src/core/store/registry.ts, src/core/store/index.ts, and src/core/store/git.ts. This registry pattern supports multiple storage backends while providing consistent interfaces for reading, writing, and versioning specifications and changes.

CLI Layer

The user-facing interface is built on commander in src/cli/index.ts. This entry point registers top-level commands including init, list, view, change, and validate, wiring them to the appropriate core services and command classes such as ListCommand, ChangeCommand, and ValidateCommand.

Telemetry

Optional usage analytics are handled by src/telemetry/index.ts, providing insights into command usage and workflow patterns without compromising the local-first architecture.

How OpenSpec Components Work Together

The OpenSpec architecture follows a predictable lifecycle for bootstrapping projects and managing changes.

Bootstrapping begins with openspec init, implemented in src/core/init.ts, which calls ensureOpenSpecRoot to create the store layout, write a default config.yaml, and optionally anchor empty directories to ensure version control compatibility.

Command Dispatch flows through the CLI layer, which parses arguments, resolves the store root via resolveRootForCommand, and invokes the appropriate command class to execute user requests.

Change Lifecycle management creates new changes under openspec/changes/<name>/. The AI generates proposals and delta specs stored as markdown files. Upon completion, the ArchiveCommand merges these deltas into the main specs/ directory and moves the change folder to openspec/changes/archive/.

Validation occurs through src/core/validation/validator.ts, which walks the artifact graph, validates requirements against schemas, and produces JSON or human-readable reports ensuring specification integrity before implementation.

Extensibility is achieved by adding new workflow schemas to src/core/schemas/, which automatically become available to the CLI via the command-generation pipeline without modifying core command logic.

Working with OpenSpec Programmatically

You can interact with the OpenSpec architecture directly through its TypeScript API.

Inspecting the Store Programmatically

import { inspectOpenSpecRoot, ensureOpenSpecRoot } from
  'https://github.com/Fission-AI/OpenSpec/blob/main/src/core/openspec-root.ts';

// Inspect an existing store
const inspection = await inspectOpenSpecRoot('/my/project');
console.log(inspection);

// Ensure a store exists (creates missing directories/files)
const result = await ensureOpenSpecRoot('/my/project', { anchorEmptyDirectories: true });
console.log(result.createdArtifacts);

Resolving the Artifact Graph

import { resolveArtifactGraph } from
  'https://github.com/Fission-AI/OpenSpec/blob/main/src/core/artifact-graph/resolver.ts';

const graph = await resolveArtifactGraph('/my/project');
const spec = graph.getSpec('auth/login');
console.log(spec);

Common CLI Workflows


# Initialise a repository (creates openspec/ and config.yaml)

openspec init

# List all active changes

openspec list

# Propose a new change (AI drafts proposal, specs, design, tasks)

openspec propose add-dark-mode

# Apply the generated tasks (AI writes code)

openspec apply

# Archive the completed change (merges deltas into main specs)

openspec archive

Summary

  • OpenSpec architecture separates canonical specifications (openspec/specs/) from active changes (openspec/changes/) using a file-system-based store.
  • Eight core modules handle root management, configuration, artifact graphs, parsing, command generation, persistence, CLI interaction, and telemetry.
  • The change lifecycle follows a spec-driven workflow: proposal → specs → design → tasks → implement → archive.
  • Key files like src/core/openspec-root.ts, src/core/artifact-graph/graph.ts, and src/cli/index.ts form the backbone of the TypeScript implementation.
  • Extensibility is built into the architecture through schema-based command generation and a registry pattern for store backends.

Frequently Asked Questions

How does OpenSpec maintain consistency between specs and implementation?

OpenSpec treats openspec/specs/ as the single source of truth while isolating work-in-progress in openspec/changes/. The ArchiveCommand ensures atomic merging of delta specs into the main directory only after validation passes, preventing drift between specifications and actual system state.

What is the role of the Artifact Graph in OpenSpec architecture?

The Artifact Graph, implemented in src/core/artifact-graph/graph.ts and src/core/artifact-graph/resolver.ts, maintains a dependency graph between specifications, designs, and tasks. It enables the system to resolve relationships, validate requirement blocks, and determine the correct order of operations when applying changes.

Can OpenSpec work with different storage backends?

Yes. While the default implementation uses the local file system, the Store module in src/core/store/registry.ts abstracts persistence operations through a registry pattern. This allows the architecture to support alternative backends such as Git-based storage or remote APIs without modifying the core engine logic.

How does the command generation system support custom workflows?

The command generation system in src/core/command-generation/generator.ts dynamically constructs CLI commands by reading workflow schemas from src/core/schemas/. Adding a new workflow automatically exposes commands like opsx:propose and opsx:apply specific to that schema, enabling domain-specific development patterns without rebuilding the CLI.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →