Use It Programmatically
Parse, validate, traverse, and convert specs in code. The @blacksmithers/openspec package gives you typed access to everything in the spec.
Install as a dependency
Add the package to your project:
$ npm install @blacksmithers/openspecThe CLI is also available globally:
$ npm install -g @blacksmithers/openspecParse any format
The parser handles JSON, YAML, and TOON. You get back a typed OpenSpec object regardless of the source format:
import { parse, detectFormat, toJson, toYaml, toToon } from '@blacksmithers/openspec';
// Parse a string — auto-detects format
const spec = parse(fileContents);
// Detect which format a string is in
const format = detectFormat(fileContents);
// 'json' | 'yaml' | 'toon'
// Convert a parsed spec back to any format
const json = toJson(spec);
const yaml = toYaml(spec);
const toon = toToon(spec);Validate
Programmatic validation returns structured results you can act on:
import { validate, validateWithSchema } from '@blacksmithers/openspec';
const result = validate(spec);
if (result.valid) {
console.log('Spec is valid');
} else {
for (const error of result.errors) {
console.error(`[${error.path}] ${error.message}`);
// [/specifications/0/epics/0/tickets/0] must have required property 'status'
}
}
// Validate against a specific schema version
const schemaResult = validateWithSchema(spec, schemaObject);The ValidationResult type gives you valid, errors, and warnings — all fully typed.
Traverse the hierarchy
Walk specs, epics, tickets, and blueprints without manual nesting:
import {
getSpecifications,
getEpics,
getTickets,
getBlueprints,
getAllTicketsMap,
findTicketById,
findTicketByNumber,
findByStatus,
findByTag,
} from '@blacksmithers/openspec';
// Get all specifications from a parsed spec
const specifications = getSpecifications(spec);
// Get all epics across specifications
const epics = getEpics(spec);
// Get all tickets across all epics and specifications
const tickets = getTickets(spec);
// Get all blueprints
const blueprints = getBlueprints(spec);
// Build a map of ticketId → Ticket for fast lookups
const ticketMap = getAllTicketsMap(spec);
// Find a specific ticket by ID or number
const ticket = findTicketById(spec, 'ticket-create-todo');
const ticketByNum = findTicketByNumber(spec, 42);
// Filter tickets by status or tag
const openTickets = findByStatus(spec, 'open');
const apiTickets = findByTag(spec, 'api');Resolve the dependency graph
Build a dependency graph and query it for actionable tickets, blocked tickets, or execution waves:
import {
resolveDependencyGraph,
getReadyTickets,
getBlockedTickets,
getExecutionWaves,
resolvePatterns,
} from '@blacksmithers/openspec';
// Build the full dependency graph
const graph = resolveDependencyGraph(spec);
// What can be worked on right now?
const ready = getReadyTickets(spec);
// [{ id: 'ticket-create-todo', ... }]
// What is blocked and why?
const blocked = getBlockedTickets(spec);
// [{ id: 'ticket-list-todos', blockedBy: ['ticket-create-todo'] }, ...]
// Get execution waves — groups of tickets that can run in parallel
const waves = getExecutionWaves(spec);
// [[ticket-create-todo], [ticket-list-todos, ticket-delete-todo]]
// Resolve inherited patterns for a specification
const patterns = resolvePatterns(spec, 'spec-todo-api');Types
All core types are exported for use in your own tools:
import type {
OpenSpec,
Project,
Specification,
Epic,
Ticket,
Blueprint,
Patterns,
ValidationResult,
} from '@blacksmithers/openspec';
// Full type safety when working with specs
function processTicket(ticket: Ticket): void {
console.log(ticket.id, ticket.title, ticket.status);
}
function buildDashboard(spec: OpenSpec): void {
const project: Project = spec.project;
const specifications: Specification[] = spec.specifications;
// ...
}What you can build
OpenSpec is an open format. Here are some things people are building with the library:
Agent Orchestrators
Feed the dependency graph to an agent scheduler. Each agent picks up ready tickets, marks them done, and unblocks the next wave.
Project Dashboards
Parse the spec and render progress by epic, spec, or ticket status. No database required — the spec file is the source of truth.
CI Validators
Block merges when the spec has circular dependencies, dangling references, or missing required fields. Shift left on spec quality.
Code Generators
Read blueprint schemas and ticket acceptance criteria to scaffold boilerplate — routes, models, tests — directly from the spec.
That's the full tour. You have a spec, it validates, and you can work with it in code. The format is open, the tooling is yours to extend.