SpecTree is a Markdown format for writing composable specs for LLM tools.
The format is standard Markdown (of any flavor), with 3 additions:
{{variable}}substitution from frontmatter@includecontent from other files by pathextendskeyword to inherit from a parent spec
This project defines the SpecTree format via language agnostic specs and test cases.
It also provides a spectree Markdown-to-Markdown preprocessor (as TypeScript/Python libraries or a CLI tool)
to resolve a SpecTree to its final output.
AI coding tools like Claude Code, Codex, or Jules are now very capable of following long detailed instructions, but they're typically limited by a context bottleneck. How do we feed them sufficient high quality instructions about what we want them to do?
Long monolithic prompts are hard to read, maintain, reuse, or share.
SpecTree lets you build context and specs like software - out of modular, composable, versionable pieces.
npm install -g @holdenmatt/spectree-cli
# Create example files
echo "Hello @world.md" > hello.md
echo "World!" > world.md
# Compile
spectree hello.md
# Output: Hello World!npm install @holdenmatt/spectreeimport { compile } from "@holdenmatt/spectree";
const output = await compile("path/to/spec.md");
console.log(output);pip install spectreefrom spectree import compile
output = compile('path/to/spec.md')
print(output)SpecTree adds three features to standard Markdown: Includes, Vars, and Extends.
Include content from another file by path:
# Project Spec
@requirements.md
@design/system.mdSubstitute variables from frontmatter:
---
role: helpful assistant
tone: friendly
---
You are a {{role}} with a {{tone}} tone.Output:
You are a helpful assistant with a friendly tone.Inherit from a parent spec with variable overrides:
---
extends: base-assistant.md
role: code reviewer
tone: professional and concise
---
Focus on finding bugs and style issues.The parent can use {{content}} to control where child content is inserted, or it's appended by default.
- Parse frontmatter
- Resolve parent documents recursively
- Cascade variables (child overrides parent)
- Substitute variables ({{vars}})
- Process includes (@references)
- Output compiled markdown
By default, all frontmatter is stripped from the compiled output. This lets you use frontmatter for metadata (eg author, version, date, etc) without polluting the output an LLM would see.
To preserve specific values in output, use the output: key:
---
author: Matt Holden # stripped
output:
temperature: 0.7 # preserved
---spectree/
├── packages/
│ ├── spectree/ # Core TypeScript library (ESM)
│ └── spectree-cli/ # CLI package (bin: `spectree`)
├── specs/ # Markdown specs
├── tests/ # Markdown test cases
└── examples/ # SpecTree examples
For detailed specs and edge case handling, see the /specs folder and corresponding test cases.
- Ted Nelson's transclusion concept (1965) - including content by reference
- Knuth's literate programming (1984) - weaving documents from components
- Jekyll's template inheritance with
layoutand{{ content }} - CSS cascade model for variable inheritance
- Long history of preprocessors: from cpp for C to Sass/LESS for CSS
MIT