
Adr Graph Easy Architect
- 119 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
Use adr-graph-easy-architect for development tasks
About
adr-graph-easy-architect: A skill for development. This provides functionality for development workflows.
- adr-graph-easy-architect
Adr Graph Easy Architect by the numbers
- 119 all-time installs (skills.sh)
- Ranked #2,847 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill adr-graph-easy-architectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 119 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
What it does
Use adr-graph-easy-architect for development tasks
Files
ADR Graph-Easy Architect
Create comprehensive ASCII architecture diagrams for Architecture Decision Records (ADRs) using graph-easy. Pure text output with automatic layout - no image rendering required.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
When to Use This Skill
- Writing new ADR that involves architectural changes
- ADR describes migration, integration, or system changes
- User asks for visual representation of a decision
- Existing ADR diagram needs review or update
Preflight Check
Ensure graph-easy is installed and functional before rendering diagrams.
Full setup instructions: Preflight Setup
Quick verify:
echo "[Test] -> [OK]" | graph-easy --as=boxart &>/dev/null && echo "✓ graph-easy ready"---
DSL Quick Reference
Full syntax with examples, node styling, edge styles, and emoji rules: DSL Syntax Reference
Essential Syntax
[Node] # Node
[A] -> [B] # Edge
[A] -- label --> [B] # Labeled edge
[A] <-> [B] # Bidirectional
( Group: [Node A] [Node B] ) # Group/container
[id] { label: "Display"; } # Custom labelFlow Direction (MANDATORY)
graph { flow: south; } # Top-to-bottom (architecture, decisions)
graph { flow: east; } # Left-to-right (pipelines, sequences)Graph Label (MANDATORY: EVERY diagram MUST have emoji + title)
WARNING: This is the most commonly forgotten requirement. Diagrams without labels are invalid.
Correct:
graph { label: "🔄 Database Migration"; flow: south; }
[Old DB] -> [New DB]Anti-Pattern (INVALID):
graph { flow: south; }
[Old DB] -> [New DB]Missing label: with emoji. The preflight validator will BLOCK any ADR containing diagrams without graph { label: "emoji ..."; }.
Emoji Selection (for graph labels ONLY - never inside nodes)
| Diagram Type | Emoji | Diagram Type | Emoji |
|---|---|---|---|
| Migration/Change | 🔄 | Architecture | 🏗️ |
| Deployment/Release | 🚀 | Network/API | 🌐 |
| Data Flow | 📊 | Storage/Database | 💾 |
| Security/Auth | 🔐 | Monitoring | 📡 |
| Error/Failure | ⚠️ | Hook/Event | 🪝 |
| Decision/Branch | 🔀 | Before/After | ⏮️/⏭️ |
Node & Edge Styling Summary
| Style | Syntax | Use For |
|---|---|---|
| Rounded corners | { shape: rounded; } | Start/end nodes |
| Double border | { border: double; } | Critical/emphasis |
| Bold border | { border: bold; } | Important nodes |
| Dotted border | { border: dotted; } | Optional/skippable |
| Solid arrow | -> | Main/happy path |
| Dotted arrow | ..> | Conditional/alternate |
| Bold arrow | ==> | Emphasized/critical |
| Labeled edge | -- label --> | Annotated connections |
Character Safety
- Graphical emojis INSIDE nodes: NEVER (breaks box alignment)
- Unicode symbols inside nodes (checkmark, cross, warning): OK (single-width)
- ASCII markers inside nodes ([x] [+] [!]): ALWAYS safe
- Graphical emojis in
graph { label: }: OK
Full symbol reference: Monospace-Safe Symbols
---
Common Diagram Patterns
Migration (Before -> After)
graph { flow: south; }
[Before] -- migrate --> [After]Multi-Component System
graph { flow: south; }
[A] -> [B] -> [C]
[B] -> [D]Pipeline (Left-to-Right)
graph { flow: east; }
[Input] -> [Process] -> [Output]Decision with Options
graph { flow: south; }
[Decision] -> [Option A]
[Decision] -> [Option B]Grouped Components
( Group:
[Component 1]
[Component 2]
)
[External] -> [Component 1]Bidirectional Flow
[Client] <-> [Server]
[Server] -> [Database]More patterns by ADR type: Diagram Examples
---
Rendering
Command (MANDATORY: Always use boxart)
graph-easy --as=boxart << 'EOF'
graph { flow: south; }
[A] -> [B] -> [C]
EOFNever use --as=ascii - it produces ugly +--+ boxes instead of clean ┌──┐ lines.
Validation Workflow
# 1. Write DSL to heredoc
# 2. Render with boxart
# 3. Review output
# 4. Iterate if needed
# 5. Copy final ASCII to ADR---
Embedding in ADR
Every rendered diagram MUST include a collapsible <details> block with graph-easy source. Full format guide and GFM syntax rules: ADR Embedding Guide
Required format:
````markdown
┌───────┐ ┌──────┐
│ Build │ --> │ Test │
└───────┘ └──────┘<details> <summary>graph-easy source</summary>
graph { label: "🚀 Pipeline"; flow: east; }
[Build] -> [Test]</details> ````
The `<details>` block is MANDATORY - never embed a diagram without its source.
---
Mandatory Checklist (Before Rendering)
Graph-Level (MUST have)
- [ ] `graph { label: "🚀 Title"; }` - semantic emoji + title (MOST FORGOTTEN - check first!)
- [ ]
graph { flow: south; }orgraph { flow: east; }- explicit direction - [ ] Command uses
--as=boxart- NEVER--as=ascii
Embedding (MUST have - non-negotiable)
- [ ] `<details>` block with source - EVERY diagram MUST have collapsible source code block
- [ ] Format: rendered diagram in
`block, followed by<details><summary>graph-easy source</summary>with source - [ ] Never commit a diagram without its reproducible source
Node Styling (Visual hierarchy)
- [ ] Start/end nodes:
{ shape: rounded; }- entry/exit points - [ ] Critical/important nodes:
{ border: double; }or{ border: bold; } - [ ] Optional/skippable nodes:
{ border: dotted; } - [ ] Long labels use
\nfor multiline - max ~15 chars per line
Edge Styling (Semantic meaning)
- [ ] Main/happy path:
->solid arrow - [ ] Conditional/alternate:
..>dotted arrow - [ ] Emphasized/critical:
==>bold arrow - [ ] Edge labels are SHORT (1-3 words):
-- YES -->,-- error -->
Character Safety (Alignment)
- [ ] NO graphical emojis inside nodes (break alignment)
- [ ] Unicode symbols OK inside nodes (single-width)
- [ ] ASCII markers ALWAYS safe ([x] [+] [!] [OK])
- [ ] Graphical emojis ONLY in
graph { label: "..."; }title
Structure (Organization)
- [ ] Groups
( Name: ... )used for logical clustering when 4+ related nodes - [ ] Node IDs short, labels descriptive:
[db] { label: "PostgreSQL"; } - [ ] No more than 7-10 nodes per diagram (split if larger)
Success Criteria
Correctness
1. Parses without error - graph-easy accepts the DSL 2. Renders cleanly - no misaligned boxes or broken lines 3. Matches content - all key elements from description represented 4. Source preserved (MANDATORY) - EVERY diagram has <details> block with source
Aesthetics
1. Uses boxart - clean Unicode lines, not ASCII +--+ 2. Visual hierarchy - start/end rounded, important bold/double, optional dotted 3. Consistent styling - same border style = same semantic meaning throughout 4. Readable labels - multiline with \n, no truncation 5. Clear flow - direction matches natural reading (top-down or left-right)
Comprehensiveness
1. Semantic emoji in title - emoji chosen to match diagram purpose 2. Legend if needed - multiline title with \n for complex diagrams 3. Edge semantics - solid=normal, dotted=conditional, bold=critical 4. Logical grouping - related nodes in ( Group: ... ) containers
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
command not found | graph-easy not installed | Run preflight check |
| Misaligned boxes | Used --as=ascii | Always use --as=boxart |
| Box border broken | Graphical emoji in node | Remove emojis from nodes, use ASCII markers |
| Nodes overlap | Too complex | Split into multiple diagrams (max 7-10 nodes) |
| Edge labels cut off | Label too long | Shorten to 1-3 words |
| No title showing | Wrong syntax | Use graph { label: "Title"; flow: south; } |
| Weird layout | No flow direction | Add graph { flow: south; } or flow: east |
| Parse error | Special chars in node | Escape or simplify node names |
Resources
Post-Execution Reflection
After this skill completes, check before closing:
1. Did the command succeed? — If not, fix the instruction or error table that caused the failure. 2. Did parameters or output change? — If the underlying tool's interface drifted, update Usage examples and Parameters table to match. 3. Was a workaround needed? — If you had to improvise (different flags, extra steps), update this SKILL.md so the next invocation doesn't need the same workaround.
Only update if the issue is real and reproducible — not speculative.
Embedding Diagrams in ADRs
Markdown Format (MANDATORY: Always Include Source)
CRITICAL: Every rendered diagram MUST be followed by a collapsible <details> block containing the graph-easy source code. This is non-negotiable for:
- Reproducibility: Future maintainers can regenerate the diagram
- Editability: Source can be modified and re-rendered
- Auditability: Changes to diagrams are trackable in git diffs
````markdown
Architecture
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Before │ ──> │ After │ ──> │ Database │
└──────────┘ └──────────┘ └──────────┘<details> <summary>graph-easy source</summary>
graph { flow: east; }
[Before] -> [After] -> [Database]</details> ````
The `<details>` block is MANDATORY - never embed a diagram without its source.
GFM Collapsible Section Syntax
GitHub Flavored Markdown supports HTML <details> and <summary> tags for collapsible sections. Key syntax rules:
Structure:
<details>
<summary>Click to expand</summary>
<!-- BLANK LINE REQUIRED HERE -->
Content goes here (Markdown supported)
<!-- BLANK LINE REQUIRED HERE -->
</details>Critical rules:
1. Blank lines required - Must have empty line after <summary> and before </details> for Markdown to render 2. No indentation - <details> and <summary> must be at column 0 (no leading spaces) 3. Summary is clickable label - Text in <summary> appears as the collapsed header 4. Markdown inside works - Code blocks, headers, lists all render correctly inside
Optional: Default expanded:
<details open>
<summary>Expanded by default</summary>
Content visible on page load
</details>Common mistake (Markdown won't render):
<details>
<summary>Broken</summary>
No blank line - this won't render as Markdown!
</details>References:
File Organization
No separate asset files needed - diagram is inline in the markdown.
Regeneration
If ADR changes, regenerate by running the source through graph-easy again:
# Extract source from <details> block, pipe through graph-easy
graph-easy --as=boxart << 'EOF'
# paste source here
EOFDiagram Examples by ADR Type
This reference provides diagram patterns for different ADR types. Every ADR requires two diagrams:
1. Before/After — Shows state change (Context section) 2. Architecture — Shows component relationships (Architecture section)
Feature ADR
Before/After Diagram
Shows what capability is being added:
graph { flow: east; }
[ Before ] { label: "Manual Process\n(No Automation)"; }
[ After ] { label: "Automated Pipeline\n(CI/CD)"; }
[ Before ] --> [ After ]Architecture Diagram
Shows new components and integrations:
graph { flow: south; }
[ User ] -> [ API Gateway ]
[ API Gateway ] -> [ New Service ]
[ New Service ] -> [ Database ]
[ New Service ] -> [ External API ]Bug Fix ADR
Before/After Diagram
Shows incorrect vs correct behavior:
graph { flow: east; }
[ Before ] { label: "Race Condition\n(Data Loss)"; border: bold; }
[ After ] { label: "Mutex Lock\n(Data Safe)"; }
[ Before ] --> [ After ]Architecture Diagram
Shows where the fix was applied:
graph { flow: south; }
[ Request Handler ] -> [ Mutex ] { label: "NEW"; }
[ Mutex ] -> [ Shared State ]Refactor ADR
Before/After Diagram
Shows structural change:
graph { flow: east; }
[ Before ] { label: "Monolith\n(Single Service)"; }
[ After ] { label: "Microservices\n(3 Services)"; }
[ Before ] --> [ After ]Architecture Diagram
Shows new structure:
graph { flow: south; }
[ API Gateway ] -> [ Auth Service ]
[ API Gateway ] -> [ User Service ]
[ API Gateway ] -> [ Data Service ]
[ Auth Service ] -> [ Shared DB ]
[ User Service ] -> [ Shared DB ]
[ Data Service ] -> [ Shared DB ]Documentation ADR
Before/After Diagram
Shows documentation coverage change:
graph { flow: east; }
[ Before ] { label: "Scattered Docs\n(README only)"; }
[ After ] { label: "Structured Docs\n(ADR + Specs)"; }
[ Before ] --> [ After ]Architecture Diagram
Shows documentation structure:
graph { flow: south; }
[ docs/ ] -> [ adr/ ]
[ docs/ ] -> [ design/ ]
[ docs/ ] -> [ api/ ]
[ adr/ ] -> [ YYYY-MM-DD-slug.md ]
[ design/ ] -> [ YYYY-MM-DD-slug/spec.md ]Performance ADR
Before/After Diagram
Shows performance improvement:
graph { flow: east; }
[ Before ] { label: "500ms Response\n(No Cache)"; border: bold; }
[ After ] { label: "50ms Response\n(Redis Cache)"; }
[ Before ] --> [ After ]Architecture Diagram
Shows caching layer:
graph { flow: east; }
[ Client ] -> [ API ]
[ API ] -> [ Redis Cache ] { label: "check"; }
[ Redis Cache ] -> [ Database ] { label: "miss"; }
[ Redis Cache ] -> [ API ] { label: "hit"; }Tips for Effective Diagrams
1. Keep it simple — 3-6 nodes maximum per diagram 2. Use labels — Annotate edges and nodes with context 3. Show contrast — Before/After should have clear visual difference 4. Be specific — Use actual component names, not generic boxes 5. Flow direction — Use east for before/after, south for architecture
Graph-Easy DSL Syntax Reference
Basic Elements
# Nodes (square brackets)
[Node Name]
# Edges (arrows)
[A] -> [B]
# Labeled edges
[A] -- label --> [B]
# Bidirectional
[A] <-> [B]
# Chain
[A] -> [B] -> [C]Groups (Containers)
# Named group with dashed border
( Group Name:
[Node A]
[Node B]
)
# Nested connections
( Before:
[Old System]
)
( After:
[New System]
)
[Before] -> [After]Node Labels
# Custom label (different from ID)
[db] { label: "PostgreSQL Database"; }
# ASCII markers for visual distinction INSIDE boxes
# (emojis break box alignment - use ASCII markers instead)
[deleted] { label: "[x] Old Component"; }
[added] { label: "[+] New Component"; }
[warning] { label: "[!] Deprecated"; }
[success] { label: "[OK] Passed"; }Character rules for nodes:
- Graphical emojis (rocket, lightbulb, checkmark, cross) - NEVER (double-width breaks box alignment)
- Unicode symbols (checkmark, cross, warning, arrows) - OK (single-width, safe)
- ASCII markers ([x] [+] [!] :) ) - ALWAYS safe (monospace)
Use graph { label: "..."; } for graphical emojis in title/legend.
Example: Emoji breaks alignment (DON'T DO THIS)
# BAD - emoji inside node
[rocket] { label: "🚀 Launch"; }Renders broken:
┌────────────┐
│ 🚀 Launch │ <-- box edge misaligned due to double-width emoji
└────────────┘Example: ASCII marker preserves alignment (DO THIS)
# GOOD - ASCII marker inside node
[rocket] { label: "[>] Launch"; }Renders correctly:
┌────────────┐
│ [>] Launch │
└────────────┘Example: Emoji safe in graph title (OK)
# OK - emoji in graph label (outside boxes)
graph { label: "🚀 Deployment Pipeline"; flow: east; }
[Build] -> [Test] -> [Deploy]Renders correctly (emoji in title, not in boxes):
🚀 Deployment Pipeline
┌───────┐ ┌──────┐ ┌────────┐
│ Build │ --> │ Test │ --> │ Deploy │
└───────┘ └──────┘ └────────┘Flow Direction (MANDATORY: Always specify)
# MANDATORY: Always specify flow direction explicitly
graph { flow: south; } # Top-to-bottom (architecture, decisions)
graph { flow: east; } # Left-to-right (pipelines, sequences)Never rely on default flow - explicit is clearer.
Graph Title and Legend (Outside Boxes - Emojis Safe Here)
Emojis break alignment INSIDE boxes but are SAFE in graph titles/legends.
Emoji Selection Guide - Choose emoji that matches diagram purpose:
| Diagram Type | Emoji | Example Title |
|---|---|---|
| Migration/Change | 🔄 | "🔄 Database Migration" |
| Deployment/Release | 🚀 | "🚀 Deployment Pipeline" |
| Data Flow | 📊 | "📊 Data Ingestion Flow" |
| Security/Auth | 🔐 | "🔐 Authentication Flow" |
| Error/Failure | ⚠️ | "⚠️ Error Handling" |
| Decision/Branch | 🔀 | "🔀 Routing Decision" |
| Architecture | 🏗️ | "🏗️ System Architecture" |
| Network/API | 🌐 | "🌐 API Integration" |
| Storage/Database | 💾 | "💾 Storage Layer" |
| Monitoring/Observability | 📡 | "📡 Monitoring Stack" |
| Hook/Event | 🪝 | "🪝 Hook Flow" |
| Before/After comparison | ⏮️/⏭️ | "⏮️ Before" / "⏭️ After" |
# Title with semantic emoji
graph { label: "🚀 Deployment Pipeline"; flow: east; }
# Title with legend (multiline using \n)
graph { label: "🪝 Hook Flow\n──────────\n✓ Allow ✗ Deny ⚠ Warn"; flow: south; }Rendered:
Hook Flow
──────────
✓ Allow ✗ Deny ⚠ Warn
╭───────╮
│ Start │
╰───────╯Rule: Emojis ONLY in graph { label: "..."; } - NEVER inside [ node ]
Node Styling (Best Practices)
# Rounded corners for start/end nodes
[ Start ] { shape: rounded; }
[ End ] { shape: rounded; }
# Double border for emphasis
[ Critical Step ] { border: double; }
# Bold border for important nodes
[ Key Decision ] { border: bold; }
# Dotted border for optional/skippable
[ Optional ] { border: dotted; }
# Multiline labels with \n
[ Hook Input\n(stdin JSON) ]Rendered examples:
╭─────────╮ ┌─────────┐
│ Rounded │ │ Default │
╰─────────╯ └─────────┘
╔═════════╗ ┏━━━━━━━━━┓
║ Double ║ ┃ Bold ┃
╚═════════╝ ┗━━━━━━━━━┛Note: Dotted borders ({ border: dotted; }) use⋮characters that render inconsistently on GitHub. Use sparingly.
Edge Styles
[ A ] -> [ B ] # Solid arrow (default)
[ A ] ..> [ B ] # Dotted arrow
[ A ] ==> [ B ] # Bold/double arrow
[ A ] - -> [ B ] # Dashed arrow
[ A ] -- label --> [ B ] # Labeled edgeEvolution Log
Convention: Reverse chronological order (newest on top, oldest at bottom). Prepend new entries.
---
2026-02-26: Initial Evolution Log
Status: Skill is in use and maintained. Track improvements here.
Purpose
This evolution log tracks updates to the skill. Each entry should note:
- What changed (content, structure, tooling)
- Why it changed (bug fix, feature request, best practice)
- Files affected
How to Use
1. When updating SKILL.md or references, add an entry here with the date 2. Keep entries reverse-chronological (newest first) 3. Link to ADRs or GitHub issues when relevant 4. Reference specific line changes when helpful
---
Monospace-Safe Symbols Reference
Avoid emojis - they have variable width and break box alignment on GitHub.
Status Markers
| Meaning | Marker |
|---|---|
| Added/New | [+] |
| Removed/Deleted | [x] |
| Changed/Updated | [*] |
| Warning/Deprecated | [!] |
| Deferred/Pending | [~] |
| Current/Active | [>] |
| Optional | [?] |
| Locked/Fixed | [=] |
Box Drawing (U+2500-257F)
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ (light)
═ ║ ╔ ╗ ╚ ╝ ╠ ╣ ╦ ╩ ╬ (double)Arrows & Pointers
→ ← ↑ ↓ (arrows)
∨ ∧ (logic - graph-easy uses these)
< > ^ v (ASCII arrows)Shapes & Bullets
• ○ ● (bullets)
□ ■ (squares)
◇ ◆ (diamonds)Math & Logic
× ÷ ± ≠ ≤ ≥ ∞ (math)
∧ ∨ ¬ (logic)Preflight Setup
Run these checks in order. Each layer depends on the previous.
Layer 1: Package Manager
/usr/bin/env bash << 'SETUP_EOF'
# Detect OS and set package manager
case "$(uname -s)" in
Darwin) PM="brew" ;;
Linux) PM="apt" ;;
*) echo "ERROR: Unsupported OS (require macOS or Linux)"; exit 1 ;;
esac
command -v $PM &>/dev/null || { echo "ERROR: $PM not installed"; exit 1; }
echo "✓ Package manager: $PM"
SETUP_EOFLayer 2: Perl + cpanminus (mise-first approach)
# Prefer mise for unified tool management
if command -v mise &>/dev/null; then
# Install Perl via mise
mise which perl &>/dev/null || mise install perl
# Install cpanminus under mise perl
mise exec perl -- cpanm --version &>/dev/null 2>&1 || {
echo "Installing cpanminus under mise perl..."
mise exec perl -- curl -L https://cpanmin.us | mise exec perl -- perl - App::cpanminus
}
echo "✓ cpanminus installed (via mise perl)"
else
# Fallback: Install cpanminus via system package manager
command -v cpanm &>/dev/null || {
echo "Installing cpanminus via $PM..."
case "$PM" in
brew) brew install cpanminus ;;
apt) sudo apt install -y cpanminus ;;
esac
}
echo "✓ cpanminus installed"
fiLayer 3: Graph::Easy Perl module
# Check if Graph::Easy is installed (mise-first)
if command -v mise &>/dev/null; then
mise exec perl -- perl -MGraph::Easy -e1 2>/dev/null || {
echo "Installing Graph::Easy via mise perl cpanm..."
mise exec perl -- cpanm Graph::Easy
}
echo "✓ Graph::Easy installed (via mise perl)"
else
perl -MGraph::Easy -e1 2>/dev/null || {
echo "Installing Graph::Easy via cpanm..."
cpanm Graph::Easy
}
echo "✓ Graph::Easy installed"
fiLayer 4: Verify graph-easy is in PATH
# Verify graph-easy is accessible and functional
command -v graph-easy &>/dev/null || {
echo "ERROR: graph-easy not found in PATH"
exit 1
}
# Test actual functionality (--version exits with code 2, unreliable)
echo "[Test] -> [OK]" | graph-easy &>/dev/null && echo "✓ graph-easy ready"All-in-One Preflight Script
/usr/bin/env bash << 'PREFLIGHT_EOF'
# Copy-paste this entire block to ensure graph-easy is ready (macOS + Linux)
# Prefers mise for unified cross-platform tool management
# Check for mise first (recommended)
if command -v mise &>/dev/null; then
echo "Using mise for Perl management..."
mise which perl &>/dev/null || mise install perl
mise exec perl -- cpanm --version &>/dev/null 2>&1 || \
mise exec perl -- curl -L https://cpanmin.us | mise exec perl -- perl - App::cpanminus
mise exec perl -- perl -MGraph::Easy -e1 2>/dev/null || mise exec perl -- cpanm Graph::Easy
else
# Fallback: system package manager
echo "💡 Tip: Install mise for unified tool management: curl https://mise.run | sh"
case "$(uname -s)" in
Darwin) PM="brew" ;;
Linux) PM="apt" ;;
*) echo "ERROR: Unsupported OS"; exit 1 ;;
esac
command -v $PM &>/dev/null || { echo "ERROR: $PM not installed"; exit 1; }
command -v cpanm &>/dev/null || { [ "$PM" = "apt" ] && sudo apt install -y cpanminus || brew install cpanminus; }
perl -MGraph::Easy -e1 2>/dev/null || cpanm Graph::Easy
fi
# Verify graph-easy is in PATH and functional
command -v graph-easy &>/dev/null || {
echo "ERROR: graph-easy not in PATH after installation"
exit 1
}
# Test actual functionality (--version exits with code 2, unreliable)
echo "[Test] -> [OK]" | graph-easy &>/dev/null && echo "✓ graph-easy ready"
PREFLIGHT_EOF