Configuration

Spektacular (Spek) splits configuration across two files: a project's own .spektacular/config.yaml, which locates each member repository, and each member repository's .spektacular/repo.yaml, which describes it and says where its code lives.

Project configuration: config.yaml

A project’s own settings: the coding agent it drives, where it stores speks, plans, and changelog records, its shared knowledge stores, and the repositories it registers as members. Every project has exactly one .spektacular/config.yaml, at the root of the project. The file is created by spektacular init, missing keys fall back to defaults, and ${VAR} patterns are expanded from the environment when config.yaml or repo.yaml is read. A complete example, declaring one shared knowledge store alongside the store each registered repository brings with it:

schema: 4 # settings format version; `migrate` raises it
written_by: 0.16.0 # the Spektacular version that last wrote this file
skills_version: 0.16.0 # the Spektacular version that installed the agent skills
command: spektacular
agent: claude
spec_trigger_threshold: moderate
epic_split_threshold: moderate
auto_commit: "off" # off | workflow | full
debug:
enabled: false
spec:
provider: file
id_method: timestamp
config:
directory: specs # relative to the folder holding `config.yaml`
plan:
provider: file
config:
directory: plans
task_id:
provider: uuid # where plan task ids come from
changelog:
provider: file
config:
directory: changelog
epic:
provider: file
strict_dependencies: false # true refuses to implement past an unmet dependency
config:
directory: epics # created the first time an epic is written
knowledge:
sources: # the project's shared stores only; each
- name: team # repository declares its own in repo.yaml
provider: file
config:
location: ${HOME}/work/team-knowledge # or ../../team-knowledge,
# relative to this file
design:
sources: # where the project's design documents live;
- name: api # declared by the project, never by a repository
provider: file
config:
location: ../design/api # relative to this file; may sit outside the project
repos:
- name: docs
location: ../../docs/.spektacular

Project configuration keys

Sixteen top-level keys control the tool from .spektacular/config.yaml: schema, written_by, skills_version, command, agent, spec_trigger_threshold, epic_split_threshold, auto_commit, debug, spec, plan, changelog, epic, knowledge, design, and repos.

schema integer
default: written by Spektacular

The settings format version. Never edit it by hand; migrate raises it. A file with no schema is read as the oldest format and needs an upgrade, as described under Upgrading a project below.

written_by string
default: written by Spektacular

The Spek version that last saved this file. Informational only: it never triggers an upgrade, so a file written by a different version of the same format is left alone.

skills_version string
default: written by Spektacular

The Spek version that last installed your agent skills. Only init and migrate set it, so rewriting the file for any other reason, registering a repository for example, leaves it untouched. When it differs from the running Spek, commands stop until you upgrade.

command string
default: spektacular

The CLI command name used in agent-generated documentation. Almost never needs to change, kept configurable so downstream tooling can refer to a different binary name if your team wraps the tool.

agent string
default: set by spektacular init

Which coding agent to drive during the implement workflow. Supported values: claude (Claude Code), bob, codex, and omp (oh-my-pi). New agents register via the Agent plugin interface.

On shared projects, each spektacular init <agent> records that agent here. Migration refreshes only the recorded agent’s files, leaving other agents’ copies behind. After upgrading, run spektacular init once for each agent to refresh every copy; otherwise omp may list both current and stale skills.

spec_trigger_threshold string
default: moderate

How readily the agent offers to capture an open-ended discussion as a spek mid-conversation, rather than waiting for you to run /spek-new. One of strict (only substantial, multi-requirement features), moderate (default: a clear scoped decision or a feature with more than one requirement), or lenient (offers readily, including small fixes). Read live at the moment the agent decides whether to offer, so a change here takes effect immediately, mid-conversation.

epic_split_threshold string
default: moderate

How readily the agent offers to split a complete spek that turns out to be more than one piece of work into an epic. One of strict (only on a strong signal, such as requirements that fall into groups that could each ship alone), moderate (default: one strong signal, or two weak signals together), or lenient (one strong signal or a single weak signal is enough). Separate from spec_trigger_threshold, and never a stand-in for it. At every level the agent must still name at least two speks that can each be verified on their own, and code plus its docs, tests or config is always one spek. Read live at the moment the agent decides whether to offer, so a change here takes effect immediately.

auto_commit string
default: off

Whether Spek records the agent’s work in git for you. One of off (default: no automatic commits), workflow (one commit in each changed repository when a spek, plan or implementation completes), or full (as workflow, plus a commit after each milestone of an implementation). Commits use your own git, run your hooks, use your identity and signing settings, and are never pushed. When it is on and a registered repository has uncommitted changes as a workflow starts, the agent asks whether to commit them first. A repository that isn’t a git repository is skipped.

debug section
default: debug.enabled: false

