# Dagre Layout Engine

> Dagre Layout Engine

- Skill: `yanacuti1121/dagre-layout-engine` (Agent Skill)
- Install (CLI): `npx skillmds@latest add yanacuti1121/dagre-layout-engine`
- Raw SKILL.md: https://api.skillmd.com/api/skills/yanacuti1121/dagre-layout-engine/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: yanacuti1121 (https://skillmd.com/u/yanacuti1121)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/yanacuti1121/dagre-layout-engine

---


# /dagre-layout-engine

## When to Use

- Auto-compute (x, y) positions for yamtam skill dependency graph nodes
- Render agent hierarchy diagram without manual coordinate placement
- Generate layered layouts for rule gate topology (L0 → L5)
- Integrate with D3.js, React Flow, or SVG rendering for visual output

## Do NOT use for

- Force-directed layouts (use d3-force for organic graphs)
- Cyclic graphs (dagre requires DAG — directed *acyclic* graph)

---

## Compute layout for skill graph

```javascript
import dagre from 'dagre'

function layoutSkillGraph(
  skills: string[],
  deps:   [string, string][]   // [from, to] edges
): Map<string, { x: number; y: number; width: number; height: number }> {
  const g = new dagre.graphlib.Graph()

  g.setGraph({
    rankdir: 'TB',     // top-to-bottom layout
    nodesep: 30,       // horizontal separation between nodes
    ranksep: 50,       // vertical separation between ranks
    marginx:  20,
    marginy:  20,
  })

  g.setDefaultEdgeLabel(() => ({}))

  // Add nodes with dimensions
  for (const skill of skills) {
    g.setNode(skill, { label: skill, width: 180, height: 40 })
  }

  // Add edges
  for (const [from, to] of deps) {
    g.setEdge(from, to)
  }

  // Compute layout
  dagre.layout(g)

  // Extract positions
  const positions = new Map<string, { x: number; y: number; width: number; height: number }>()
  for (const node of g.nodes()) {
    positions.set(node, g.node(node))
  }
  return positions
}
```

---

## Defense gate topology layout

```javascript
const gateNodes = ['L0-audit', 'L1-evasion', 'L2-proxy', 'L3-container', 'L4-deps', 'L5-path']
const gateEdges: [string, string][] = [
  ['L0-audit', 'L1-evasion'],
  ['L1-evasion', 'L2-proxy'],
  ['L2-proxy', 'L3-container'],
  ['L3-container', 'L4-deps'],
  ['L4-deps', 'L5-path'],
]

const positions = layoutSkillGraph(gateNodes, gateEdges)
// Render SVG using computed positions
for (const [node, pos] of positions) {
  console.log(`${node}: x=${pos.x.toFixed(0)}, y=${pos.y.toFixed(0)}`)
}
```

---

## Export to SVG

```javascript
function toSvg(positions: Map<string, { x: number; y: number; width: number; height: number }>): string {
  const rects = [...positions.entries()].map(([label, { x, y, width, height }]) =>
    `<rect x="${x - width/2}" y="${y - height/2}" width="${width}" height="${height}" rx="4" fill="#f0f4f8" stroke="#888"/>
     <text x="${x}" y="${y}" text-anchor="middle" dominant-baseline="middle" font-size="12">${label}</text>`
  ).join('\n')

  const maxX = Math.max(...[...positions.values()].map(p => p.x + p.width / 2)) + 20
  const maxY = Math.max(...[...positions.values()].map(p => p.y + p.height / 2)) + 20

  return `<svg xmlns="http://www.w3.org/2000/svg" width="${maxX}" height="${maxY}">\n${rects}\n</svg>`
}
```

---

## Anti-Fake-Pass Checklist

```
❌ Cyclic edges → dagre hangs or throws — validate DAG before layout
❌ Node added after dagre.layout() → position = undefined
❌ rankdir:'LR' for deep trees → horizontal layout overflows viewport
❌ No width/height on nodes → dagre uses 0×0 → nodes overlap
❌ Edge label not set (setDefaultEdgeLabel missing) → graphlib throws
❌ g.node() returns undefined for nodes not in graph — check g.hasNode() first
```

