mcpField
G
graphviz-diagrams

graphviz-diagrams

github.com/mindmorassデザイン・UI254 回インストール37 週間前に更新
リポジトリ

graphviz-diagrams について

Graphviz DOT で複雑なグラフを作成するスキルです。精密なレイアウトが必要な構造を可視化し、編集可能なソースとレンダリング画像を併せて出力します。

主な機能

  1. 01DOT による図の作成
  2. 02図の画像へのレンダリング
  3. 03Markdown へのソースと画像の添付
  4. 04複数のレイアウトエンジンの選択
  5. 05一般的なグラフ形式の例の利用

活用シーン

  1. 01複雑な依存関係の可視化
  2. 02呼び出しグラフやコードフローの記録
  3. 03ネットワーク構成や状態機械の図示

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindmorass/reflex --skill graphviz-diagrams

インストール後、Claude Code で/graphviz-diagramsを入力して読み込まれたか確認します。

詳細

Graphviz 図のスキル

目的

Graphviz DOT 言語を使って、ソースコードとレンダリング済み画像の両方を含む複雑なグラフを作成します。

使用する場面

  • 複雑な依存関係グラフ
  • 呼び出しグラフとコードフロー
  • ネットワークトポロジー
  • 階層構造
  • 複雑な遷移を持つ状態機械
  • 正確なレイアウト制御が必要なグラフ全般

出力形式

Graphviz 図には、必ず次のものを含めてください。

  1. インライン DOT ソース - 参照や将来の編集用
  2. レンダリング済み画像 - あらゆる Markdown レンダラーで表示するため
ドキュメント構造
## Diagram: [Name]

### Source
```dot
digraph G {
    A -> B
}
```

### Rendered
![Diagram Name](./attachments/diagram-name.png)

レンダリングのワークフロー

ステップ 1:DOT ソースを記述する
dot_source = """
digraph G {
    rankdir=LR;
    A -> B -> C;
}
"""
ステップ 2:画像にレンダリングする
import subprocess
from pathlib import Path

def render_graphviz(
    dot_source: str,
    output_path: Path,
    format: str = "png",
    engine: str = "dot"
) -> Path:
    """
    Render DOT source to image file.

    Args:
        dot_source: DOT language source code
        output_path: Output file path (without extension)
        format: Output format (png, svg, pdf)
        engine: Layout engine (dot, neato, fdp, circo, twopi, sfdp)

    Returns:
        Path to rendered image
    """
    output_file = output_path.with_suffix(f".{format}")

    result = subprocess.run(
        [engine, f"-T{format}", "-o", str(output_file)],
        input=dot_source,
        text=True,
        capture_output=True
    )

    if result.returncode != 0:
        raise RuntimeError(f"Graphviz error: {result.stderr}")

    return output_file
ステップ 3:Markdown に埋め込む
def create_diagram_markdown(
    name: str,
    dot_source: str,
    image_path: str
) -> str:
    """Create markdown with both source and rendered image."""
    return f"""## Diagram: {name}

### Source
```dot
{dot_source}
レンダリング結果

{name} """


## DOT Language Reference

### Basic Graph Types

