- Status: Draft
- Authors: Angel Marino (@mrangelmarino)
- Created: 2026-03-27
- Repository: github.com/solo-ist/specscript
SpecScript is an open format that extends Markdown into a programmable document system. It defines three composable layers: bidirectional translation between structured data (JSON) and Markdown content blocks, inline representation of structured data as natural prose, and embedded natural language scripting directives interpreted by an AI runtime at transformation time.
A SpecScript document is simultaneously content, structured data, and transformation logic. Any conforming runtime can execute it.
Markdown is the de facto authoring format for technical and editorial content. But it remains a passive format — a document describes content and waits for an external system to decide what to do with it. Transformation logic, conditional rendering, data binding, and output targeting all live outside the document in application code, templates, or CI pipelines.
Meanwhile, AI language models have made natural language a viable programming interface. Instructions that previously required a DSL, template syntax, or scripting language can now be expressed as prose and interpreted reliably by a model.
SpecScript unifies these observations. It extends Markdown with:
- A schema-driven translation layer between JSON and Markdown content blocks.
- An inline syntax for representing structured key-value data as natural text.
- A fenced block convention for natural language directives that execute during document transformation.
The result is a document that carries its own transformation logic, expressed in the language the author already speaks.
- Documents are programs. A SpecScript document is not inert content. It contains executable logic and can produce different outputs depending on context, target, and data.
- Prose is the scripting language. Directive blocks are written in natural language. No DSL is required. The barrier to writing transformation logic is literacy, not programming skill.
- Format over application. The intelligence lives in the document, not the tool. Any conforming runtime can execute a SpecScript document. The spec is implementation-agnostic.
- Markdown is the universal IR. Markdown content blocks are the intermediate representation. All structured data passes through Markdown on its way to any output format.
- Layers compose independently. Each layer is useful on its own. Layer 1 works without Layer 2 or 3. Layer 2 works without Layer 3. A runtime may implement any subset, but MUST declare which layers it supports.
- Document: A SpecScript-conforming Markdown file.
- Block: A discrete content node in the document's AST (paragraph, heading, code fence, blockquote, list, table, etc.).
- Directive: A natural language instruction embedded in a
specfenced code block, executed by the runtime at transformation time. - Schema: A JSON Schema or equivalent contract that defines the expected structure for Layer 1 translation.
- Runtime: A program that parses, interprets, and transforms a SpecScript document.
- Target: An output format (e.g.,
html,pdf,docx,slack-post,json). - Field: A structured key-value pair represented inline using Layer 2 syntax.
A SpecScript document is a valid Markdown file. Any Markdown parser can render it as static content. SpecScript-specific features degrade gracefully: directive blocks render as code fences, inline fields render as bracketed text, and frontmatter renders as a YAML block (or is ignored, per existing convention).
A SpecScript document MAY include YAML frontmatter delimited by ---. The frontmatter defines document-level metadata consumed by the runtime.
---
schema: product-announcement/v1
output: [html, pdf, slack-post]
data: ./product.json
specscript: "0.1"
---| Key | Type | Description |
|---|---|---|
specscript |
string |
SpecScript version this document targets. Defaults to latest. |
schema |
string |
Schema identifier for Layer 1 translation. |
output |
string | array |
Target format(s) for transformation. |
data |
string | object |
Path to external data file, URL, or inline data object. |
runtime |
object |
Runtime-specific configuration (model, tools, permissions). |
All other frontmatter keys are passed through as document metadata.
All standard Markdown blocks are valid SpecScript content blocks. The runtime MUST parse the document into a block-level AST where each block is typed and addressable.
Block types include, at minimum:
heading(with level 1–6)paragraphcode_fence(with language identifier)blockquotelist(ordered and unordered)tablethematic_breakhtml_blockdirective(SpecScript extension; see §5)field(SpecScript extension; see §4)
Layer 1 defines bidirectional translation between JSON and Markdown content blocks. Given a JSON object and a schema, a conforming runtime MUST be able to:
- Serialize: Transform JSON → Markdown content blocks.
- Deserialize: Transform Markdown content blocks → JSON.
The schema defines the mapping contract. The AI acts as the translation engine, interpreting the schema to produce natural, readable Markdown from structured data and extracting structured data from natural prose.
A schema is a document that defines:
- The expected JSON structure (fields, types, nesting).
- Rendering hints for each field (which Markdown block type to use, ordering, prose style).
- Round-trip fidelity requirements (which fields MUST survive a serialize → deserialize cycle without loss).
Schemas MAY be expressed as JSON Schema with SpecScript-specific extensions, or as a standalone SpecScript schema format (to be defined in a subsequent RFC).
{
"$specscript": "0.1",
"type": "object",
"properties": {
"title": {
"type": "string",
"render": "heading",
"level": 1
},
"summary": {
"type": "string",
"render": "paragraph",
"style": "concise"
},
"features": {
"type": "array",
"items": { "type": "string" },
"render": "list",
"ordered": false
}
},
"roundtrip": ["title", "features"]
}- Serialize (JSON → Markdown): The runtime passes the JSON object and schema to an AI model with instructions to produce Markdown content blocks conforming to the schema's rendering hints. The output is a valid Markdown document (or document fragment).
- Deserialize (Markdown → JSON): The runtime passes Markdown content and the schema to an AI model with instructions to extract structured data conforming to the schema's type definitions. Fields marked as
roundtripMUST be extracted with semantic equivalence to the original. - Determinism: Fields with explicit
renderhints SHOULD produce deterministic output across serialization passes. Fields without hints MAY vary in prose style between passes, provided semantic content is preserved.
If the AI cannot produce a valid translation (missing required fields, type mismatches, ambiguous content), the runtime MUST surface a structured error indicating the block and field where translation failed. The runtime MUST NOT silently drop data.
Layer 2 introduces syntax for embedding structured key-value data inline within Markdown content. The data renders as natural text to a human reader but is machine-addressable as structured fields.
Inline fields use a bracket notation:
[key: value]
Multiple fields may appear on the same line:
[price: $29/mo] [trial: 14 days] [tier: professional]
Fields may also appear within prose:
The product costs [price: $29/mo] with a [trial: 14 days] free trial.
- A field is delimited by
[and]. - The key and value are separated by
:(colon followed by a space). - Keys MUST match the pattern
[a-zA-Z_][a-zA-Z0-9_.-]*. - Values are treated as strings by default. The schema MAY define type coercion rules.
- Nested brackets within values MUST be escaped:
\[and\]. - Fields are block-context-aware: a field inside a heading is associated with that heading's scope.
Fields are scoped to their nearest parent block. A runtime MUST be able to query fields by key across the document or within a specific block scope.
## Pricing
[price: $29/mo] [trial: 14 days]
## Enterprise
[price: custom] [trial: 30 days]In this example, querying price globally returns two results. Querying price within the Enterprise heading scope returns custom.
When a Layer 1 schema defines a field, and that field appears in the document as a Layer 2 inline field, the inline field takes precedence during deserialization. This allows authors to override schema-derived values inline.
Layer 3 introduces executable natural language directive blocks. These are fenced code blocks with the language identifier spec that contain prose instructions interpreted by an AI runtime during document transformation.
```spec
Summarize the previous three sections into an executive summary
targeting a CFO audience. Keep it under 200 words.
```Directives are standard Markdown fenced code blocks. In a non-SpecScript renderer, they display as preformatted text with the language label spec. In a SpecScript runtime, they execute.
A directive is a natural language instruction that the runtime interprets and executes during a transformation pass. Directives may:
- Generate content: Produce new Markdown blocks inserted at the directive's position in the document.
- Transform content: Modify, condense, expand, reformat, or restyle surrounding blocks.
- Conditionally include/exclude content: Control which blocks appear in the output based on target, audience, data, or any condition expressible in natural language.
- Reference data: Access fields defined via Layer 2, data from Layer 1 schemas, or external data sources defined in frontmatter.
- Call tools: Invoke registered tools or MCP servers available to the runtime (see §6.5).
- Chain: Reference the output of previous directives. Execution order is top-to-bottom.
A directive has access to:
- The full document AST at the point of execution (blocks above it are resolved; blocks below are unresolved).
- All Layer 2 fields in the document.
- Layer 1 schema and data, if defined.
- Frontmatter metadata.
- Runtime-provided context (target format, environment variables, user identity, timestamp).
A directive MAY trigger external tool invocations if the runtime supports it. Tool availability is declared in frontmatter or runtime configuration:
---
runtime:
tools:
- mcp: https://mcp.slack.com/mcp
- mcp: https://gcal.mcp.claude.com/mcp
- fetch: true
---A directive like:
```spec
Pull my calendar events for next week and generate a
schedule summary as a table.
```...would invoke the Google Calendar MCP tool, receive structured data, and render it as a Markdown table via Layer 1 translation.
Directives MAY include structured metadata as YAML at the top of the block, separated from the natural language body by ---:
```spec
cache: true
target: [html, pdf]
---
Generate a comparison table against competitors listed
in the schema. Cite only public pricing pages.
```| Key | Type | Description |
|---|---|---|
cache |
boolean |
Whether the directive output may be cached across runs. |
target |
string | array |
Execute only when transforming to the specified target(s). |
depends |
string | array |
Block IDs or directive IDs that must resolve before this one. |
id |
string |
A unique identifier for this directive, referenceable by others. |
mode |
string |
replace (default) inserts output at directive position. append adds after. prepend adds before. |
If a directive fails (AI cannot interpret, tool call fails, data unavailable), the runtime MUST:
- Insert an error block at the directive's position indicating the failure.
- Continue processing subsequent directives (fail-open by default).
- Surface all errors in a structured transformation report.
A runtime MAY support a strict mode in frontmatter (runtime.strict: true) that halts transformation on any directive failure.
A conforming runtime processes a SpecScript document in the following order:
- Parse: Read the document into a block-level AST.
- Resolve frontmatter: Extract metadata, schema, data references, runtime config.
- Load schema and data: Fetch external schemas and data sources if referenced.
- Layer 2 extraction: Identify and index all inline fields.
- Layer 3 execution: Walk the AST top-to-bottom. For each directive block, interpret and execute it, replacing the directive with its output (or inserting/appending per
mode). - Layer 1 translation: If an output target is specified, translate the resolved AST into the target format using registered block translators.
- Emit: Output the final result.
If multiple output targets are specified, the runtime executes steps 5–7 independently per target. Target-conditional directives (via target metadata) execute only for matching targets.
A SpecScript document with no directives and no external data references MUST produce identical output across transformation passes. Documents with directives or external data MAY produce different output (e.g., if a tool returns live data). The cache directive metadata allows authors to opt into idempotent behavior for specific directives.
A runtime declares conformance at one or more layer levels:
| Level | Requirements |
|---|---|
| SpecScript/L1 | Implements Layer 1 bidirectional translation with schema support. |
| SpecScript/L2 | Implements Layer 2 inline field parsing and querying. |
| SpecScript/L3 | Implements Layer 3 directive interpretation and execution. |
| SpecScript/Full | Implements all three layers and the full transformation pipeline. |
A runtime MAY implement layers incrementally. Layer 2 and Layer 3 may be implemented independently of each other; both depend on the AST parsing capability assumed by Layer 1.
A conforming runtime MUST:
- Parse any valid Markdown document without error.
- Preserve non-SpecScript Markdown content exactly.
- Degrade gracefully: a document with features above the runtime's conformance level MUST still render its static Markdown content. Unsupported directives SHOULD be emitted as code fences. Unsupported fields SHOULD be emitted as bracketed text.
- Surface errors structurally, never silently.
The spec does not mandate a specific AI provider, model, or API. A runtime MAY use any language model capable of interpreting natural language directives and performing schema-driven translation. The runtime SHOULD allow users to configure their preferred model.
Directives are executable. A runtime MUST treat directive content as potentially untrusted if the document source is not verified. Runtimes SHOULD implement:
- Permission scoping: Tool calls require explicit opt-in via frontmatter or runtime configuration.
- Sandboxing: Directive execution should not have access to the host filesystem, network, or environment beyond explicitly granted permissions.
- Audit logging: All tool invocations triggered by directives SHOULD be logged.
A malicious document could craft directives that exfiltrate inline field data or schema data via tool calls. Runtimes MUST validate that tool invocations are consistent with declared permissions and SHOULD warn users when a directive attempts to send data to an undeclared endpoint.
Directive content is interpreted by an AI model. Standard prompt injection considerations apply. Runtimes SHOULD isolate directive interpretation from system-level instructions and SHOULD NOT allow directive content to override runtime safety constraints.
- File extension:
.specscript.md(preferred) or.ss.md(short form) - MIME type:
text/markdown+specscript(proposed; pending IANA registration) - Fallback:
text/markdown(SpecScript documents are valid Markdown)
The reference implementation is Prose, a Markdown editor with native SpecScript support. Prose provides:
- Visual editing of SpecScript documents with directive blocks rendered in source mode.
- Live preview of directive execution results.
- Layer 2 field inspection and querying via UI.
- MCP tool integration for Layer 3 tool calls.
A standalone CLI runtime (specscript-cli) is planned for CI/CD and pipeline integration.
The following topics are deferred to subsequent RFCs:
- RFC-0002: SpecScript Schema Format — a dedicated schema language optimized for SpecScript translation contracts, potentially self-hosted as SpecScript documents.
- RFC-0003: Directive Standard Library — a catalog of common directive patterns (summarize, translate, condense, expand, compare, generate-table) with specified behavior for interoperability across runtimes.
- RFC-0004: Composition and Imports — mechanisms for one SpecScript document to import blocks, fields, or directives from another.
- RFC-0005: Versioning and Migration — how documents declare version requirements and how runtimes handle version mismatches.
SpecScript emerges from work on programmable content systems, the conviction that documents should carry their own logic, and the observation that AI has made natural language a viable scripting interface.
This document is itself a Markdown file. In a future where this RFC is a SpecScript document, it would contain directives that generate the conformance test suite from the spec text.