OpenSpec: Specs That Write Themselves (and Then Help You Build)
Most specifications live in Google Docs, Confluence pages, or Notion databases. They start strong — someone writes a detailed plan, the team reviews it, work begins. Then the code evolves, the spec doesn't, and within a few weeks the document describes a system that no longer exists.
OpenSpec takes a different approach. Specs live in your repository, in markdown, under version control. They change when the code changes. They're reviewed in the same pull requests as the code they describe. And because they're plain files in a known directory structure, tools can read them, write them, and reason about them programmatically.
What is OpenSpec?
OpenSpec is a convention for organizing project specifications as markdown files inside your codebase. There's no special syntax, no proprietary format, no CLI tool you need to install. It's a directory structure and a set of expectations about what goes where.
The structure looks like this:
openspec/
├── specs/ # Current state of each feature area
│ ├── authentication.md
│ ├── billing.md
│ └── notifications.md
└── changes/ # Proposed modifications
└── add-sso-support/
├── proposal.md # Goals and business value
├── design.md # Technical scope and architecture
└── tasks.md # Story breakdown with acceptance criteria
The specs/ directory describes what exists today. Each file covers a feature area — not a microservice, not an endpoint, but a coherent slice of your product's behavior. Authentication. Billing. Notifications. The goal is one spec per area, updated as the system evolves.
The changes/ directory describes what you're planning to build. Each subdirectory is a change proposal — a named unit of work with its rationale, technical design, and task breakdown. When the work ships, the relevant specs in specs/ get updated to reflect the new state.
Specs as code
The decision to put specs in the repo isn't cosmetic. It changes the dynamics of how specs get maintained.
When a spec lives in a wiki, updating it after a code change is a separate task — and it almost never happens. There's no enforcement mechanism, no review process, and no visible drift until someone reads the doc months later and realizes it's wrong.
When a spec lives in the repo, it shows up in diffs. A pull request that changes authentication behavior but doesn't touch openspec/specs/authentication.md is a visible omission. Reviewers can catch it. CI can flag it. The spec stays honest because the same forces that keep code honest — version control, pull requests, review — apply to it.
This also means specs have history. You can git blame a spec to see who changed it and when. You can diff the spec at the start of a quarter against the spec at the end. You can trace exactly when a business rule was added, modified, or removed — and which code changes accompanied it.
How ArcLume uses OpenSpec internally
ArcLume is built on AdonisJS with a Vue frontend, PostgreSQL with pgvector for embeddings, and Claude as the AI backbone. It's a non-trivial codebase with multiple services, background jobs, and integrations. We use OpenSpec to document our own architecture.
Our openspec/specs/ directory contains four files:
- auth-and-organizations.md — Documents the User + AuthIdentity separation pattern, OAuth flows, and role-based access control across organizations.
- ai-generation.md — Describes the generation pipeline: how transcripts and briefs become structured epics and stories, including the RAG retrieval strategy and Claude prompt architecture.
- codebase-indexing.md — Covers the full indexing pipeline: repository cloning, AST parsing, chunking, embedding generation, interface detection, and how the knowledge graph gets built.
- maps-and-stories.md — Defines the domain model: maps, epics, stories, outlines, and how they relate to each other and to external systems like Jira and Linear.
These aren't documentation for external consumption. They're working documents that we reference when planning new features, onboarding contributors, and — critically — when generating our own stories with ArcLume.
The feedback loop: specs that inform generation
Here's where it gets interesting. When ArcLume indexes a connected repository, it detects OpenSpec files by their directory path. Files in openspec/specs/ are tagged as spec chunks. Files in openspec/changes/ are tagged as change proposal chunks. Both are embedded alongside the rest of the codebase — but with a key difference.
During retrieval, OpenSpec chunks receive a relevance boost. When ArcLume assembles context for story generation, spec content surfaces ahead of generic code. If your repository has a spec describing how authentication works, that spec will appear in the context window when you're planning authentication-related work — even if the vector similarity to some random auth utility function would otherwise rank higher.
The effect is that specs act as a grounding layer. They tell the AI what the team has already decided: the domain vocabulary, the architectural boundaries, the assumptions that shouldn't be questioned. Stories generated against a codebase with good specs are noticeably better-scoped and more consistent with how the team actually thinks about the system.
We see this in our own usage. When we plan a new ArcLume feature using ArcLume, the generated stories reference the patterns described in our own OpenSpec files. The auth spec ensures new features follow the AuthIdentity pattern. The indexing spec ensures changes to the pipeline don't violate assumptions about chunk types. The specs don't constrain the AI — they calibrate it.
The write path: exporting to OpenSpec
Reading specs is half the loop. The other half is writing them.
Every map in ArcLume — the container for an epic and its stories — can be exported as an OpenSpec change proposal. The export generates three files:
- proposal.md — The epic's goals, business value, assumptions, and out-of-scope items. This is the "why" document that product and engineering align on before work begins.
- design.md — Technical scope, affected services and components, and acceptance criteria. This is the engineering spec that describes how the work will be structured.
- tasks.md — The full story breakdown with titles, descriptions, complexity estimates, labels, and acceptance criteria for each story.
The export downloads as a ZIP. You unzip it into your repo's openspec/changes/ directory, commit, and push. From that point forward, the change proposal is version-controlled, reviewable, and — on the next index — available as grounding context for future generation.
This creates a compounding loop. The more you use ArcLume to plan, the richer your OpenSpec directory becomes. The richer your specs, the better your next round of generation. The system gets smarter about your codebase over time — not because of some proprietary learning mechanism, but because your repository accumulates structured knowledge about itself.
What makes a good spec
Not every markdown file is a useful spec. The ones that improve generation quality share a few characteristics:
- Domain vocabulary. Define the terms your team uses. If your system has "workspaces" and "organizations" and they mean different things, say so. This prevents the AI from conflating concepts that look similar but aren't.
- Architectural boundaries. State what owns what. "The billing service is the only system that writes to the subscriptions table" is a single sentence that prevents an entire class of bad story generation.
- Business rules. Document the rules that aren't obvious from the code. "Free-tier organizations are limited to 3 connected repos" is a constraint that affects scoping, but you'd never infer it from reading a repository model.
- Key files. List the files that matter most for each feature area. This gives both humans and AI a starting point for navigation.
You don't need to be exhaustive. A 30-line spec that covers the domain model, the main business rules, and the key files for a feature area is more valuable than a 500-line document that tries to describe every endpoint.
Getting started
If you want to try OpenSpec in your own project — with or without ArcLume — the setup takes about five minutes:
- Create an
openspec/specs/directory in your repository root. - Pick one feature area you know well. Write a markdown file that covers: a one-paragraph summary, the domain model (key entities and their relationships), the important business rules, and 5-10 key file paths.
- Commit it. That's your first spec.
If you're using ArcLume, connect the repo and re-index. ArcLume automatically detects the OpenSpec directory and starts using your specs as grounding context. You'll notice the difference immediately in generation quality — stories will use your terminology, respect your architectural boundaries, and reference the right parts of the codebase.
If you're not using ArcLume, the specs still pull their weight. They're readable documentation that lives where engineers actually look — in the repo. They get reviewed alongside code. They accumulate institutional knowledge that would otherwise live in someone's head or a forgotten Confluence page.
Why this matters for your team
The core problem OpenSpec solves isn't documentation. It's alignment.
When a product manager writes "update the notification preferences," they have a mental model of what that means. The engineer who picks up that ticket has a different mental model — one informed by the actual code. The gap between those models is where rework, frustration, and missed deadlines live.
OpenSpec narrows that gap by giving both sides a shared reference point that's grounded in the system as it actually exists. The product manager can read the notifications spec and understand what's possible. The engineer can read the change proposal and understand what's intended. Neither has to guess.
Add ArcLume to the picture and the specs become active participants in the planning process. They inform generation, they're updated by exports, and they accumulate knowledge that makes every subsequent planning cycle faster and more accurate.
The best part is that you don't have to adopt everything at once. Start with one spec. See if it changes the conversation. If it does, write another. The value compounds.
Ready to try ArcLume?
ArcLume is currently in beta. Connect your repos, build a knowledge graph, and start generating codebase-aware epics and stories.
Join the Beta