Press executes programs written in Markdown. You define services with input/output contracts, and an LLM wires and runs them -- reading the contracts, building a dependency graph, and spawning child loops to execute each service. Programs get better automatically as models improve, because they declare what to produce, not how to produce it.
Press is an RLM (Recursive Language Model) -- a system where an LLM operates in a persistent REPL loop, writing and executing code until it completes a task. The model can recursively invoke itself via press() for subtasks.
npm install -g @openprose/presscould-haiku is a documentation quality measurement instrument. It spawns 4 service types across 14 instances:
- scraper -- fetches and parses the documentation site
- tester (x9, parallel) -- 3 agents at each of 3 capability tiers (haiku, sonnet, opus) independently attempt to understand and use the tool from its docs alone
- synthesizer -- cross-references results across tiers to identify clarity, complexity, and ambiguity patterns
- reporter -- produces a diagnostic with per-section scores and recommendations
The program runs 9 testers in parallel, fans results into a synthesizer, and produces a structured report. Total execution: ~9 minutes, ~2M tokens. No glue code -- just Markdown files with contracts.
Here is the mechanics. A two-service program that uppercases text and reports on it:
index.md
---
name: trivial-pipeline
kind: program
services: [uppercaser, reporter]
---
requires:
- text: a piece of text to process
ensures:
- report: a summary showing the uppercased text and its character countuppercaser.md
---
name: uppercaser
kind: service
---
requires:
- text: a piece of text
ensures:
- uppercased: the text converted to all uppercasereporter.md
---
name: reporter
kind: service
---
requires:
- uppercased: uppercased text to report on
ensures:
- report: a summary showing the uppercased text and its character countRun it:
press run ./my-program/index.md --text "hello world"Press reads the contracts, wires uppercaser.ensures.uppercased to reporter.requires.uppercased, spawns each service as an LLM session, and returns the report. No glue code. The model satisfies the contracts.
Prose programs default to declarative contracts -- the model decides how to satisfy them. Authors who need more control can specify explicit wiring (Level 2) or step-by-step execution blocks (Level 3) for determinism.
Contracts aren't just documentation -- they change behavior. Here's a service with shape constraints and strategies:
---
name: researcher
kind: service
shape:
self: [evaluate sources, score confidence]
delegates:
summarizer: [compression]
prohibited: [direct web scraping]
---
requires:
- topic: a research question
ensures:
- findings: sourced claims from 3+ distinct sources, each with confidence 0-1
- if sources are unavailable: partial findings from cached data, flagged as stale
strategies:
- when few sources found: broaden search terms
- when many low-quality sources: prioritize academic and primary sourcesshape.prohibited prevents the model from scraping -- it must use other
tools. ensures with a conditional clause means the service degrades
gracefully instead of failing. strategies guide behavior without being
prescriptive -- the model adapts based on what it observes.
Programs default to declarative contracts (the model decides how). Authors who need more control can pin the wiring (Level 2) or write explicit execution blocks (Level 3) for full determinism.
Press is designed for complex, multi-agent analytical and generative tasks where the overhead of the two-phase pipeline is amortized across many services.
Good fit:
- Documentation analysis with multiple independent evaluators (could-haiku)
- Research pipelines with scraping, analysis, and synthesis stages
- Content generation with iterative refinement (worker-critic loops)
- Any task where you'd otherwise write 200+ lines of LLM orchestration code
Not a good fit:
- Simple, single-step LLM calls (use your model's API directly)
- Tasks requiring sub-second latency
- Deterministic pipelines where the output must be identical every run (though explicit execution blocks give you more control)
Typical costs:
- Simple 2-service program: ~50K tokens, ~60 seconds
- Medium 4-service program: ~100K tokens, ~2 minutes
- Complex 14-service program (could-haiku): ~2M tokens, ~9 minutes
Most agent frameworks orchestrate LLM calls -- you write code that chains prompts together. Press gives the LLM a sandbox and lets it write programs. The model reads your contracts, decides how to satisfy them, and writes JavaScript to do so.
The key difference: Press programs improve when you swap in a smarter model, without changing any code. A more capable model satisfies the same contracts more efficiently. Your programs are assets that appreciate with model capability.
Press also has no tool-calling, no function schemas, no API wrappers. The model's only tool is a JavaScript sandbox with press() for recursion and RETURN() for completion. One runtime dependency (acorn).
Press runs Prose programs in two phases:
-
Forme (wiring) -- The LLM reads the program's contracts, builds a dependency graph, and writes a
manifest.md. This is the Forme container phase: auto-wiringrequiresagainstensures. -
Prose VM (execution) -- The LLM reads the manifest and walks the execution order. For each service, it calls
press("serviceName", { inputs, workspace }), which spawns a child REPL loop with the service definition and resolved inputs.
Key design decisions:
- The model IS the CPU. Press builds system prompts and runs the sandbox. The LLM reads specs and writes code. Press is the computer; the model is the intelligence.
- Services communicate via filesystem. Each service gets a workspace directory. Outputs are written to files, then copied to the parent's bindings. State is managed on disk, not in memory.
press()for delegation,RETURN()to complete. Two primitives.press("researcher", { inputs })spawns a child session.RETURN(value)ends the current loop.console.log()observes.contextholds input data.- Pass by reference, resolve on entry. The VM passes file paths to children. Press resolves them to content when building the child's system prompt. Children see values, not paths.
| Action | Who |
|---|---|
| Build system prompt for each phase (load specs, wrap in XML) | Press |
| Run the REPL loop (call LLM, extract code, execute, observe) | Press |
| Resolve input paths to content for child press() calls | Press |
| Execute code blocks in sandbox | Press |
| Everything below: the model | |
| Read service files, parse contracts, wire dependencies | Model |
| Write manifest with dependency graph | Model |
| Create directory structure, manage state.md | Model |
| Decide when to call press() and with what arguments | Model |
| Decide when to use Promise.all for parallelism | Model |
| Copy files from workspace to bindings | Model |
| Evaluate contract satisfaction, handle errors | Model |
| Program | Model | Status | Time | Tokens |
|---|---|---|---|---|
| trivial-pipeline | Sonnet 4.6 | PASS | 64s | 50K |
| parallel-analysis | Sonnet 4.6 | PASS | 65s | 58K |
| haiku-refiner | Sonnet 4.6 | PASS | 157s | 89K |
| bilingual-haiku | Sonnet 4.6 | PASS | 196s | 97K |
| error-handling | Sonnet 4.6 | PASS | 101s | 68K |
| could-haiku | Sonnet 4.6 | PASS | 544s | ~2M |
Requires Node.js >= 20.
npm install -g @openprose/press
export OPENROUTER_API_KEY="your-key"
press run your-program/index.md --text "hello world"git clone https://github.com/openprose/press.git
cd press
npm installCopy the example env file and add your API key:
cp .env.example .env
# Edit .env and set OPENROUTER_API_KEYRun tests (no API key needed):
npm testimport { pressRun } from "@openprose/press";
const result = await pressRun({
callLLM,
specDir: "./prose-specs",
programPath: "./my-program/index.md",
programDir: "./my-program",
callerInputs: { text: "hello world" },
});
console.log(result.answer);
console.log(result.phaseResults.forme.iterations); // Forme iterations used
console.log(result.phaseResults.vm.iterations); // VM iterations used| Option | Type | Default | Description |
|---|---|---|---|
callLLM |
CallLLM |
(required) | (messages, systemPrompt) => Promise<string> |
specDir |
string |
(required) | Directory containing prose.md, forme.md, etc. |
programPath |
string |
(required) | Path to the program entry point (.md file) |
programDir |
string |
(required) | Directory containing the program and service files |
callerInputs |
Record<string, string> |
(required) | User inputs matching the program's requires |
maxIterations |
number |
15 | Iteration budget per phase |
maxDepth |
number |
3 | Delegation depth limit |
Press needs the Prose and Forme specification files (prose.md, forme.md,
session.md, filesystem.md) to tell the LLM how to wire and execute programs.
CLI users: Press resolves specs automatically from the companion
openprose/prose repository. If you've
cloned both repos as siblings, it just works. Otherwise, set --spec-dir or
the PRESS_SPEC_DIR environment variable.
Programmatic API users: Pass specDir pointing to the directory containing
the spec files. Clone the prose repo and
point to prose/skills/open-prose/:
const result = await pressRun({
specDir: "./prose/skills/open-prose",
// ...
});The specs define how the LLM acts as the Forme container (wiring) and the Prose VM (execution). They are the "instruction set" of the Press computer.
Run the eval suite:
npx tsx src/eval-pipeline.tsThis runs all programs in the default spec against Sonnet 4.6, tracks tokens and timing, and writes results to eval-results/. Use --concurrency to control parallelism, --spec-file for custom specs.
Think of it like the Java ecosystem: Prose is the language, Forme is Spring (the wiring framework), Press is the JVM (the computer that runs it).
- Press is the runtime (this repo). MIT licensed.
- Prose is the programming language. Programs are Markdown files with contracts.
- Forme is the wiring framework. It reads contracts and produces a manifest.
- The language and specs live at github.com/openprose/prose.
- LANGUAGE.md -- Press runtime documentation
- CONTAINER.md -- Container and execution model
- STDLIB.md -- Standard library reference (composites, controls, roles, drivers)
- OBSERVABILITY.md -- Observability and tracing
- TENETS.md -- Design principles
- CHANGELOG.md -- Release history
- Prose -- The programming language Press executes
MIT