Struckdown
Markdown-based syntax for structured conversations with language models.
Struckdown makes it easy to extract structured, typed data from text using LLMs. Instead of parsing free-form responses, you define exactly what you want with a simple template syntax.
Quick Example
Turn unstructured text into structured data:
sd batch *.txt "Purpose, <5 words: [[purpose]]"
Output:
[
{"filename": "butter_robot.txt", "purpose": "Pass butter, question existence."},
{"filename": "portal_gun.txt", "purpose": "Interdimensional travel device."}
]
Or with type constraints:
sd batch *.txt "Price: [[number:price]] Currency: [[pick:currency|USD,GBP,EUR]]"
Key Features
- Slot syntax –
[[variable]]for completions,[[type:variable]]for typed extraction - Type safety – Extract booleans, numbers, dates, or pick from options
- Batch processing – Process hundreds of files with progress bars
- Token management – Use
<checkpoint>to save tokens between steps - Caching – Automatic disk caching saves money and time
- Custom actions – Extend with Python functions (RAG, APIs, databases)
- Web integration – Fetch URLs and search the web directly in prompts
- Multiple outputs – JSON, CSV, Excel, or stdout
Installation
# Requires UV (https://docs.astral.sh/uv/)
uv tool install git+https://github.com/benwhalley/struckdown
Configure your LLM:
export LLM_API_KEY="sk-..."
export LLM_API_BASE="https://api.openai.com/v1"
export DEFAULT_LLM="gpt-4o-mini"
Basic Usage
Single Prompts
# Simple extraction
sd chat "Is Python compiled? [[bool:answer]]"
# Pick from options
sd chat "Sentiment of 'I love it': [[pick:sentiment|positive,negative,neutral]]"
# Number with constraints
sd chat "Rate 1-10: 'Great!' [[int:rating|min=1,max=10]]"
Batch Processing
# Process files to JSON
sd batch *.txt "Summarise: [[summary]]" -o results.json
# Extract to CSV
sd batch documents/*.txt "Name: [[extract:name]] Email: [[extract:email]]" -o contacts.csv
# Chain operations
sd batch *.txt "Company: [[extract:company]]" | \
sd batch "Find stock ticker: [[ticker]]" -k
Multi-Step Reasoning
sd chat "
Document:
Extract key points: [[extract+:points]]
<checkpoint>
Based on:
Recommendation: [[recommendation]]
" -s document.txt
Python API
from struckdown import chatter
result = chatter("""
Analyse this review:
Sentiment: [[pick:sentiment|positive,negative,neutral]]
Rating: [[int:rating|min=1,max=5]]
""", context={"review": "Great product but slow shipping"})
print(result["sentiment"]) # "positive"
print(result["rating"]) # 4
print(result.total_cost) # 0.0001 (USD)
Documentation
| Section | Description |
|---|---|
| Getting Started | Installation and first steps |
| Template Syntax | Complete syntax reference |
| CLI Reference | All CLI commands |
| Custom Actions | Extend with Python plugins |
| Caching | How caching works |
| API Reference | Python API documentation |
Environment Variables
| Variable | Description | Default |
|---|---|---|
LLM_API_KEY | API key for LLM provider | Required |
LLM_API_BASE | API base URL (OpenAI-compatible) | OpenAI default |
DEFAULT_LLM | Default model name | gpt-4o-mini |
STRUCKDOWN_CACHE | Cache directory (0 to disable) | ~/.struckdown/cache |
STRUCKDOWN_CACHE_SIZE | Cache size limit in MB | 10240 (10 GB) |
SD_MAX_CONCURRENCY | Max concurrent API calls | 20 |