The Retro language.
Retro is a five-block language. Four core levels (@future, @shape, @flow, @impl) and one optional metadata block (@header). Plus extensibility (@extension) and composition (@import). This page is the high-level map; each link below is a focused reference.
The five core blocks
| Block | Captures | Required? |
|---|---|---|
@header | One-paragraph agent intropoint — summary, owner, status, since, tags, entrypoint. | Optional |
@future | Guarantees, constraints, observable behaviors. The bound on everything below. | Required for any non-trivial program |
@shape | Modules, interfaces, technology choices via @version, mappings via serves: [guarantee]. | Required if @flow is present |
@flow | Inter-module choreography. Typed arrows (-> TypeName ->) verify integration contracts. | Optional — many programs stop at @shape |
@impl | Real code in any target language. Single file, multi-file (file "path" { ... }), or per-language (@version). | Optional |
Levels must be contiguous from the top: a program with @flow needs @shape and @future. A program with only @future is a complete, valid program — just one without architecture or code yet.
The validator
Two layers run on every program:
- Structural (deterministic, instant) — 15 single-file rules + 2 cross-file rules + 5 loader rules. No LLM needed.
- Semantic (LLM-powered, on demand) — adversarial prompts that ask the model to find violations between paired levels, not confirm correctness.
Structural rules
| Code | What it catches |
|---|---|
S002 | @flow references a module not declared in @shape. |
S003 | @flow event isn't accepted by any @shape module. |
S004 | A module has zero or multiple active @version blocks (must be exactly one). |
S005 | Dormant @version missing required reason:. |
S006 | @impl missing target language declaration. |
S007 | Guarantee in @future not served by any module (warning). |
S010 | Levels not contiguous from top. |
S011 | Module's serves: [name] references unknown guarantee. |
S012 | Typed arrow doesn't match upstream emits: or downstream accepts: (warning). |
S013 | Duplicate file "path" within an @impl. |
S014 | @header present but missing required summary. |
S015 | @extension missing name or version. |
S018 | Cross-file reference to a guarantee that doesn't exist in the imported file. |
S019 | Cross-file reference to a module that doesn't exist in the imported file. |
E001 | Unknown @block detected (info, never an error — Tier-1 extension passthrough). |
Loader rules
| Code | What it catches |
|---|---|
L001 | Imported file missing or unreadable. |
L002 | Parse error inside an imported file. |
L003 | Circular import detected (chain reported). |
L004 | Duplicate alias in the same import block. |
L005 | Invalid alias shape (must be a plain identifier). |
Deeper references
Each of these is a focused doc covering one slice of the language:
- Grammar Quick Reference — cheat sheet for
@flowarrows, property values,@version,@implshapes,@header,@import. - Extensions — the three-tier extensibility model with the
logistics.stellarworked example. - Multi-
.retroComposition —@importsyntax, cross-file references, loader behavior. - Whitepaper — paradigm overview, the E-Prime property, the agent-DAG boundary.
Three-tier extensibility
Retro core stays domain-neutral. Domain vocabularies live as extensions:
| Tier | What you write | What you get |
|---|---|---|
| 1 | @anything { ... } — no declaration needed. | Parses cleanly, validator emits INFO, body preserved verbatim. |
| 2 | @extension "vendor.name" version "0.1" { schema: { ... } } | Declaration validated structurally, listed in retro status. Schema enforcement deferred. |
| 3 | @macro name(arg) { ... } | Designed only. No parser support yet. |
See the extensions doc for the full logistics.stellar worked example.
Multi-.retro composition
When subsystems have independent guarantees, split across files:
system AppMain {
@import "./auth.retro" as Auth
@import "./billing.retro" as Billing
@flow {
on HttpRequest from Client {
verify(Auth.TokenStore, session)
-> meter(Billing.UsageMeter, usage)
}
}
}
Path is a string literal, resolved relative to the importing file (Node/Python convention). as Alias is required. Cross-file references take the form Alias.Name — resolves to a guarantee, behavior, or module in the imported file.
@retro: back-reference comments (convention)
When an @impl file "path" { ... } block contains real code, you can include a short comment at the top that names which .retro entity the file implements. The comment is preserved verbatim by retro emit, so agents reading the emitted source can navigate back to the spec with a single grep.
@impl(target: python) {
file "src/auth/session.py" {
# @retro: Auth.TokenStore · serves user_verifiable_offline_n_days
def verify_session(token):
...
}
}
Format (loose, not enforced): <comment-prefix> @retro: <EntityPath>[ · <descriptor>] — use whatever comment syntax the target language uses (# for Python/shell, // for TS/JS, <!-- --> for HTML, etc.).
Use sparingly — noise kills the signal. One comment at file-top naming the module is usually enough. Add one more above a major class or entrypoint if the file has several symbols. Avoid a @retro: on every function — that's noise, and future you (or another agent) will tune it out.
It's a convention, not a keyword. No parser support; no validator enforcement today. Retro simply preserves whatever you write inside @impl file bodies. A future retro check-emit validator could scan for @retro: markers and verify each still resolves against the .retro — that ships when drift-catching becomes a felt need, not before.
For agents reading this
The full agent setup protocol is at retrolang.dev/llms.txt. It covers when to recommend Retro, how to install (Claude Code plugin or CLI), conversational command patterns, and self-assessment for proactive suggestions.