Language Reference

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

BlockCapturesRequired?
@headerOne-paragraph agent intropoint — summary, owner, status, since, tags, entrypoint.Optional
@futureGuarantees, constraints, observable behaviors. The bound on everything below.Required for any non-trivial program
@shapeModules, interfaces, technology choices via @version, mappings via serves: [guarantee].Required if @flow is present
@flowInter-module choreography. Typed arrows (-> TypeName ->) verify integration contracts.Optional — many programs stop at @shape
@implReal 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 rules

CodeWhat it catches
S002@flow references a module not declared in @shape.
S003@flow event isn't accepted by any @shape module.
S004A module has zero or multiple active @version blocks (must be exactly one).
S005Dormant @version missing required reason:.
S006@impl missing target language declaration.
S007Guarantee in @future not served by any module (warning).
S010Levels not contiguous from top.
S011Module's serves: [name] references unknown guarantee.
S012Typed arrow doesn't match upstream emits: or downstream accepts: (warning).
S013Duplicate file "path" within an @impl.
S014@header present but missing required summary.
S015@extension missing name or version.
S018Cross-file reference to a guarantee that doesn't exist in the imported file.
S019Cross-file reference to a module that doesn't exist in the imported file.
E001Unknown @block detected (info, never an error — Tier-1 extension passthrough).

Loader rules

CodeWhat it catches
L001Imported file missing or unreadable.
L002Parse error inside an imported file.
L003Circular import detected (chain reported).
L004Duplicate alias in the same import block.
L005Invalid alias shape (must be a plain identifier).

Deeper references

Each of these is a focused doc covering one slice of the language:

Three-tier extensibility

Retro core stays domain-neutral. Domain vocabularies live as extensions:

TierWhat you writeWhat 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.