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
!includeresolves relative to the input file by default. For stdin, set--include-root DIR(strict) or--compat extendedto fall back to CWD.!themeand unsupportedskinparamkeys 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)
| Arrow | Meaning |
|---|---|
-> | synchronous request |
--> | synchronous response (dashed) |
->> | asynchronous |
-x | lost 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:
|
|
|
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.