Agent skill
c4-diagrams
Creates and manages C4 architecture diagrams using PlantUML. Use when the user wants to visualize software architecture, create context/container/component/sequence diagrams, document system design with the C4 model, or mentions architecture diagrams, system design, or PlantUML. Supports iterative diagram building through conversational workflow.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/c4-diagrams
SKILL.md
C4 Architecture Diagrams
This skill helps you create and manage C4 architecture diagrams using the PlantUML format. C4 diagrams provide a hierarchical way to visualize software architecture at different levels of detail, from high-level system context down to low-level components.
The C4 model uses four diagram types:
- Context: Shows the system in its environment with external actors and systems
- Container: Zooms into the system to show high-level technical building blocks
- Component: Zooms into a container to show its internal structure
- Sequence: Shows how elements interact with each other over time
All diagrams are stored as .puml files in doc/diagrams/ and rendered to PNG images using the public PlantUML server.
Requirements
Before using this skill, ensure you have:
- Bash - For directory setup (available on Linux, macOS, WSL)
- Python 3.6+ - For diagram rendering (uses standard library only, no pip install needed)
- Internet access - To reach the public PlantUML server (https://www.plantuml.com/plantuml/)
- File system write permissions - In your project's working directory
Note: This skill uses only standard library dependencies. No package managers or external installations required beyond Python itself.
🚀 High-Level Workflow
Creating C4 diagrams follows a five-phase workflow:
- Initialize Directory Structure - Set up
doc/diagrams/with subdirectories for each diagram type - Choose Diagram Type & Create File - Select appropriate diagram type and initialize from template
- Add Elements - Define the entities in your diagram (people, systems, containers, components)
- Define Relationships - Connect elements with labeled relationships
- Render Diagram - Generate PNG image from PlantUML source
Each phase includes validation steps to ensure correctness before proceeding to the next phase.
Phase 1: Initialize Directory Structure
1.1 Check for Existing Structure
Before creating diagrams, verify that the directory structure exists:
Use the Bash tool to check:
ls -la doc/diagrams 2>/dev/null
If the output shows subdirectories context/, container/, component/, and sequence/, proceed to Phase 2.
1.2 Create Directory Structure
If the structure doesn't exist, run the initialization script:
bash .claude/skills/c4-diagrams/scripts/init-structure.sh
Expected behavior:
- Creates
doc/diagrams/at project root if missing - Creates four subdirectories:
doc/diagrams/context/- For context-level diagramsdoc/diagrams/container/- For container-level diagramsdoc/diagrams/component/- For component-level diagramsdoc/diagrams/sequence/- For sequence diagrams
- Reports what was created or verified
- Idempotent: safe to run multiple times
1.3 Verify Success
After running the script, confirm the structure was created:
ls -R doc/diagrams
You should see all four subdirectories.
Error handling:
- If the script fails with a permission error, ensure you have write permissions in the project directory
- If you're in the wrong directory, navigate to the project root first
- The script will provide specific error messages to guide troubleshooting
Phase 2: Choose Diagram Type & Create File
2.1 Understand Diagram Types
Choose the appropriate diagram type based on what you want to visualize:
Context Diagrams (context/)
- Purpose: Show the system in its environment
- Elements: People, systems, external systems
- Use when: Explaining what the system does and who uses it
- Audience: Everyone (technical and non-technical)
Container Diagrams (container/)
- Purpose: Show high-level technical building blocks
- Elements: Web apps, mobile apps, databases, microservices
- Use when: Explaining the system's runtime architecture
- Audience: Technical stakeholders (developers, architects)
Component Diagrams (component/)
- Purpose: Show components within a container
- Elements: Controllers, services, repositories, modules
- Use when: Explaining internal structure of a specific container
- Audience: Developers working on the system
Sequence Diagrams (sequence/)
- Purpose: Show interactions between elements over time
- Elements: Any of the above, with time-ordered relationships
- Use when: Explaining workflows, processes, or API call chains
- Audience: Developers and architects
- ⚠️ Important constraints:
- ❌ NO boundaries - Container_Boundary, System_Boundary are not supported
- ❌ NO _Ext suffixes - Use Container(), not Container_Ext()
- ✅ Participants must be in a flat list (no nesting or grouping structures)
- ✅ Relationships are time-ordered from top to bottom
For detailed guidance on when to use each type, see Diagram Types Guide.
2.2 Check if Diagram Already Exists
Before creating a new diagram, check if it already exists:
Determine the diagram name (convert to lowercase, replace spaces with hyphens):
- User says: "Create a system context diagram" → name:
system-context - User says: "Web application container diagram" → name:
web-application
Check for existing file:
ls doc/diagrams/{type}/{name}.puml 2>/dev/null
If the file exists:
- Read the file using the Read tool to understand its current state
- Skip to Phase 3 or Phase 4 to modify it
If the file doesn't exist:
- Continue to create a new diagram
2.3 Initialize New Diagram from Template
To create a new diagram, read the appropriate template and write it to the target location:
-
Read the template:
Read .claude/skills/c4-diagrams/templates/{type}.pumlWhere
{type}is one of:context,container,component,sequence -
Optionally customize the template:
- Replace title placeholder with user-specified title
- Add initial comments or notes
- Keep all C4-PlantUML directives intact
-
Write to target location:
Write doc/diagrams/{type}/{name}.puml
Validation:
- Verify the file was created:
ls doc/diagrams/{type}/{name}.puml - Briefly read the file to confirm contents
- Proceed to Phase 3
Phase 3: Add Elements
3.1 Parse Current Diagram State
Before adding elements, read the diagram file to understand what's already there:
Read doc/diagrams/{type}/{name}.puml
Identify:
- Existing elements (Person, System, Container, Component)
- Any boundaries or groupings
- Current layout and organization
3.2 Determine Elements to Add
Based on the user's request, identify what elements need to be added:
Common element types by diagram:
Context diagrams:
Person(id, "Name", "Description")- Users and actorsSystem(id, "Name", "Description")- Your systemSystem_Ext(id, "Name", "Description")- External systems
Container diagrams:
Container(id, "Name", "Technology", "Description")- Apps, services, databasesContainerDb(id, "Name", "Technology", "Description")- Databases specificallyContainerQueue(id, "Name", "Technology", "Description")- Message queues
Component diagrams:
Component(id, "Name", "Technology", "Description")- Components within a containerComponentDb(id, "Name", "Technology", "Description")- Database componentsComponentQueue(id, "Name", "Technology", "Description")- Queue components
Sequence diagrams:
- Use the same element types as above (Person, Container, Component, etc.)
- ⚠️ CRITICAL: Do NOT use boundaries (System_Boundary, Container_Boundary) - sequence diagrams require a flat participant list
- ⚠️ CRITICAL: Do NOT use _Ext suffixes (System_Ext, Container_Ext, ContainerDb_Ext) - use regular variants instead
- Example: Use
Container(cache, "Cache", "Redis", "Desc")notContainer_Ext(...)
Boundaries (Context/Container/Component diagrams only - NOT sequence):
System_Boundary(id, "Name", "Optional Description") {
// Elements inside the boundary (indented with 2 spaces)
}
For complete syntax reference, see Syntax Reference.
3.3 Add Element Definitions
To add elements, use the Edit tool to insert element definitions at the appropriate location:
Important syntax rules:
- IDs must be valid identifiers: Use letters, numbers, underscores only
- Sanitize IDs: Replace hyphens and special characters with underscores
- Example: "web-app" → "web_app"
- Example: "API Gateway" → "API_Gateway"
- Technology parameter: Required for Container and Component elements (3rd parameter)
- Quote all strings: Names, technologies, and descriptions must be in quotes
Example additions:
For a context diagram:
Person(user, "User", "A customer using the system")
System(main_system, "Main System", "The core application")
System_Ext(payment_gateway, "Payment Gateway", "External payment processor")
For a container diagram:
Container(web_app, "Web Application", "React", "Provides UI for users")
ContainerDb(database, "Database", "PostgreSQL", "Stores application data")
Container(api, "API Server", "Node.js/Express", "Handles business logic")
3.4 Validate Element Additions
After adding elements, verify correctness:
- Read the edited file to confirm changes
- Check for syntax errors:
- Unclosed parentheses
- Missing quotes
- Invalid IDs (hyphens, spaces, special characters)
- Missing technology parameter for containers/components
- Ensure all elements have proper types, names, and descriptions
- Fix any errors before proceeding to Phase 4
Phase 4: Define Relationships
4.1 Parse Existing Elements and Relationships
Before adding relationships, read the diagram to identify:
- All defined elements and their IDs
- Existing relationships (to avoid duplicates)
- Logical connections that need to be added
4.2 Determine Relationships to Add
Based on the user's request and diagram logic, identify which elements should be connected:
Relationship syntax:
Rel(source_id, target_id, "Description")
Rel(source_id, target_id, "Description", "Technology/Protocol")
Directional variants (optional, for layout control):
Rel_U- Relationship pointing upRel_D- Relationship pointing downRel_L- Relationship pointing leftRel_R- Relationship pointing right
Examples:
Rel(user, web_app, "Uses", "HTTPS")
Rel(web_app, api, "Makes API calls", "REST/JSON")
Rel(api, database, "Reads/writes", "JDBC")
Rel(main_system, payment_gateway, "Processes payments", "API")
4.3 Add Relationship Definitions
To add relationships, use the Edit tool to insert them after the element definitions:
Best practices:
- Add relationships in a dedicated section (after all elements)
- Group related relationships together
- Use descriptive labels that explain the interaction
- Include technology/protocol information when relevant
For sequence diagrams:
- Relationships are time-ordered (top to bottom)
- Use dividers to group logical steps:
== Step Name == - Consider using
groupblocks for sub-processes:plantuml== Authentication == group Login Process Rel(user, api, "Submits credentials") Rel(api, database, "Verifies user") end
4.4 Validate Relationships
After adding relationships, verify correctness:
- Confirm both source and target IDs exist in the diagram
- Check that relationship directions make logical sense
- Ensure descriptions are clear and meaningful
- Verify technology/protocol parameters are accurate
- For sequence diagrams, confirm ordering is correct
If validation fails:
- Fix ID mismatches
- Correct syntax errors
- Adjust descriptions for clarity
- Re-read the file to verify fixes
Phase 5: Render Diagram
5.1 Generate PNG from PUML
To render the diagram, run the rendering script:
python3 .claude/skills/c4-diagrams/scripts/render-diagram.py doc/diagrams/{type}/{name}.puml
Example:
python3 .claude/skills/c4-diagrams/scripts/render-diagram.py doc/diagrams/context/system-context.puml
Expected behavior:
- Reads the PUML file
- Encodes content for PlantUML server
- POSTs to https://www.plantuml.com/plantuml/
- Saves PNG response to same directory with same name
- Example:
doc/diagrams/context/system-context.png
5.2 Verify Output
After rendering, confirm the PNG was created:
ls -lh doc/diagrams/{type}/{name}.png
The script includes:
- Retry logic: Attempts up to 3 times with exponential backoff (1s, 2s, 4s delays)
- Timeout handling: 15 second timeout per request
- Clear error messages: Specific errors for network, syntax, and server issues
5.3 Error Handling
If rendering fails, the script will provide specific error messages:
Network errors:
- Connection issues or timeouts
- Check internet connectivity
- Try again after a few moments
HTTP 400 errors:
- Invalid PlantUML syntax in the PUML file
- Read the file and check for syntax errors
- Common issues: unclosed boundaries, missing quotes, invalid IDs
- Manually validate at https://www.plantuml.com/plantuml/uml/
HTTP 429 errors:
- Rate limited by server
- Wait a minute before retrying
- Consider reducing render frequency
HTTP 5xx errors:
- PlantUML server issues
- Try again later
- Server typically recovers quickly
5.4 Next Steps
After successful rendering:
Option 1: Iterate on the diagram
- View the generated PNG
- If changes needed, return to Phase 3 or 4
- Edit elements or relationships
- Re-render (return to Phase 5.1)
Option 2: Create additional diagrams
- Return to Phase 2 to create a new diagram
- Consider creating diagrams at different levels:
- Start with Context (big picture)
- Add Container (technical structure)
- Add Component (internal details)
- Add Sequence (workflows)
Option 3: Explore advanced features
- Load Best Practices Guide for design tips
- Load C4 Model Concepts to understand deeper principles
- Load C4-PlantUML Library Docs for advanced syntax
Common Pitfalls
❌ Don't use hyphens in element IDs → ✅ Do use underscores:
System(web-app, "Web App", "Desc") // WRONG
System(web_app, "Web App", "Desc") // CORRECT
❌ Don't omit technology for containers/components → ✅ Do always include it:
Container(api, "API Server", "Handles logic") // WRONG
Container(api, "API Server", "Node.js", "Handles logic") // CORRECT
❌ Don't forget closing braces → ✅ Do always close boundaries:
System_Boundary(backend, "Backend") {
Container(api, "API", "Node.js", "Server")
// WRONG - missing }
} // CORRECT
❌ Don't reference undefined IDs → ✅ Do ensure all IDs are defined:
Rel(user, app, "Uses") // WRONG if 'user' not defined first
❌ Don't use boundaries in sequence diagrams → ✅ Do use flat participant lists:
' WRONG - sequence diagrams don't support boundaries
Container_Boundary(backend, "Backend") {
Container(api, "API", "Node.js", "Server")
}
' CORRECT - flat list of participants
Container(api, "API", "Node.js", "Server")
❌ Don't use _Ext suffixes in sequence diagrams → ✅ Do use regular variants:
Container_Ext(cache, "Cache", "Redis", "Cache") // WRONG in sequence
Container(cache, "Cache", "Redis", "Cache") // CORRECT
⚠️ Important: Place diagrams in correct subdirectories (doc/diagrams/context/, container/, component/, sequence/)
⚠️ Important: Validate PUML syntax before rendering to avoid errors and server requests
⚠️ Important: Sequence diagrams have unique syntax constraints - see template and syntax reference
Reference Documentation
Load these on-demand for deeper information:
- C4 Model Concepts - Theory, principles, and abstraction levels
- Diagram Types Guide - When to use each type, examples, audience considerations
- Syntax Reference - Complete macro reference, ID rules, boundaries, relationships
- Best Practices - Design patterns, layout, naming, anti-patterns
- C4-PlantUML Library Documentation - Complete upstream docs, advanced features, customization
Didn't find tool you were looking for?