#### Directed Graph (digraph)
```dot
digraph G {
    A -> B;
    B -> C;
    A -> C;
}
無向グラフ(graph)
graph G {
    A -- B;
    B -- C;
    A -- C;
}
グラフ属性
digraph G {
    // Graph attributes
    rankdir=LR;           // Direction: TB, BT, LR, RL
    splines=ortho;        // Edge style: line, polyline, curved, ortho, spline
    nodesep=0.5;          // Space between nodes
    ranksep=1.0;          // Space between ranks
    bgcolor="white";      // Background color
    fontname="Helvetica"; // Font for labels

    // Nodes and edges
    A -> B;
}
ノード属性
digraph G {
    // Node defaults
    node [shape=box, style=filled, fillcolor=lightblue];

    // Individual node styling
    A [label="Start", shape=ellipse, fillcolor=green];
    B [label="Process
Data", shape=box];
    C [label="Decision", shape=diamond, fillcolor=yellow];
    D [label="End", shape=ellipse, fillcolor=red];

    A -> B -> C;
    C -> D;
}
よく使われるノード形状
形状用途
boxプロセス、アクション
ellipse開始/終了、終端
diamond判断
circle状態
record構造化データ
Mrecord角丸のレコード
cylinderデータベース
folderディレクトリ/コレクション
componentコンポーネント
note注釈
エッジ属性
digraph G {
    // Edge defaults
    edge [color=gray, fontsize=10];

    A -> B [label="step 1", color=blue, penwidth=2];
    B -> C [label="step 2", style=dashed];
    C -> D [label="step 3", arrowhead=empty];
    D -> A [label="loop", style=dotted, constraint=false];
}
矢印のスタイル
矢印の先端説明
normal塗りつぶされた三角形(デフォルト)
empty中抜きの三角形
dot塗りつぶされた円
odot中抜きの円
diamond塗りつぶされたひし形
none矢印の先端なし
veeV 字型
box塗りつぶされた四角形
サブグラフとクラスター
digraph G {
    // Cluster (named subgraph with cluster_ prefix)
    subgraph cluster_frontend {
        label="Frontend";
        style=filled;
        fillcolor=lightgray;

        UI -> Components -> State;
    }

    subgraph cluster_backend {
        label="Backend";
        style=filled;
        fillcolor=lightyellow;

        API -> Service -> Database;
    }

    // Cross-cluster edges
    State -> API [label="HTTP"];
}
レコード(構造化ノード)
digraph G {
    node [shape=record];

    user [label="User|{id: int|name: string|email: string}"];
    order [label="Order|{id: int|user_id: int|total: decimal}"];

    user -> order [label="1:N"];
}
HTML ラベル
digraph G {
    node [shape=none];

    table [label=<
        <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD BGCOLOR="lightblue"><B>User</B></TD></TR>
            <TR><TD ALIGN="LEFT">id: int</TD></TR>
            <TR><TD ALIGN="LEFT">name: string</TD></TR>
            <TR><TD ALIGN="LEFT">email: string</TD></TR>
        </TABLE>
    >];
}

レイアウトエンジン

エンジン最適な用途説明
dot階層構造有向グラフ、ツリー、DAG
neatoネットワーク無向グラフ、ばねモデル
fdp大規模ネットワーク力学ベースのレイアウト、スケーラブル
sfdp非常に大規模なグラフマルチスケールの力学ベースレイアウト
circo円形円形レイアウト
twopi放射状ルートから放射状に広がるレイアウト
使用方法
# Different engines produce different layouts
dot -Tpng graph.dot -o graph-hierarchical.png
neato -Tpng graph.dot -o graph-spring.png
circo -Tpng graph.dot -o graph-circular.png

よく使われるパターン

依存関係グラフ
digraph Dependencies {
    rankdir=BT;
    node [shape=box, style=filled, fillcolor=lightblue];

    // Packages
    app [label="app"];
    api [label="api"];
    core [label="core"];
    utils [label="utils"];
    db [label="database"];

    // Dependencies (arrows point to dependency)
    app -> api;
    app -> core;
    api -> core;
    api -> db;
    core -> utils;
    db -> utils;
}
状態機械
digraph StateMachine {
    rankdir=LR;
    node [shape=circle];

    // Start state
    start [shape=point, width=0.2];

    // States
    idle [label="Idle"];
    loading [label="Loading"];
    success [label="Success", shape=doublecircle];
    error [label="Error"];

    // Transitions
    start -> idle;
    idle -> loading [label="fetch()"];
    loading -> success [label="200 OK"];
    loading -> error [label="error"];
    error -> idle [label="retry()"];
    success -> idle [label="reset()"];
}
呼び出しグラフ
digraph CallGraph {
    rankdir=TB;
    node [shape=box, fontname="Courier"];

    main [style=filled, fillcolor=lightgreen];
    main -> init;
    main -> process;
    main -> cleanup;

    init -> loadConfig;
    init -> connectDB;

    process -> validateInput;
    process -> transform;
    process -> save;

    transform -> normalize;
    transform -> enrich;

    save -> connectDB [style=dashed, label="reuse"];
}
ネットワークトポロジー
graph Network {
    layout=neato;
    overlap=false;
    node [shape=box];

    // Nodes
    internet [shape=cloud, label="Internet"];
    firewall [shape=box3d, label="Firewall"];
    lb [label="Load
Balancer"];
    web1 [label="Web 1"];
    web2 [label="Web 2"];
    app1 [label="App 1"];
    app2 [label="App 2"];
    db [shape=cylinder, label="Database"];

    // Connections
    internet -- firewall;
    firewall -- lb;
    lb -- web1;
    lb -- web2;
    web1 -- app1;
    web1 -- app2;
    web2 -- app1;
    web2 -- app2;
    app1 -- db;
    app2 -- db;
}
エンティティ関係
digraph ERD {
    rankdir=LR;
    node [shape=record, fontname="Helvetica"];
    edge [arrowhead=none];

    user [label="<pk> User|id: PK\lname: string\lemail: string\l"];
    order [label="<pk> Order|id: PK\luser_id: FK\ltotal: decimal\l"];
    item [label="<pk> OrderItem|id: PK\lorder_id: FK\lproduct_id: FK\l"];
    product [label="<pk> Product|id: PK\lname: string\lprice: decimal\l"];

    user:pk -> order:pk [label="1:N", arrowhead=crow];
    order:pk -> item:pk [label="1:N", arrowhead=crow];
    product:pk -> item:pk [label="1:N", arrowhead=crow];
}
フローチャート
digraph Flowchart {
    rankdir=TB;
    node [fontname="Helvetica"];

    start [shape=ellipse, label="Start", style=filled, fillcolor=lightgreen];
    input [shape=parallelogram, label="Get Input"];
    validate [shape=diamond, label="Valid?"];
    process [shape=box, label="Process Data"];
    error [shape=box, label="Show Error", style=filled, fillcolor=lightyellow];
    output [shape=parallelogram, label="Output Result"];
    end [shape=ellipse, label="End", style=filled, fillcolor=lightcoral];

    start -> input;
    input -> validate;
    validate -> process [label="Yes"];
    validate -> error [label="No"];
    error -> input;
    process -> output;
    output -> end;
}

パブリッシャーとの連携

Obsidian との連携
def publish_graphviz_to_obsidian(
    vault_path: str,
    folder: str,
    filename: str,
    diagram_name: str,
    dot_source: str
):
    """Publish Graphviz diagram to Obsidian with source and image."""
    from pathlib import Path

    vault = Path(vault_path)
    target_dir = vault / folder
    attachments_dir = vault / "attachments"

    target_dir.mkdir(parents=True, exist_ok=True)
    attachments_dir.mkdir(parents=True, exist_ok=True)

    # Render image
    image_name = f"{filename}-diagram.png"
    image_path = attachments_dir / image_name
    render_graphviz(dot_source, image_path.with_suffix(""), "png")

    # Create markdown with both source and image
    content = f"""# {diagram_name}

## Source

```dot
{dot_source}

