Install
openclaw skills install plantuml-skillTurn natural language into uml-diagrams.org style PlantUML diagrams (sequence, class, activity, use case, component, state…) and render to SVG/PNG/PDF. Use when the user asks to draw a UML diagram.
openclaw skills install plantuml-skillGenerate professional PlantUML diagrams from natural language descriptions. This skill handles the full pipeline: requirement analysis → PlantUML code generation → image rendering.
Use this skill when the user asks to:
ALL diagrams generated by this skill MUST adhere to the uml-diagrams.org reference style — strict OMG UML 2.x rendered with Visio UML 2.x stencils (black-and-white, no decoration). This is the canonical style used throughout https://www.uml-diagrams.org and serves as the authoritative visual reference for every diagram this skill produces. No exceptions unless the user explicitly requests otherwise.
#000000) on a pure white background (#FFFFFF). No colors, no grayscale fills, no gradients, no themed accents.skinparam classAttributeIconSize 0. Use + - # ~ text markers only.skinparam style strictuml enforces text stereotypes («interface», «abstract», «enumeration»). Always declare interfaces/abstract classes via class <<interface>> or class <<abstract>> — never use the interface or abstract class keywords.<<abstract>> text stereotype with strictuml produces the correct italic rendering automatically.skinparam shadowing false).X at the bottom of the lifeline (PlantUML <participant> ! syntax).«include» / «extend» as dashed open arrows.Every .puml file MUST include the mandatory uml-diagrams.org-style preamble as its first lines after @startuml (see Style Configuration).
Extract from the user's description:
If the diagram type is not explicitly stated, infer it from the description:
| Description signals | Recommended diagram |
|---|---|
| "A sends X to B", "request/response", "handshake" | Sequence |
| "inherits from", "has many", "belongs to", entities & fields | Class |
| "if/then", "approve/reject", workflow, pipeline | Activity |
| "user can", "admin manages", roles & permissions | Use Case |
| "depends on", "connects to", services & interfaces | Component |
| "deployed on", "hosted on", nodes & servers | Deployment |
| "transitions from", "changes state", lifecycle | State |
| timeline, milestones, phases, schedule | Gantt |
| hierarchy, brainstorming, tree structure | Mind Map |
If ambiguous, ask the user to clarify the diagram type before proceeding.
Write the PlantUML source following these rules:
@startuml:
skinparam preamble — see OMG-UML / uml-diagrams.org Style Configuration.
Maximum backward compatibility, used by every example except #07.<style> preamble — see Alternative — CSS-style Preamble.
Recommended on PlantUML ≥ 1.2019.9 where skinparam is being phased out.
Pick ONE per file — never mix both inside the same .puml.@startuml / @enduml delimiterstitleSave the PlantUML source to a .puml file in the working directory.
Use the bundled conversion script. Pick the variant that matches the current OS / shell:
Linux, macOS, or Windows with a POSIX shell (Git Bash, MSYS2, WSL, Cygwin):
bash .opencode/skills/plantuml/scripts/generate-plantuml.sh <input.puml> <output_dir> --format <svg|png|pdf|txt>
Windows native PowerShell (no bash required):
powershell -ExecutionPolicy Bypass -File .opencode\skills\plantuml\scripts\generate-plantuml.ps1 <input.puml> <output_dir> -Format <svg|png|pdf|txt>
Both scripts accept the same arguments and try three backends in strict priority order. The PlantUML public server is the preferred / default path; Docker and the local JAR are only used as fallbacks when the server is unreachable:
docker pull plantuml/plantuml:latest) — fallbackplantuml.jar (requires Java) — last-resort offline fallbackAfter rendering, show the user the output. If SVG is generated, read and display it inline. If PNG/PDF is generated, tell the user where the file is saved.
If the user requests changes:
.puml fileNote: All examples below omit the mandatory monochrome preamble for brevity. In actual generated code, EVERY file MUST include the OMG-UML style preamble immediately after
@startuml. The class diagram example shows the full preamble inline as a reference.
@startuml
title Authentication Flow
actor User
participant "Web App" as App
participant "Auth Service" as Auth
database "User DB" as DB
User -> App: Login (email, password)
App -> Auth: POST /auth/login
Auth -> DB: SELECT user WHERE email
DB --> Auth: user record
Auth -> Auth: Verify password hash
alt Success
Auth --> App: JWT token
App --> User: Dashboard
else Failure
Auth --> App: 401 Unauthorized
App --> User: Error message
end
@enduml
Key syntax: -> sync message, --> async/return, ->> async, alt/else/end branching,
loop/end loops, opt/end optional, activate/deactivate lifeline, note left/right
@startuml
' OMG-UML Monochrome Style
skinparam style strictuml
skinparam monochrome true
skinparam backgroundColor white
skinparam defaultFontName Helvetica
skinparam shadowing false
skinparam classAttributeIconSize 0
skinparam sequenceMessageAlign center
skinparam ActorBackgroundColor white
skinparam ParticipantBackgroundColor white
skinparam NoteBackgroundColor white
skinparam SequenceGroupBackgroundColor white
skinparam PackageBackgroundColor white
skinparam ClassBackgroundColor white
title Payment System
class User {
+id: UUID
+email: String
+name: String
+register()
}
class Order {
+id: UUID
+total: Decimal
+status: OrderStatus
+calculateTotal()
}
class PaymentProcessor <<interface>> {
+processPayment(amount: Decimal): Boolean
+refund(transactionId: UUID): Boolean
}
class NotificationService <<abstract>> {
#enabled: Boolean
+{abstract} send(to: String, body: String)
}
enum OrderStatus {
PENDING
CONFIRMED
SHIPPED
DELIVERED
}
User "1" -- "*" Order : places
Order ..|> PaymentProcessor
NotificationService <|-- EmailNotifier
@enduml
Key syntax: + public, - private, # protected, {abstract} abstract method,
class Foo <<interface>> (interface via text stereotype — NOT interface Foo),
class Bar <<abstract>> (abstract class — NOT abstract class Bar),
enum, relationships: -- association, *-- composition, o-- aggregation,
<|-- inheritance, ..|> realization
@startuml
title Order Processing
start
:Receive Order;
if (Payment Valid?) then (yes)
:Reserve Inventory;
if (Inventory Available?) then (yes)
:Confirm Order;
:Ship Order;
stop
else (no)
:Notify Customer;
:Cancel Order;
stop
endif
else (no)
:Reject Order;
stop
endif
@enduml
Key syntax: start/stop/end, if/then/else/endif, repeat/repeat while,
fork/fork again/end fork (parallel), split/split again/end split,
partition "name" { ... } (swimlane), :Text; action
@startuml
title E-Commerce System
left to right direction
actor Customer
actor Admin
rectangle "E-Commerce" {
usecase "Browse Products" as UC1
usecase "Place Order" as UC2
usecase "Manage Inventory" as UC3
usecase "Process Returns" as UC4
}
Customer --> UC1
Customer --> UC2
Admin --> UC3
Admin --> UC4
UC2 ..> UC1 : <<include>>
@enduml
Key syntax: actor, usecase, rectangle/package for system boundary,
--> association, ..> dependency, <<include>> / <<extend>> stereotypes
@startuml
title Microservice Architecture
package "Frontend" {
[Web App]
[Mobile App]
}
package "API Gateway" {
[Gateway]
}
package "Services" {
[User Service]
[Order Service]
[Payment Service]
}
database "PostgreSQL" as DB
cloud "Message Queue" as MQ
[Web App] --> [Gateway]
[Mobile App] --> [Gateway]
[Gateway] --> [User Service]
[Gateway] --> [Order Service]
[Order Service] --> [Payment Service]
[User Service] --> DB
[Order Service] --> DB
[Order Service] --> MQ
@enduml
Key syntax: [Component], package "name" { }, database, cloud, node,
frame, interface, ()-- required interface, --() provided interface
@startuml
title Production Deployment
node "AWS us-east-1" {
node "VPC" {
node "Public Subnet" {
[Load Balancer]
[Bastion Host]
}
node "Private Subnet" {
node "App Server 1" {
[Application]
}
node "App Server 2" {
[Application]
}
database "RDS Primary"
}
}
cloud "CDN"
}
@enduml
Key syntax: node "name" { }, nested node, database, cloud, actor
@startuml
title Order Lifecycle
[*] --> Draft
Draft --> Submitted : submit()
Submitted --> Paid : processPayment()
Submitted --> Cancelled : cancel()
Paid --> Shipped : ship()
Shipped --> Delivered : confirmDelivery()
Delivered --> [*]
Cancelled --> [*]
state Paid {
[*] --> Authorizing
Authorizing --> Captured : success
Authorizing --> Failed : decline
Captured --> [*]
}
@enduml
Key syntax: [*] start/end, --> transition with optional : label,
state Name { } composite state, state "Name" as Alias
@startuml
title Project Roadmap
project starts 2025-01-06
[Design] lasts 10 days
[Development] lasts 20 days
[Development] starts at [Design]'s end
[Testing] lasts 10 days
[Testing] starts at [Development]'s end
[Deployment] lasts 3 days
[Deployment] starts at [Testing]'s end
[Frontend] lasts 12 days
[Frontend] starts at [Design]'s end
[Backend] lasts 15 days
[Backend] starts at [Design]'s end
@enduml
Key syntax: project starts YYYY-MM-DD, [Task] lasts N days,
[Task] starts at [Other]'s end, -- separator for dependency,
printscale weekly/monthly, @dailymail, @weeklymail
@startmindmap
title System Architecture
* Root Node
** Level 1 A
*** Level 2 A1
*** Level 2 A2
** Level 1 B
*** Level 2 B1
**** Level 3 B1a
**** Level 3 B1b
** Level 1 C
@endmindmap
Key syntax: * root, ** level 1, *** level 2, etc.
Use @startmindmap / @endmindmap (not @startuml).
Affix _ to markdown-style side notation, e.g., ***_ Right side node.
Colors: <style> * { BackgroundColor lightblue } </style>
Every generated .puml file MUST include this preamble immediately after @startuml.
It locks PlantUML's rendering to the uml-diagrams.org reference style (strict OMG UML 2.x,
black-and-white Visio stencils):
' uml-diagrams.org reference style — strict OMG UML 2.x, monochrome
skinparam monochrome true
skinparam backgroundColor #FFFFFF
skinparam defaultFontName Helvetica
skinparam defaultFontSize 12
skinparam shadowing false
skinparam style strictuml
skinparam classAttributeIconSize 0
skinparam sequenceMessageAlign center
skinparam roundCorner 0
' Force every fill to white so monochrome never falls back to grey
skinparam ActorBackgroundColor #FFFFFF
skinparam ParticipantBackgroundColor #FFFFFF
skinparam NoteBackgroundColor #FFFFFF
skinparam SequenceGroupBackgroundColor #FFFFFF
skinparam PackageBackgroundColor #FFFFFF
skinparam ClassBackgroundColor #FFFFFF
skinparam ObjectBackgroundColor #FFFFFF
skinparam StateBackgroundColor #FFFFFF
skinparam UsecaseBackgroundColor #FFFFFF
skinparam ComponentBackgroundColor #FFFFFF
skinparam ActivityBackgroundColor #FFFFFF
skinparam NodeBackgroundColor #FFFFFF
skinparam DatabaseBackgroundColor #FFFFFF
skinparam StereotypeCBackgroundColor #FFFFFF
skinparam StereotypeIBackgroundColor #FFFFFF
skinparam StereotypeABackgroundColor #FFFFFF
skinparam StereotypeEBackgroundColor #FFFFFF
' Sequence diagrams — match the lifeline / activation look on uml-diagrams.org:
' * lifeline = dashed black vertical line
' * activation bar = thin WHITE rectangle with black border (NOT yellow)
skinparam SequenceLifeLineBorderColor #000000
skinparam SequenceLifeLineBackgroundColor #FFFFFF
skinparam SequenceLifeLineBorderThickness 0.75
skinparam SequenceActivationBackgroundColor #FFFFFF
skinparam SequenceActivationBorderColor #000000
skinparam SequenceArrowColor #000000
skinparam SequenceArrowThickness 0.75
skinparam SequenceBoxBackgroundColor #FFFFFF
' Default arrow / border colour everywhere
skinparam ArrowColor #000000
skinparam ArrowThickness 0.75
skinparam DefaultTextColor #000000
What each directive does (mapped to uml-diagrams.org figures):
| Directive | Effect / uml-diagrams.org reference |
|---|---|
skinparam monochrome true | Strips all PlantUML colour themes. Matches the Visio UML 2.x stencil look used across uml-diagrams.org. |
skinparam backgroundColor #FFFFFF | Pure white canvas — same as every figure on uml-diagrams.org. |
skinparam *BackgroundColor #FFFFFF (all element kinds) | Forces every classifier / actor / note / package / lifeline / state / use case / component / activity / node / database fill to pure white. Eliminates the grey fills monochrome would otherwise leave. |
skinparam defaultFontName Helvetica + size 12 | Sans-serif typography equivalent to Arial used by Visio stencils on uml-diagrams.org. |
skinparam shadowing false | Disables drop shadows — uml-diagrams.org figures never have shadows. |
skinparam style strictuml | Critical. Enforces text stereotypes («interface», «abstract», «enumeration») and removes the Ⓒ/Ⓘ/Ⓐ/Ⓔ circle adornments. Abstract classifier names render in italics, matching uml-diagrams.org §"Classifier". |
skinparam classAttributeIconSize 0 | Removes the coloured visibility dots (●/◐/○). uml-diagrams.org uses +/-/#/~ text markers only. |
skinparam roundCorner 0 | Square corners on rectangles (matches Visio stencils). Activity diagrams override locally for round-cornered actions. |
skinparam SequenceLifeLineBorderStyle (implicit dashed via strictuml) + SequenceLifeLineBorderColor #000000 | Lifelines render as dashed black lines — exactly the lifeline notation shown on uml-diagrams.org/sequence-diagrams.html. |
skinparam SequenceActivationBackgroundColor #FFFFFF + SequenceActivationBorderColor #000000 | Activation bar (execution specification) is a thin white rectangle with black border, per the uml-diagrams.org definition: "Execution is represented as a thin grey or white rectangle on the lifeline". |
skinparam ArrowColor #000000 + ArrowThickness 0.75 | All arrows are thin black — matches Visio stencil hair-line strokes. |
NEVER apply colored themes (!theme blueprint, !theme cerulean, etc.), custom colors,
gradients, shadows, or decorative styling — doing so breaks compliance with the
uml-diagrams.org reference style. If a user explicitly and unambiguously requests colour,
add it on top of this preamble rather than removing the preamble.
Since PlantUML 1.2019.9 the project officially recommends the CSS-like <style> block
(plantuml.com/style-evolution) as the preferred
styling mechanism — "skinparam is being phased out … users should migrate to style".
This skill ships a second, visually equivalent preamble based on <style>. Both
preambles produce the same uml-diagrams.org reference look; choose one according to the
PlantUML version available at render time:
Use the skinparam preamble (default) when… | Use the <style> preamble (alternative) when… |
|---|---|
| You need maximum backward compatibility (PlantUML < 1.2019.9) | You are on a modern PlantUML version and want forward-looking syntax |
You want a single flat block of skinparam lines that's easy to grep | You want CSS-style nested scoping (sequenceDiagram { lifeLine { … } }) |
You need fine-grained per-element-type *BackgroundColor knobs | You want fewer lines and per-diagram-type cascading rules |
Do NOT mix both inside the same .puml file. Pick one preamble per diagram.
@startuml
<style>
root {
FontName Helvetica
FontSize 12
FontColor #000000
BackGroundColor #FFFFFF
LineColor #000000
LineThickness 0.75
RoundCorner 0
Shadowing 0
}
title {
FontSize 14
FontStyle bold
FontColor #000000
BackGroundColor transparent
LineColor transparent
LineThickness 0
}
note {
BackGroundColor #FFFFFF
LineColor #000000
FontColor #000000
}
sequenceDiagram {
actor { BackGroundColor #FFFFFF; LineColor #000000; FontColor #000000 }
participant { BackGroundColor #FFFFFF; LineColor #000000; FontColor #000000 }
lifeLine { BackGroundColor #FFFFFF; LineColor #000000; LineStyle 5-5; LineThickness 0.75 }
reference { BackGroundColor #FFFFFF; LineColor #000000 }
group { BackGroundColor #FFFFFF; LineColor #000000 }
arrow { LineColor #000000; LineThickness 0.75; FontColor #000000 }
}
classDiagram {
class { BackGroundColor #FFFFFF; LineColor #000000; FontColor #000000 }
arrow { LineColor #000000; LineThickness 0.75 }
}
activityDiagram {
activity { BackGroundColor #FFFFFF; LineColor #000000; FontColor #000000; RoundCorner 10 }
arrow { LineColor #000000; LineThickness 0.75 }
diamond { BackGroundColor #FFFFFF; LineColor #000000 }
}
useCaseDiagram {
actor { BackGroundColor #FFFFFF; LineColor #000000 }
usecase { BackGroundColor #FFFFFF; LineColor #000000 }
rectangle { BackGroundColor #FFFFFF; LineColor #000000 }
}
componentDiagram {
component { BackGroundColor #FFFFFF; LineColor #000000 }
package { BackGroundColor #FFFFFF; LineColor #000000 }
}
stateDiagram {
state { BackGroundColor #FFFFFF; LineColor #000000; FontColor #000000 }
arrow { LineColor #000000 }
}
</style>
' Two settings still have NO CSS equivalent yet — keep them as skinparams:
skinparam style strictuml
skinparam classAttributeIconSize 0
Notes on the CSS preamble:
LineStyle 5-5 is the CSS equivalent of skinparam *LineStyle dashed — gives the
uml-diagrams.org dashed lifeline.Shadowing 0 replaces skinparam shadowing false.RoundCorner 0 at root keeps every rectangle square; activityDiagram.activity
overrides it to 10 for the round-cornered action shape used on uml-diagrams.org.strictuml (removes circle stereotype icons) and classAttributeIconSize 0 (removes
attribute visibility dots) have no CSS equivalent yet as of PlantUML 1.2026.x —
keep them as skinparam lines beside the <style> block. This is the only place where
the two systems must coexist.examples/07_sequence_oauth2_css_style.puml.
All other example files keep the skinparam preamble for backward compatibility.If the PlantUML server returns an error:
.puml file@startuml / @enduml are properly paired@startmindmap for mind maps)docker pull plantuml/plantuml:latest && bash generate-plantuml.sh ...After successful generation:
.puml and the rendered image