Debug logging. Set debug.enabled: true to write a JSONL log of every command to .spektacular/debug/session-log.jsonl, useful when reporting issues or developing a new plugin. See the Debugging page for the full walkthrough.

spec section
default: file provider, timestamp IDs, specs

How speks are stored and identified.

  • spec.provider: storage backend; only file ships today.
  • spec.id_method: spek naming scheme. One of timestamp (default), counter (sequential numbers), or external (the caller supplies an id with each spek).
  • spec.config.directory: where the file provider writes speks. Defaults to specs, relative to the folder holding config.yaml (the same rule as repos[].location), so speks land in .spektacular/specs. A directory outside the project is refused.

Every spek record also carries lifecycle metadata: a created date, a document status, and, once resolved, a closed date, tracked automatically without any extra configuration.

Locations the CLI reports for speks, such as a list’s path, are relative to the folder holding config.yaml, for example specs/<name>.md. Speks are addressed by name, never by this location: see Documents.

plan section
default: file provider, plans

How plans are stored.

  • plan.provider: storage backend; only file ships today.
  • plan.config.directory: where the file provider writes plans. Defaults to plans, relative to the folder holding config.yaml, so plans land in .spektacular/plans.
  • plan.task_id.provider: where task identifiers come from; uuid (default) issues random UUIDs. See Plan tasks.

Every plan record also carries lifecycle metadata: a created date, a document status, and, once resolved, a closed date, tracked automatically without any extra configuration.

Locations the CLI reports for plan documents, such as a list’s path or the status plan_path, are relative to the folder holding config.yaml, for example plans/<name>/plan.md. Plan documents are addressed by the feature name and a document name, never by this location: see Documents.

changelog section
default: file provider, changelog

How completed-feature changelog records are stored.

  • changelog.provider: storage backend; only file ships today.
  • changelog.config.directory: where the file provider writes changelog records. Defaults to changelog, relative to the folder holding config.yaml, so records land in .spektacular/changelog.

A record is written automatically at the end of every implement run, one flat markdown file per feature, covering what was built, why it matters, and how the outcome differed from the plan. Every changelog record also carries the same lifecycle metadata as speks and plans: a created date, a document status, and, once resolved, a closed date.

Locations the CLI reports for changelog records, such as a list’s path, are relative to the folder holding config.yaml, for example changelog/<name>.md. Records are addressed by name, never by this location: see Documents.

epic section
default: file provider, warn on unmet dependencies, epics

How epics are stored, and how implementation treats a dependency between an epic’s speks that is not implemented yet.

  • epic.provider: storage backend; only file ships today.
  • epic.strict_dependencies: what happens when you start implementing a spek whose dependencies are not all implemented. false (default) warns, names each unmet dependency and its state, and lets you continue, recording the override in the changelog. true refuses, and offers to implement the first unmet dependency that is ready instead.
  • epic.config.directory: where the file provider writes epics. Defaults to epics, relative to the folder holding config.yaml, so epics land in .spektacular/epics. The directory is created the first time an epic is written, never by init. A directory outside the project is refused.

init writes this section for new projects and migrate adds it to existing ones. Using epics stays optional: a project that never splits a spek sees no change in behaviour.

knowledge section
default: none

Ordered list of the shared knowledge stores the project itself owns, such as a team handbook. Each repository declares its own store in its repo.yaml, not here.

  • knowledge.sources[].name: the name this store is addressed by. Must be unique among the project’s own stores.
  • knowledge.sources[].provider: storage backend; only file ships today.
  • knowledge.sources[].config.location: where the file provider reads knowledge from. Relative paths resolve from the folder holding config.yaml, the same base a repos entry uses.
design section
default: none

Ordered list of the design sources the project declares. A design document holds the worked design a feature is built to, and a spek references one rather than restating it. Design sources are declared by the project only; a repository does not declare its own.

  • design.sources[].name: the name this source is addressed by. Must be unique among the project’s design sources.
  • design.sources[].provider: storage backend; only file ships today.
  • design.sources[].config.location: where the file provider reads and writes design documents. Relative paths resolve from the folder holding config.yaml, the same base a repos entry uses. The location may sit outside the project, and is never rewritten on save.

A source can hold both kinds of design document side by side. A design your team already had is stored exactly as supplied, gaining no frontmatter and never being reformatted; a design Spek authors with you carries the same lifecycle record every spek and plan carries.

See the Design Documents page for the full reference.

repos section
default: none

How a project registers its member repositories. Each entry names one repository and locates the folder that holds the repository’s own repo.yaml:

  • repos[].name: the repository’s project-local name, unique within this project and slug-safe; plans and changelog entries refer to repositories by it.
  • repos[].location: the folder holding the repository’s repo.yaml, absolute or relative to the folder holding this config.yaml. Nothing is appended to it, so the project’s own footprint is . and a repository folder inside the project is ../repos/<name>. The older local key is still accepted and means the same thing; it is written back as location.
  • repos[].provider: the repository’s provider. Only git ships today.
  • repos[].dependencies: the project-local names of other registered repositories this one depends on.

