Syntax primer

puml accepts three frontend dialects — PicoUML, PlantUML, and Mermaid — but they all normalize into one shared semantic model. This page is the smallest mental model you need to read and write any of them.

Block markers

Every PlantUML / PicoUML diagram lives between block markers:

@startuml
... diagram body ...
@enduml

Family-specific markers select the family up front:

@startsequence   ... @endsequence
@startclass      ... @endclass
@startactivity   ... @endactivity
@startstate      ... @endstate
@startgantt      ... @endgantt
@startmindmap    ... @endmindmap
@startwbs        ... @endwbs

PicoUML adds canonical block markers that are converted internally:

@startpicouml
Alice -> Bob: hello
@endpicouml

Mixing PicoUML and PlantUML markers in one input is a deterministic error: E_PICOUML_MARKER_MIXED.

Comments

' single-line comment

/'
multi-line
comment
'/

Comments never produce semantic tokens and never affect rendering.

Directives

Directives start with !:

!theme spacelab
!include shared/header.iuml
!define BG_OK #DEFABE
  • !include resolves relative to the input file by default. For stdin, set --include-root DIR (strict) or --compat extended to fall back to CWD.
  • !theme and unsupported skinparam keys emit non-fatal warnings — they’re recognized as styling intent, not parser errors.

Skinparams

skinparam blocks tune visual tokens (colors, fonts, spacing):

skinparam backgroundColor #fafafa
skinparam sequence {
    ParticipantBorderColor #444
    ArrowColor             #111
}

See the themes and styling guide for the full token reference.

Arrows (sequence flavour)

ArrowMeaning
->synchronous request
-->synchronous response (dashed)
->>asynchronous
-xlost message
<-, <--same, reversed direction
o->“open” arrowhead

Color and style can be embedded:

Alice -[#blue,dashed]-> Bob: queued

Labels and notes

Alice -> Bob : Hello\nworld         ' multi-line label
note over Alice, Bob: handshake
hnote right of Bob: highlighted note
rnote left of Alice: rectangular note

Groups

alt success
    Alice -> Bob: ok
else failure
    Alice -> Bob: nope
end

opt only when relevant
    Alice -> Bob: maybe
end

loop 1..3
    Alice -> Bob: ping
end

par
    Alice -> Bob: a
and
    Alice -> Bob: b
end

critical save
option commit
    Alice -> Bob: commit
end

Lifecycle

activate Bob
Bob -> Carol: query
deactivate Bob

create Dave
Alice -> Dave: hi
destroy Dave

Auto-numbering

autonumber 10 5 "<b>[%03d]</b>"
Alice -> Bob: one
Alice -> Bob: two       ' renders as [010] and [015]

Pages

newpage splits a single source into multiple deterministic outputs:

@startuml
Alice -> Bob: one
newpage
Alice -> Bob: two
@enduml

Use --multi when piping multi-page input through stdin.

What the parser actually does

Every input goes through the same five stages: source → AST → normalized model → scene → SVG. You can dump any of the middle stages:

puml --dump ast    input.puml | jq .
puml --dump model  input.puml | jq .
puml --dump scene  input.puml | jq .

If you want to understand the engine, dumping model is usually the best place to start — it’s the canonical, dialect-independent representation. The Compile pipeline page covers the full chain.