Note: The CLI is optional. The primary interface for Specora Core is your LLM coding agent (Claude Code, Cursor, Windsurf). The LLM reads
CLAUDE.mdand calls Python functions directly – no CLI needed. The CLI exists for CI/CD pipelines, shell scripts, and users who prefer terminal commands. For every CLI command below, the equivalent Python API call is documented in CLAUDE.md.
Complete reference for every command, subcommand, option, and flag in the Specora Core CLI.
# Clone the repository
git clone https://github.com/syndicalt/specora-core.git
cd specora-core
# Install with all extras (recommended)
pip install -e ".[all]"
The project defines four optional dependency groups:
| Extra | Installs | Purpose |
|---|---|---|
dev |
pytest, ruff | Testing and linting |
llm |
openai, anthropic, httpx | LLM-powered Factory and Healer features |
healer |
fastapi, uvicorn, httpx | Healer HTTP service |
all |
All of the above | Everything |
# Minimal (Forge only -- no LLM features)
pip install -e .
# With LLM support (Factory commands)
pip install -e ".[llm]"
# With Healer HTTP service
pip install -e ".[healer]"
# Everything
pip install -e ".[all]"
spc available globallyWhen installed inside a virtual environment, spc only works while that venv is active. To use it from any directory:
Option A: Install into system Python
deactivate # exit any active venv
pip install -e "path/to/specora-core[all]"
Option B: PowerShell alias (add to $PROFILE)
function spc { python -m forge.cli.main @args }
Option C: Use python -m directly
python -m forge.cli.main forge validate domains/my_app
python -m forge.cli.main healer fix domains/my_app
ModuleNotFoundErrorIf you see ModuleNotFoundError: No module named 'extractor' (or healer, factory, etc.):
pip install -e ".[all]" from the specora-core directory. New packages (like extractor) require a reinstall.$env:PYTHONPATH = "C:\path\to\specora-core" (PowerShell) or PYTHONPATH=/path/to/specora-core (bash).spc --help
Expected output:
Usage: spc [OPTIONS] COMMAND [ARGS]...
Specora Core -- Contract-Driven Development Engine.
Build applications from declarative specifications. Run with no arguments to
start the interactive REPL.
Options:
-v, --verbose Enable debug logging
--help Show this message and exit.
Commands:
diff Contract diff tracking.
extract Reverse-engineer a codebase into Specora contracts.
factory The Factory -- conversational contract authoring (LLM-powered).
forge The compiler and code generation pipeline.
healer The Healer -- self-healing contract pipeline.
init Scaffold a new domain with starter contracts.
Five minutes from zero to working contracts:
# 1. Install
pip install -e ".[all]"
# 2. Scaffold a new domain
spc init my_app
# 3. Validate contracts
spc forge validate domains/my_app
# 4. Compile to IR (verify it works)
spc forge compile domains/my_app
# 5. Generate code
spc forge generate domains/my_app
# 6. Inspect generated files
ls runtime/
For the LLM-powered experience, set an API key and use the Factory:
export ANTHROPIC_API_KEY="sk-ant-..."
spc factory new
Two entry points are registered in pyproject.toml:
| Command | Entry Point | Notes |
|---|---|---|
specora-core |
forge.cli.main:cli |
Full name |
spc |
forge.cli.main:cli |
Short alias (recommended) |
You can also invoke the CLI via Python module:
python -m forge.cli.main [COMMAND] [OPTIONS]
All three invocations are identical. This document uses spc throughout.
Run spc with no arguments to enter the interactive REPL:
spc
The REPL shows a branded welcome screen with:
The prompt is a magenta > character. Type slash commands or natural language.
All REPL slash commands and their mappings:
| Slash Command | CLI Equivalent | Description |
|---|---|---|
/validate [path] |
spc forge validate [path] |
Validate contracts against meta-schemas |
/compile [path] |
spc forge compile [path] |
Compile contracts to IR |
/generate [path] |
spc forge generate [path] |
Generate code from contracts |
/graph [path] |
spc forge graph [path] |
Show dependency graph |
/new |
spc factory new |
Bootstrap a new domain (interview) |
/add <kind> -d <domain> -n <name> |
spc factory add ... |
Add a single contract |
/explain <path> |
spc factory explain <path> |
Explain a contract in plain English |
/refine <path> <instruction> |
spc factory refine ... |
Modify a contract via natural language |
/chat [--domain <d>] |
spc factory chat ... |
Agentic domain conversation |
/heal [path] |
spc healer fix [path] |
Auto-fix validation errors |
/status |
spc healer status |
Healer queue status |
/tickets |
spc healer tickets |
List healer tickets |
/history |
spc healer history |
Healer fix history |
/visualize [path] |
spc factory visualize [path] |
Generate Mermaid diagrams |
/migrate <file> -d <domain> |
spc factory migrate ... |
Import from OpenAPI/SQL/Prisma |
/extract <path> [--domain <d>] |
spc extract ... |
Reverse-engineer codebase into contracts |
/help |
N/A | Show the help table |
/clear |
N/A | Clear the screen and re-show welcome |
/exit |
N/A | Exit the REPL |
! <cmd> |
N/A | Run a shell command (e.g., ! ls domains/) |
The REPL provides tab completion for all slash commands. Start typing / and press Tab to see available commands.
Command history is persisted to ~/.specora/history. Use the up/down arrow keys to navigate previous commands. History persists across sessions.
The REPL shows ghost-text suggestions from your command history as you type (via AutoSuggestFromHistory). Press the right arrow key to accept a suggestion.
Any input that does not start with / or ! is routed through the LLM agent. The agent interprets your intent and maps it to the appropriate CLI command. This requires an LLM provider to be configured (see Environment Variables).
Examples:
> validate my library contracts
(routes to: forge validate domains/library)
> show me the dependency graph
(routes to: forge graph domains/)
> create a new entity called review in the library domain
(routes to: factory add entity -d library -n review)
| Key | Action |
|---|---|
Ctrl+C |
Cancel current input (does not exit) |
Ctrl+D or EOF |
Exit the REPL |
| Up/Down arrows | Navigate command history |
| Right arrow | Accept auto-suggestion |
| Tab | Trigger completion |
Usage: spc [OPTIONS] COMMAND [ARGS]...
Specora Core -- Contract-Driven Development Engine.
Build applications from declarative specifications. Run with no arguments to
start the interactive REPL.
Options:
-v, --verbose Enable debug logging
--help Show this message and exit.
Commands:
diff Contract diff tracking.
extract Reverse-engineer a codebase into Specora contracts.
factory The Factory -- conversational contract authoring (LLM-powered).
forge The compiler and code generation pipeline.
healer The Healer -- self-healing contract pipeline.
init Scaffold a new domain with starter contracts.
| Option | Type | Default | Description |
|---|---|---|---|
-v, --verbose |
Flag | false |
Enable debug-level logging via Rich handler. Shows detailed log output from all subsystems. |
--help |
Flag | N/A | Show help message and exit. |
When invoked with no subcommand (spc alone), the CLI launches the interactive REPL. This is controlled by invoke_without_command=True on the root group.
The Forge is the deterministic compiler pipeline. It reads .contract.yaml files, validates them, compiles them into an Intermediate Representation (IR), and generates code.
Usage: spc forge [OPTIONS] COMMAND [ARGS]...
The compiler and code generation pipeline.
Options:
--help Show this message and exit.
Commands:
compile Compile contracts into IR.
generate Compile contracts and generate code.
graph Display the contract dependency graph.
validate Validate all contracts against their meta-schemas.
Validate all contracts against their meta-schemas.
Usage: spc forge validate [OPTIONS] [PATH]
Validate all contracts against their meta-schemas.
Checks that every .contract.yaml file conforms to its kind's meta-schema.
Reports all errors and warnings with human-readable messages and suggested
fixes.
Options:
--output [text|json] Output format
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory or the top-level domains/ directory. All .contract.yaml files under this path are discovered and validated. |
| Option | Type | Default | Description |
|---|---|---|---|
--output |
Choice: text, json |
text |
Output format. text produces rich terminal output with colors. json produces machine-readable JSON. |
| Code | Meaning |
|---|---|
| 0 | All contracts are valid (may have warnings) |
| 1 | One or more validation errors found, or contracts could not be loaded |
When --output json is used:
{
"valid": true,
"contract_count": 12,
"errors": [],
"warnings": [
{
"fqn": "entity/library/book",
"path": "spec.fields.isbn",
"message": "Field 'isbn' has no description",
"severity": "warning"
}
]
}
# Validate all domains
spc forge validate
# Validate a specific domain
spc forge validate domains/library
# Get JSON output for CI pipelines
spc forge validate domains/library --output json
# Validate and pipe to jq
spc forge validate --output json | jq '.errors[]'
spc forge compile – Runs validation as part of compilationspc healer fix – Auto-fix validation errorsCompile contracts into the Intermediate Representation (IR).
Usage: spc forge compile [OPTIONS] [PATH]
Compile contracts into IR.
Runs the full pipeline: load -> validate -> resolve -> compile -> passes.
Prints a summary of the compiled IR.
Options:
--output [text|json] Output format
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory or domains/. |
| Option | Type | Default | Description |
|---|---|---|---|
--output |
Choice: text, json |
text |
Output format. |
The compile command executes the full pipeline in order:
.contract.yaml files| Code | Meaning |
|---|---|
| 0 | Compilation successful |
| 1 | Compilation failed (validation errors, resolution errors, etc.) |
{
"success": true,
"summary": "4 entities, 1 workflow, 4 routes, 4 pages",
"entities": 4,
"workflows": 1,
"routes": 4,
"pages": 4
}
# Compile all domains
spc forge compile
# Compile a specific domain
spc forge compile domains/library
# JSON output for tooling
spc forge compile domains/library --output json
spc forge validate – Validation only (no compilation)spc forge generate – Compile + generate codeCompile contracts and generate code for target platforms.
Usage: spc forge generate [OPTIONS] [PATH]
Compile contracts and generate code.
Runs the full compilation pipeline, then invokes target generators to
produce code files in the output directory.
Options:
-t, --target TEXT Target generators to run
-o, --output PATH Output directory for generated files
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory or domains/. |
| Option | Type | Default | Description |
|---|---|---|---|
-t, --target |
Text (repeatable) | typescript, fastapi, postgres |
Target generator(s) to run. Can be specified multiple times. |
-o, --output |
Path | runtime/ |
Output directory for generated files. Created if it does not exist. |
| Target | Generator Class | Output |
|---|---|---|
typescript |
TypeScriptGenerator |
TypeScript interfaces and types |
fastapi |
FastAPIGenerator |
FastAPI route handlers and models |
postgres |
PostgresGenerator |
CREATE TABLE DDL statements |
If an unknown target name is provided, it is skipped with a warning listing available targets.
| Code | Meaning |
|---|---|
| 0 | Generation successful |
| 1 | Compilation failed before generation could start |
# Generate all targets (TypeScript + FastAPI + PostgreSQL)
spc forge generate domains/library
# Generate only TypeScript types
spc forge generate domains/library --target typescript
# Generate only PostgreSQL DDL
spc forge generate domains/library -t postgres
# Multiple specific targets
spc forge generate domains/library -t typescript -t postgres
# Custom output directory
spc forge generate domains/library --output output/
# Generate for all domains
spc forge generate
Generated files are written to subdirectories under the output directory:
runtime/
backend/
routes_books.py # FastAPI route handlers
routes_authors.py
frontend/
types.ts # TypeScript interfaces
database/
schema.sql # PostgreSQL DDL
Every generated file includes a @generated provenance header. Never edit generated files by hand – change the contracts and regenerate.
spc forge compile – Compile without generating codespc forge validate – Validate before generatingDisplay the contract dependency graph.
Usage: spc forge graph [OPTIONS] [PATH]
Display the contract dependency graph.
Options:
--output [text|json] Output format
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory or domains/. |
| Option | Type | Default | Description |
|---|---|---|---|
--output |
Choice: text, json |
text |
Output format. text renders a Rich tree grouped by kind. json produces machine-readable JSON. |
The text output renders a Rich tree grouped by contract kind, showing each contract’s FQN and its dependencies (requires) and dependents (used by).
{
"nodes": [
{
"fqn": "entity/library/book",
"kind": "Entity",
"dependencies": ["mixin/stdlib/timestamped", "mixin/stdlib/identifiable"],
"dependents": ["route/library/books", "page/library/books"]
}
],
"count": 12
}
# Show graph for all domains
spc forge graph
# Show graph for a specific domain
spc forge graph domains/library
# JSON output for external tools
spc forge graph domains/library --output json
# Pipe to jq to find contracts with no dependents
spc forge graph --output json | jq '.nodes[] | select(.dependents | length == 0)'
spc factory visualize – Generate Mermaid diagrams (ER, state, deps)The Factory is the LLM-powered contract authoring system. It uses conversational interviews and natural language to create, explain, modify, and migrate contracts. All Factory commands that use an LLM require a provider to be configured (see Environment Variables).
Usage: spc factory [OPTIONS] COMMAND [ARGS]...
The Factory -- conversational contract authoring (LLM-powered).
Options:
--help Show this message and exit.
Commands:
add Add a single contract to an existing domain via LLM interview.
chat Agentic domain conversation -- discuss, propose, and build contracts.
explain Explain a contract in plain English using the LLM.
migrate Import external schemas into Specora contracts via LLM.
new Bootstrap a new domain from a conversational interview.
refine Modify an existing contract via natural language instruction.
visualize Generate Mermaid diagrams for contracts.
Bootstrap a complete domain from a multi-phase conversational interview.
Usage: spc factory new [OPTIONS]
Bootstrap a new domain from a conversational interview.
Options:
--help Show this message and exit.
None.
| Option | Type | Default | Description |
|---|---|---|---|
--help |
Flag | N/A | Show help message and exit. |
The factory new command runs a structured, multi-phase interview:
$EDITOR (or displayed in-terminal). You can edit them before confirming.domains/<name>/.If you interrupt the interview (Ctrl+C or Ctrl+D), the session is saved to .specora/session/. When you run factory new again, you are prompted to resume or start fresh. This means you can stop mid-interview and pick up where you left off.
For each entity discovered, the Factory generates:
entities/<name>.contract.yaml – Entity contractworkflows/<name>_lifecycle.contract.yaml – Workflow contract (if entity has a state machine)routes/<name>s.contract.yaml – Route contract (CRUD endpoints)pages/<name>s.contract.yaml – Page contract (UI spec)# Start a new domain interview
spc factory new
# Or via the REPL
> /new
spc init – Scaffold a domain without LLM (minimal starter files)spc factory add – Add a single contract to an existing domainAdd a single contract to an existing domain.
Usage: spc factory add [OPTIONS] {entity|workflow|route|page}
Add a single contract to an existing domain via LLM interview.
Options:
-d, --domain TEXT Target domain name [required]
-n, --name TEXT Contract name (snake_case) [required]
-e, --entity TEXT Entity FQN (required for route/page)
--help Show this message and exit.
| Argument | Required | Choices | Description |
|---|---|---|---|
KIND |
Yes | entity, workflow, route, page |
The kind of contract to create. |
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
-d, --domain |
Text | Yes | N/A | Target domain name. The domain directory must already exist under domains/. |
-n, --name |
Text | Yes | N/A | Contract name in snake_case. |
-e, --entity |
Text | No (required for route and page) |
"" |
Entity FQN that the route or page is for. Format: entity/<domain>/<name>. |
| Kind | LLM Required | Process |
|---|---|---|
entity |
Yes | Runs an entity interview to capture fields, types, constraints, relationships |
workflow |
Yes | Runs a workflow interview to capture states, transitions, guards |
route |
No | Mechanically emits a CRUD route contract for the referenced entity |
page |
No | Mechanically emits a page contract for the referenced entity |
After generation, the contract is validated against meta-schemas. If validation fails, the command exits with code 1 and displays errors.
The generated YAML is displayed with syntax highlighting and line numbers. You are prompted Write this contract? [Y/n] before anything is written to disk.
| Code | Meaning |
|---|---|
| 0 | Contract written successfully, or user cancelled |
| 1 | Domain not found, contract already exists, missing --entity, validation errors, or LLM configuration error |
# Add an entity with LLM interview
spc factory add entity -d library -n review
# Add a workflow with LLM interview
spc factory add workflow -d library -n review_lifecycle
# Add a route (mechanical, no LLM needed)
spc factory add route -d library -n reviews -e entity/library/review
# Add a page (mechanical, no LLM needed)
spc factory add page -d library -n reviews -e entity/library/review
spc factory new – Create an entire domain at oncespc factory refine – Modify an existing contractExplain a contract in plain English using the LLM.
Usage: spc factory explain [OPTIONS] PATH
Explain a contract in plain English using the LLM.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
PATH |
Yes | Path to a .contract.yaml file. Must exist on disk. |
.contract.yaml extension..contract.yaml.| Code | Meaning |
|---|---|
| 0 | Explanation displayed |
| 1 | File not found, not a contract file, LLM configuration error, or LLM error |
# Explain an entity contract
spc factory explain domains/library/entities/book.contract.yaml
# Explain a workflow
spc factory explain domains/library/workflows/book_lifecycle.contract.yaml
# Via the REPL
> /explain domains/library/entities/book.contract.yaml
spc factory refine – Modify a contract after understanding itModify an existing contract via natural language instruction.
Usage: spc factory refine [OPTIONS] PATH INSTRUCTION
Modify an existing contract via natural language instruction.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
PATH |
Yes | Path to a .contract.yaml file. Must exist on disk. |
INSTRUCTION |
Yes | Natural language description of the change to make. |
metadata.name is forced to snake_caserequires entries are forced to lowercase FQN formatgraph_edge values are forced to SCREAMING_SNAKE_CASEApply this change? [Y/n].Every accepted refinement produces a ContractDiff with:
factoryfactory:refine.forge/diffs/.contract.yaml.| Code | Meaning |
|---|---|
| 0 | Change applied or user cancelled |
| 1 | File not found, not a contract file, LLM error, YAML parse failure, or validation errors in the modified contract |
# Add a field
spc factory refine domains/library/entities/book.contract.yaml "add an isbn field of type string, required"
# Change a relationship
spc factory refine domains/library/entities/book.contract.yaml "change the author reference to use WRITTEN_BY as the graph edge"
# Remove a field
spc factory refine domains/library/entities/book.contract.yaml "remove the subtitle field"
# Via the REPL
> /refine domains/library/entities/book.contract.yaml add a page_count integer field
spc factory explain – Understand a contract before modifying itspc diff history – View the change history after refiningAgentic domain conversation with tool use. The LLM can discuss your domain model and propose concrete changes (entity creation, contract modification, validation).
Usage: spc factory chat [OPTIONS]
Agentic domain conversation -- discuss, propose, and build contracts.
Options:
-d, --domain TEXT Domain to chat about
--help Show this message and exit.
None.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
-d, --domain |
Text | No | Auto-detected | Domain to chat about. If omitted and exactly one domain exists, it is auto-selected. If multiple domains exist, you must specify. |
domains/ contains exactly one subdirectory, that domain is auto-selected.domains/ contains zero subdirectories, the command exits with an error suggesting spc init.domains/ contains multiple subdirectories, the command exits with an error listing available domains.The chat agent has three tools it can invoke:
| Tool | Description |
|---|---|
propose_entity |
Creates a new Entity contract (with auto-generated Route and Page contracts). Shows the proposal for confirmation before writing. |
propose_modification |
Modifies an existing contract via natural language. Shows the modification for confirmation before applying. |
validate_domain |
Runs validation on all contracts in the current domain. |
Every tool invocation requires your explicit confirmation before any files are modified.
The chat is a persistent conversation. The LLM maintains context across messages. After each tool execution, the domain context is refreshed so the LLM sees the latest contract state.
Type exit, quit, /exit, /quit, or press Ctrl+D to end the chat.
domains/.| Code | Meaning |
|---|---|
| 0 | Chat ended normally |
| 1 | No domains found, multiple domains without --domain, or LLM configuration error |
# Chat about the only domain
spc factory chat
# Chat about a specific domain
spc factory chat -d library
# Via the REPL
> /chat
> /chat --domain library
> I need a review system where patrons can rate books
(LLM proposes entity/library/review with fields: rating, comment, patron, book)
Write this contract? [Y/n] y
Created entity/library/review with route and page contracts.
> Can you add a date field to the review?
(LLM proposes modification to entity/library/review)
Apply this modification? [Y/n] y
> Let's validate everything
(LLM runs validate_domain)
All 16 contracts are valid.
spc factory new – Full domain bootstrap (structured interview)spc factory add – Add a single contract (non-chat)Generate Mermaid diagrams from contracts.
Usage: spc factory visualize [OPTIONS] [PATH]
Generate Mermaid diagrams for contracts.
Options:
--type [er|state|deps] Diagram type
-o, --output TEXT Save to file instead of printing
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory. Must exist on disk. |
| Option | Type | Default | Description |
|---|---|---|---|
--type |
Choice: er, state, deps |
er |
Diagram type to generate. |
-o, --output |
Text | "" (print to terminal) |
File path to save the Mermaid output. If empty, prints to terminal with syntax highlighting. |
er – Entity-Relationship DiagramGenerates a Mermaid erDiagram showing all entities, their fields, field types, and relationships (derived from references in field definitions).
state – State Machine DiagramGenerates Mermaid stateDiagram-v2 diagrams for each Workflow contract. Shows states, transitions, and the initial state. If there are multiple workflows, each gets its own diagram separated by blank lines.
deps – Dependency Graph DiagramGenerates a Mermaid graph TD (top-down) diagram showing all contracts and their requires relationships. Different contract kinds use different node shapes:
[name]((name))[/name/]>name]# ER diagram to terminal
spc factory visualize domains/library
# State machine diagram
spc factory visualize domains/library --type state
# Dependency graph saved to file
spc factory visualize domains/library --type deps -o docs/deps.mmd
# Via the REPL
> /visualize domains/library
> /visualize domains/library --type state
spc forge graph – Text-based dependency graph (Rich tree output)Import external schemas (OpenAPI, SQL DDL, Prisma) into Specora contracts via LLM.
Usage: spc factory migrate [OPTIONS] SOURCE
Import external schemas into Specora contracts via LLM.
Options:
-d, --domain TEXT Target domain name [required]
--format [auto|openapi|sql|prisma]
Source format
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
SOURCE |
Yes | Path to the source schema file. Must exist on disk. |
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
-d, --domain |
Text | Yes | N/A | Target domain name. Contracts will be written to domains/<domain>/. |
--format |
Choice: auto, openapi, sql, prisma |
No | auto |
Source format. auto detects from file extension and content. |
When --format auto (the default):
| File Extension | Detected Format |
|---|---|
.yaml, .yml |
openapi |
.sql |
sql |
.prisma |
prisma |
Content-based detection is used as fallback:
CREATE TABLE (case-insensitive) are detected as sqlmodel and @@ are detected as prismaopenapiThe LLM maps source types to Specora field types:
| SQL Types | Specora Type |
|---|---|
VARCHAR, TEXT, CHAR |
string |
INT, BIGINT, SERIAL |
integer |
DECIMAL, FLOAT, DOUBLE |
number |
BOOLEAN, BOOL |
boolean |
TIMESTAMP, TIMESTAMPTZ |
datetime |
DATE |
date |
UUID |
uuid |
Foreign keys are automatically converted to references with graph_edge labels.
--format auto).domains/<domain>/entities/.| Code | Meaning |
|---|---|
| 0 | Migration completed or user cancelled |
| 1 | LLM configuration error, LLM error, no contracts extracted, or all contracts failed validation |
# Migrate from an OpenAPI spec
spc factory migrate api-spec.yaml -d my_app
# Migrate from SQL DDL
spc factory migrate schema.sql -d my_app --format sql
# Migrate from Prisma schema
spc factory migrate schema.prisma -d my_app --format prisma
# Via the REPL
> /migrate schema.sql -d my_app
spc extract – Reverse-engineer from source code (not schema files)The Healer is the self-healing pipeline. It detects contract validation errors, creates tickets, proposes fixes (via LLM), and applies them with your approval.
Usage: spc healer [OPTIONS] COMMAND [ARGS]...
The Healer -- self-healing contract pipeline.
Options:
--help Show this message and exit.
Commands:
approve Approve a proposed fix and apply it.
fix Load contracts, validate, create tickets for errors, and process fixes.
history Show applied healer fixes from the diff store.
reject Reject a proposed fix.
serve Start the Healer HTTP service.
show Show detailed information about a ticket.
status Show queue statistics.
tickets List healer tickets with optional filters.
Healer tickets progress through these statuses:
queued -> analyzing -> proposed -> approved -> applied
|
+-------> rejected
(any stage) -> failed
| Status | Description |
|---|---|
queued |
Ticket created, waiting for analysis |
analyzing |
Pipeline is analyzing the error |
proposed |
A fix has been proposed, awaiting human approval |
approved |
Fix approved by human, being applied |
applied |
Fix successfully applied to the contract file |
failed |
Processing failed at some stage |
rejected |
Human rejected the proposed fix |
The Healer uses a SQLite database at .forge/healer/healer.db. It is created automatically on first use.
Scan contracts, validate, create tickets for errors, and process fixes.
Usage: spc healer fix [OPTIONS] [PATH]
Load contracts, validate, create tickets for errors, and process fixes.
Scans the contract directory, validates all contracts, creates healer
tickets for any validation errors, and processes them through the pipeline.
Options:
--help Show this message and exit.
| Argument | Required | Default | Description |
|---|---|---|---|
PATH |
No | domains/ |
Path to a domain directory. |
error): creates a healer ticket with source VALIDATION.| Code | Meaning |
|---|---|
| 0 | Completed (may have proposed or failed tickets) |
| 1 | Could not load contracts |
# Fix all domains
spc healer fix
# Fix a specific domain
spc healer fix domains/library
# Via the REPL
> /heal
> /heal domains/library
spc healer tickets – View tickets awaiting approvalspc healer approve – Approve a proposed fixShow queue statistics.
Usage: spc healer status [OPTIONS]
Show queue statistics.
Options:
--output [text|json] Output format
--help Show this message and exit.
| Option | Type | Default | Description |
|---|---|---|---|
--output |
Choice: text, json |
text |
Output format. |
Displays a Rich table with ticket counts per status:
Healer Queue Status
┌───────────┬───────┐
│ Status │ Count │
├───────────┼───────┤
│ queued │ 0 │
│ analyzing │ 0 │
│ proposed │ 2 │
│ approved │ 0 │
│ applied │ 5 │
│ failed │ 1 │
│ rejected │ 0 │
├───────────┼───────┤
│ Total │ 8 │
└───────────┴───────┘
{
"by_status": {
"queued": 0,
"proposed": 2,
"applied": 5,
"failed": 1
},
"total": 8
}
spc healer status
spc healer status --output json
# Via the REPL
> /status
List healer tickets with optional filters.
Usage: spc healer tickets [OPTIONS]
List healer tickets with optional filters.
Options:
--status [queued|analyzing|proposed|approved|applied|failed|rejected]
Filter by ticket status
--priority [critical|high|medium|low]
Filter by priority
--output [text|json] Output format
--help Show this message and exit.
| Option | Type | Default | Description |
|---|---|---|---|
--status |
Choice: queued, analyzing, proposed, approved, applied, failed, rejected |
None (all) | Filter tickets by status. Case-insensitive. |
--priority |
Choice: critical, high, medium, low |
None (all) | Filter tickets by priority. Case-insensitive. |
--output |
Choice: text, json |
text |
Output format. |
Displays a Rich table with columns: ID (first 8 chars), Status, Priority, Tier, Contract FQN, and Error (truncated to 40 chars).
[
{
"id": "a1b2c3d4-...",
"status": "proposed",
"priority": "high",
"tier": 1,
"contract_fqn": "entity/library/book",
"error": "Missing required field: spec.fields"
}
]
# List all tickets
spc healer tickets
# List only proposed tickets
spc healer tickets --status proposed
# List high-priority tickets
spc healer tickets --priority high
# Combined filter
spc healer tickets --status proposed --priority critical
# JSON for scripting
spc healer tickets --output json
# Via the REPL
> /tickets
Show detailed information about a ticket.
Usage: spc healer show [OPTIONS] TICKET_ID
Show detailed information about a ticket.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
TICKET_ID |
Yes | Full UUID or unique prefix (minimum 4 characters) of the ticket. |
You can use a prefix of the ticket ID instead of the full UUID. The system resolves it:
| Field | Description |
|---|---|
| Status | Current ticket status |
| Priority | critical, high, medium, or low |
| Tier | Numeric tier level |
| Source | How the ticket was created (validation, etc.) |
| Contract | FQN of the affected contract |
| Error | Error type classification |
| Message | Full error message |
| Created | Creation timestamp (UTC) |
| Resolved | Resolution timestamp (if resolved) |
| Note | Resolution note (if any) |
| Context | Additional context (path, source file, etc.) |
| Proposal | Fix proposal details: method, confidence, explanation, change count |
| Code | Meaning |
|---|---|
| 0 | Ticket displayed |
| 1 | Ticket not found or ambiguous ID |
# Show by full ID
spc healer show a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Show by prefix
spc healer show a1b2c3d4
Approve a proposed fix and apply it.
Usage: spc healer approve [OPTIONS] TICKET_ID
Approve a proposed fix and apply it.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
TICKET_ID |
Yes | Full UUID or unique prefix of the ticket. |
proposed status.applied.| Code | Meaning |
|---|---|
| 0 | Fix approved and applied |
| 1 | Ticket not found, ticket not in proposed status, or application failed |
# Approve by prefix
spc healer approve a1b2c3d4
# Full workflow: fix -> review -> approve
spc healer fix domains/library
spc healer tickets --status proposed
spc healer show a1b2c3d4
spc healer approve a1b2c3d4
spc healer reject – Reject a proposed fix insteadspc healer tickets – List tickets to find IDsReject a proposed fix.
Usage: spc healer reject [OPTIONS] TICKET_ID
Reject a proposed fix.
Options:
-r, --reason TEXT Reason for rejection
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
TICKET_ID |
Yes | Full UUID or unique prefix of the ticket. |
| Option | Type | Default | Description |
|---|---|---|---|
-r, --reason |
Text | "" |
Reason for rejecting the fix. Recorded on the ticket for future reference. |
proposed status.rejected.| Code | Meaning |
|---|---|
| 0 | Fix rejected |
| 1 | Ticket not found, or ticket not in proposed status |
# Reject without reason
spc healer reject a1b2c3d4
# Reject with reason
spc healer reject a1b2c3d4 -r "The proposed field name is wrong"
spc healer reject a1b2c3d4 --reason "Would break existing API clients"
Show applied healer fixes from the diff store.
Usage: spc healer history [OPTIONS]
Show applied healer fixes from the diff store.
Options:
--help Show this message and exit.
Queries the diff store (.forge/diffs/) for all diffs with origin HEALER and displays them in a Rich table.
| Column | Description |
|---|---|
| Date | When the fix was applied (YYYY-MM-DD HH:MM) |
| Contract | FQN of the modified contract |
| Reason | Why the fix was applied (truncated to 50 chars) |
| Changes | Number of individual field changes |
spc healer history
# Via the REPL
> /history
spc diff history – View all changes (not just healer) for a specific contractStart the Healer HTTP service.
Usage: spc healer serve [OPTIONS]
Start the Healer HTTP service.
Options:
--port INTEGER Port to serve on
--host TEXT Host to bind to
--help Show this message and exit.
| Option | Type | Default | Description |
|---|---|---|---|
--port |
Integer | 8083 |
Port to bind the HTTP server to. |
--host |
Text | 0.0.0.0 |
Host address to bind to. Use 0.0.0.0 for all interfaces or 127.0.0.1 for localhost only. |
Starts a FastAPI/Uvicorn HTTP server exposing the Healer API. This enables external systems (CI pipelines, monitoring tools) to submit errors and query ticket status programmatically.
healer optional dependency group (pip install -e ".[healer]").# Start on default port (8083)
spc healer serve
# Custom port
spc healer serve --port 9000
# Localhost only
spc healer serve --host 127.0.0.1 --port 8083
Reverse-engineer a codebase into Specora contracts.
Usage: spc extract [OPTIONS] PATH
Reverse-engineer a codebase into Specora contracts.
Analyzes Python and TypeScript source files, extracts entities, routes, and
workflows, then emits contract YAML files.
Options:
-d, --domain TEXT Domain name (auto-inferred from directory name if omitted)
-o, --output TEXT Output base directory
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
PATH |
Yes | Path to the source codebase directory. Must exist on disk. |
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
-d, --domain |
Text | No | Auto-inferred from directory name | Domain name for the generated contracts. Converted to snake_case. |
-o, --output |
Text | No | domains/ |
Base output directory. Contracts are written to <output>/<domain>/. |
| Language | What is Extracted |
|---|---|
| Python | Pydantic models, SQLAlchemy models, dataclasses, FastAPI routes |
| TypeScript | TypeScript interfaces, type aliases |
The extractor runs a 4-pass pipeline:
.py and .ts/.tsx filesAfter extraction, each discovered entity is presented for review. You can accept or reject individual entities before contracts are written.
For each accepted entity:
entities/<name>.contract.yaml – Entity contractroutes/<name>s.contract.yaml – Route contractpages/<name>s.contract.yaml – Page contract# Extract from a Python project
spc extract ./my-flask-app
# Extract with explicit domain name
spc extract ./my-flask-app -d my_app
# Extract to custom output directory
spc extract ./my-flask-app -d my_app -o output/
# Via the REPL
> /extract ./my-flask-app
> /extract ./my-flask-app --domain my_app
spc factory migrate – Import from schema files (OpenAPI, SQL, Prisma) rather than source codeContract diff tracking. Every mutation to a contract file can be tracked with a structured diff that records what changed, who changed it, and why.
Usage: spc diff [OPTIONS] COMMAND [ARGS]...
Contract diff tracking.
Options:
--help Show this message and exit.
Commands:
history Show the change history for a contract.
show Show details of a specific diff.
Diffs are stored as JSON files in .forge/diffs/, organized by contract FQN.
Show the change history for a specific contract.
Usage: spc diff history [OPTIONS] CONTRACT_FQN
Show the change history for a contract.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
CONTRACT_FQN |
Yes | Fully qualified name of the contract (e.g., entity/library/book). |
| Column | Description |
|---|---|
| Date | When the change was made (YYYY-MM-DD HH:MM) |
| Origin | Who made the change: human, healer, advisor, or factory (with optional detail) |
| Reason | Why the change was made (truncated to 60 chars) |
| Changes | Number of individual field-level changes |
Diffs are displayed in reverse chronological order (newest first).
# View history for an entity
spc diff history entity/library/book
# View history for a workflow
spc diff history workflow/library/book_lifecycle
spc diff show – View details of a specific diffspc healer history – View only healer-originated diffsShow details of a specific diff.
Usage: spc diff show [OPTIONS] DIFF_ID
Show details of a specific diff.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
DIFF_ID |
Yes | UUID of the diff to display. |
Displays full diff details:
| Field | Description |
|---|---|
| Diff ID | Full UUID |
| Contract | FQN of the affected contract |
| Date | Timestamp (UTC) |
| Origin | Who made the change (with detail) |
| Reason | Why the change was made |
Then lists all individual changes with type indicators:
+ (green) – Added field/value- (red) – Removed field/value~ (yellow) – Modified field/value (shows old -> new)| Code | Meaning |
|---|---|
| 0 | Diff displayed |
| 1 | Diff not found |
# View a specific diff
spc diff show a1b2c3d4-e5f6-7890-abcd-ef1234567890
Scaffold a new domain with starter contracts.
Usage: spc init [OPTIONS] DOMAIN
Scaffold a new domain with starter contracts.
Creates the directory structure and a starter entity contract.
Options:
--help Show this message and exit.
| Argument | Required | Description |
|---|---|---|
DOMAIN |
Yes | Name of the domain to create. Used as the directory name under domains/. |
domains/<domain>/
entities/
example.contract.yaml # Starter entity with name, description, active fields
workflows/ # Empty, ready for workflow contracts
pages/ # Empty, ready for page contracts
routes/ # Empty, ready for route contracts
agents/ # Empty, ready for agent contracts
The generated example.contract.yaml contains:
apiVersion: specora.dev/v1
kind: Entity
metadata:
name: example
domain: <domain>
description: "A starter entity -- replace with your own"
tags: [starter]
requires:
- mixin/stdlib/timestamped
- mixin/stdlib/identifiable
spec:
fields:
name:
type: string
required: true
description: "The name of this record"
constraints:
maxLength: 200
description:
type: text
description: "Detailed description"
active:
type: boolean
default: true
description: "Whether this record is active"
| Code | Meaning |
|---|---|
| 0 | Domain scaffolded successfully |
| 1 | Domain directory already exists |
# Create a new domain
spc init healthcare
# Then edit the starter entity
# $EDITOR domains/healthcare/entities/example.contract.yaml
# Validate
spc forge validate domains/healthcare
# Generate code
spc forge generate domains/healthcare
spc factory new – Create a domain via LLM interview (richer output)These variables configure the LLM engine used by Factory, Healer, and Extractor commands. They are probed in priority order – the first match wins.
| Variable | Priority | Default Model | Description |
|---|---|---|---|
SPECORA_AI_MODEL |
1 (highest) | Explicit model | Override model selection. Must be a model ID known to the registry. Requires the corresponding provider API key. |
ANTHROPIC_API_KEY |
2 | claude-sonnet-4-6 |
Anthropic API key. Selects Claude as the provider. |
OPENAI_API_KEY |
3 | gpt-4o |
OpenAI API key. Selects GPT-4o. |
XAI_API_KEY |
4 | grok-3-mini |
xAI API key. Uses the xAI base URL (https://api.x.ai/v1). |
OLLAMA_BASE_URL |
5 (lowest) | llama3.3:70b |
Ollama base URL for local models (e.g., http://localhost:11434). No API key needed. |
When SPECORA_AI_MODEL is set, the provider is determined from the model’s registry entry. The corresponding API key variable must also be set.
When XAI_API_KEY is set without OPENAI_API_KEY, the xAI base URL is automatically configured.
| Variable | Default | Description |
|---|---|---|
EDITOR |
N/A | Editor used by factory new for contract preview. Falls back to VISUAL. |
VISUAL |
N/A | Fallback editor if EDITOR is not set. |
SPECORA_HEALER_WEBHOOK_URL |
N/A | Webhook URL for healer notifications. |
The CLI loads .env files from the current directory using python-dotenv with override=True. This means .env values override system-level environment variables.
| Path | Purpose | Created By |
|---|---|---|
~/.specora/ |
User-level config directory | REPL (for command history) |
~/.specora/history |
REPL command history | REPL (auto-created) |
.forge/ |
Project-level Forge data | Forge commands |
.forge/diffs/ |
Contract diff storage (JSON) | factory refine, Healer |
.forge/healer/ |
Healer data directory | Healer commands |
.forge/healer/healer.db |
Healer ticket database (SQLite) | Healer commands |
.specora/session/ |
Factory session persistence | factory new |
domains/ |
Contract source directory | init, factory new, extract |
runtime/ |
Generated code output | forge generate |
The standard library at spec/stdlib/ provides reusable contracts:
| Path | Contents |
|---|---|
spec/stdlib/mixins/ |
timestamped, identifiable, auditable, taggable, commentable, soft_deletable |
spec/stdlib/workflows/ |
crud_lifecycle, approval, ticket |
These are automatically discovered and available via requires references (e.g., mixin/stdlib/timestamped).
# Option A: Quick scaffold (no LLM)
spc init my_app
# Edit domains/my_app/entities/*.contract.yaml manually
# Option B: LLM-guided interview
export ANTHROPIC_API_KEY="sk-ant-..."
spc factory new
# Follow the interactive interview
# Validate
spc forge validate domains/my_app
# Generate code
spc forge generate domains/my_app
# Inspect output
ls runtime/
# Point the extractor at your source code
spc extract ./my-existing-app -d my_app
# Review and accept/reject extracted entities interactively
# Validate the generated contracts
spc forge validate domains/my_app
# Fix any issues
spc healer fix domains/my_app
# Generate fresh code
spc forge generate domains/my_app
# From OpenAPI
spc factory migrate api-spec.yaml -d my_app
# From SQL DDL
spc factory migrate schema.sql -d my_app --format sql
# From Prisma
spc factory migrate schema.prisma -d my_app --format prisma
# Validate the results
spc forge validate domains/my_app
# See what's wrong
spc forge validate domains/my_app
# Auto-fix with the Healer
spc healer fix domains/my_app
# Check for proposed fixes
spc healer tickets --status proposed
# Review a proposed fix
spc healer show a1b2c3d4
# Approve or reject
spc healer approve a1b2c3d4
spc healer reject a1b2c3d4 -r "Wrong approach"
# Understand the contract first
spc factory explain domains/library/entities/book.contract.yaml
# Make a change via natural language
spc factory refine domains/library/entities/book.contract.yaml "add a page_count integer field"
# Verify the change
spc forge validate domains/library
# View the diff history
spc diff history entity/library/book
# Regenerate code
spc forge generate domains/library
# All targets (TypeScript + FastAPI + PostgreSQL)
spc forge generate domains/library
# Specific targets
spc forge generate domains/library -t typescript
spc forge generate domains/library -t postgres
spc forge generate domains/library -t typescript -t postgres
# Custom output directory
spc forge generate domains/library -o output/
# Start the Healer HTTP service (for CI/runtime integration)
spc healer serve --port 8083
# Check queue status
spc healer status
# View all tickets
spc healer tickets
# View healer fix history
spc healer history
# View all change history for a specific contract
spc diff history entity/library/book
# Launch the REPL
spc
# Quick validation cycle
> /validate
> /compile
> /generate
# LLM-powered authoring
> /new
> /chat -d library
> /explain domains/library/entities/book.contract.yaml
> /refine domains/library/entities/book.contract.yaml add an isbn field
# Visualize your domain
> /visualize domains/library
> /visualize domains/library --type state
> /graph
# Self-healing
> /heal
> /status
> /tickets
# Shell escape
> ! ls runtime/
> ! cat runtime/database/schema.sql