Where the repository’s code lives is the repository’s own concern, declared by source in its repo.yaml (below). The older address key is no longer accepted here: a configuration that still carries it fails to load with an error naming the repository, and its value moves to that repository’s source.

A repository’s description, role, and tags are not declared here either. They live in the repository’s own configuration file, described below.

Repository configuration: repo.yaml

What a member repository is: its description, role, tags, where its code lives, and its own knowledge sources and changelog provider. Every member repository carries its own repo.yaml, distinct from the project’s own .spektacular/config.yaml above. The folder holding that file is the repository’s location, and the source key says where its code is, relative to that same folder. It is created as part of the repository’s footprint, either when it is registered with repo add or during a project’s initialization cascade over its already-registered repositories. It carries no reference back to any project that registers it, so the same repository can belong to any number of projects while describing itself in exactly one place. A complete example, for a documentation site:

schema: 2 # settings format version; `migrate` raises it
written_by: 0.16.0 # the Spektacular version that last wrote this file
description: Marketing and documentation site, built with Astro
role: documentation
tags:
- docs
- website
source:
provider: file # file or git
config:
location: .. # or git@github.com:org/docs.git for git
knowledge:
provider: file
config:
location: knowledge
changelog:
provider: file
config:
directory: changelog

Repository configuration keys

Descriptive metadata, the location of the repository’s code, and the repository’s own knowledge sources and changelog provider, shown wherever this repository’s details are surfaced, such as spektacular repo list or the repository roster an agent sees during planning and implementation. Every relative path in this file, the source included, resolves from the folder holding the file.

schema integer
default: written by Spektacular

The settings format version of this repo.yaml, on its own count: a repository file at format 2 sits beside a project file at format 3. migrate raises it for every registered repository present on disk.

written_by string
default: written by Spektacular

The Spek version that last saved this file, for diagnosis only.

description string
default: none

A short account of what this repository is or does.

role string
default: none

The role this repository plays, such as service, documentation, or library.

tags list of strings
default: none

Free-form labels for the repository, such as docs, website, or backend.

source string
default: the directory holding .spektacular/

Where this repository’s code lives. Either a file location (a plain path or a file:// path, absolute, relative to the directory holding repo.yaml, or using ${VAR}) or a git location (git://, ssh://, https://, or user@host:path). A git location is cloned into the project’s .spektacular/repos/<name>/ folder the first time the repository is used and never fetched or pulled afterwards. When set, repo list reports it as the repository’s root and workflows send agents there; knowledge and changelog entries still land where this file’s knowledge and changelog keys say, under the folder holding repo.yaml. Leave it unset when the repository’s Spek files sit inside its code. Not to be confused with the project-level source in config.yaml, which records a git address for changelog provenance only.

knowledge section
default: a file store at knowledge

This repository’s single knowledge store, holding what is true of its own code. The store is addressed by the name the project registered this repository under, so there is no name to set here and no more than one store to declare.

  • knowledge.provider: storage backend; only file ships today.
  • knowledge.config.location: where the file provider reads this repository’s knowledge from. Relative paths resolve against the folder holding repo.yaml.

See the Knowledge Base page for the full reference.

changelog section
default: file provider, changelog

Same shape as the project-level changelog key above, resolved from the folder holding this file; this is where the repository’s own derived changelog entries land.

Upgrading a project: migrate

Every settings file records the format version it was written in. When a release changes that format, or when you install a newer Spek than the one that installed your agent skills, commands stop with an error naming migrate until the project is brought up to date. migrate, init, version check and help always run, so the way out is always reachable.

Preview every change first, which touches nothing on disk:

Terminal window
spektacular migrate --dry-run

Then apply it:

Terminal window
spektacular migrate

One run:

  • upgrades config.yaml and every registered repository’s repo.yaml present on disk, through as many formats as each file is behind
  • keeps a .v<N>.old copy of each file it rewrites, named after the format the file started at
  • adds settings a newer format introduced, with their defaults, while keeping any value you already set: moving to format 4 adds epic_split_threshold: moderate and the epic section (provider file, strict_dependencies: false, directory epics)
  • skips repositories that are not checked out locally and names each one; they are upgraded the next time they are set up
  • reinstalls the agent skills when they are older than the running Spektacular, and records the new version only once that install succeeds

Re-running spektacular init <agent> applies the same upgrades before it does anything else, so an existing project can also be brought current by setting it up again. A file written by a newer Spek is refused rather than converted: the error asks you to update Spek, and the file is never rewritten.

Pluggable by design

Speks, plans, knowledge, and agents are all behind plugin interfaces. See what ships today and what's planned.