レンダリング結果

![[{image_name}]] """

note_path = target_dir / f"{filename}.md"
note_path.write_text(content)

### Joplin Integration
```python
def publish_graphviz_to_joplin(
    notebook: str,
    title: str,
    diagram_name: str,
    dot_source: str
):
    """Publish Graphviz diagram to Joplin with source and image."""
    import tempfile
    from pathlib import Path

    with tempfile.TemporaryDirectory() as tmpdir:
        tmpdir = Path(tmpdir)

        # Render image
        image_path = tmpdir / "diagram.png"
        render_graphviz(dot_source, image_path.with_suffix(""), "png")

        # Create markdown
        content = f"""# {diagram_name}

## Source

```dot
{dot_source}

レンダリング結果

{diagram_name} """

    md_path = tmpdir / f"{title}.md"
    md_path.write_text(content)

    # Joplin にインポートする(Markdown と参照先の画像をインポート)
    subprocess.run([
        "joplin", "import", str(tmpdir),
        "--notebook", notebook
    ], check=True)

## Graphviz vs Mermaid

| Feature | Graphviz | Mermaid |
|---------|----------|---------|
| **Layout control** | Precise, many engines | Automatic only |
| **Complexity** | Handles very large graphs | Better for simpler diagrams |
| **Rendering** | External tool required | Browser-native |
| **Styling** | Extensive options | Limited but sufficient |
| **Learning curve** | Steeper | Easier |
| **Use case** | Complex dependencies, call graphs | Quick diagrams, sequences |

**Use Graphviz when:**
- You need precise layout control
- Graph is large or complex
- You need specific node arrangements
- Creating dependency or call graphs

**Use Mermaid when:**
- Quick inline diagrams
- Sequence diagrams
- Simple flowcharts
- Native browser rendering preferred

## Prerequisites

### Install Graphviz
```bash
# macOS
brew install graphviz

# Ubuntu/Debian
sudo apt-get install graphviz

# Windows (chocolatey)
choco install graphviz

# Verify installation
dot -V

チェックリスト

Graphviz 図を作成する前に:

  • Graphviz がインストールされている(dot -V)
  • 出力ディレクトリに書き込み可能
  • DOT 構文を検証済み
  • 適切なレイアウトエンジンを選択済み
  • ソースと画像の両方を出力に含めている
  • 対象(Obsidian/Joplin)に応じた画像パスが正しい

コメント