smithery.ai

canvas-gen

Generate Obsidian Canvas files from beads issues. Use: /canvas-gen [epic-id]

First seen Apr 14, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
Allowed toolsBash, Read, Write, Glob

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,307 B
  • docs SUMMARY.md 94 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

/canvas-gen — Canvas Generation from Beads

TL;DR: Auto-generate Obsidian Canvas files from beads issues for visual task tracking.


Usage

/canvas-gen                   # Generate from all in-progress issues
/canvas-gen <epic-id>         # Generate from specific epic
/canvas-gen --template=work   # Use work session template
/canvas-gen --output=<name>   # Custom output filename

Canvas Types

Template Use Case Structure
work Active work session Epic → Tasks → Subtasks
hierarchy Skill/agent overview Layers with relationships
timeline Sprint/week view Date-ordered columns

Execution

1. PARSE input:
   epic_id = PARSE argument (optional)
   template = PARSE --template flag (default: "work")
   output_name = PARSE --output flag (default: auto-generated)

2. FETCH beads data:
   IF epic_id:
       issues = Bash("bd show {epic_id} --format=json")
       children = Bash("bd list --parent={epic_id} --format=json")
   ELSE:
       issues = Bash("bd list --status=in_progress --format=json")

3. GENERATE canvas structure:
   canvas = {
       nodes: [],
       edges: []
   }

   # Layout constants
   NODE_WIDTH = 250
   NODE_HEIGHT = 60
   COLUMN_GAP = 300
   ROW_GAP = 100

   # Position tracking
   x_offset = 0
   y_offset = 0

   # Generate nodes by status
   FOR EACH status IN ["in_progress", "blocked", "pending", "completed"]:
       status_issues = issues.filter(i => i.status == status)
       column_y = 0

       FOR EACH issue IN status_issues:
           node = {
               id: issue.id,
               type: "text",
               x: x_offset,
               y: column_y,
               width: NODE_WIDTH,
               height: NODE_HEIGHT,
               text: FORMAT_NODE_TEXT(issue),
               color: STATUS_COLOR(status)
           }
           canvas.nodes.push(node)
           column_y += ROW_GAP

       x_offset += COLUMN_GAP

4. GENERATE edges (dependencies):
   FOR EACH issue IN issues:
       IF issue.blocked_by:
           FOR EACH blocker_id IN issue.blocked_by:
               edge = {
                   id: GENERATE_ID(),
                   fromNode: blocker_id,
                   toNode: issue.id,
                   fromSide: "right",
                   toSide: "left"
               }
               canvas.edges.push(edge)

5. FORMAT_NODE_TEXT(issue):
   RETURN "**{issue.id}**\n{issue.title}\n_{issue.status}_"

6. STATUS_COLOR(status):
   MATCH status:
       "in_progress" → "5"  # Purple
       "blocked"     → "1"  # Red
       "pending"     → "4"  # Yellow
       "completed"   → "4"  # Green (using yellow, no green in Obsidian)
   DEFAULT → "0"

7. WRITE canvas file:
   IF output_name:
       filename = output_name + ".canvas"
   ELSE:
       filename = "beads-" + DATE + ".canvas"

   filepath = "obsidian-vault/canvas/" + filename
   Write(filepath, JSON.stringify(canvas, null, 2))

8. OUTPUT confirmation:
   OUTPUT "✅ Canvas generated: {filepath}"
   OUTPUT "Nodes: {canvas.nodes.length} | Edges: {canvas.edges.length}"
   OUTPUT "Open in Obsidian to view"

Output Format

Canvas JSON Structure

{
  "nodes": [
    {
      "id": "beads-abc",
      "type": "text",
      "x": 0,
      "y": 0,
      "width": 250,
      "height": 60,
      "text": "**beads-abc**\nImplement feature X\n_in_progress_",
      "color": "5"
    }
  ],
  "edges": [
    {
      "id": "edge-1",
      "fromNode": "beads-xyz",
      "toNode": "beads-abc",
      "fromSide": "right",
      "toSide": "left"
    }
  ]
}

Color Reference

Obsidian Canvas colors:

Color Code Color Use For
"0" Default -
"1" Red Blocked
"2" Orange Priority
"3" Yellow Pending
"4" Green Completed
"5" Cyan In Progress
"6" Purple Epic

Integration

With /retro

After /retro extracts entities, /canvas-gen can visualize:

  • Skills used → nodes
  • Agents spawned → child nodes
  • Dependencies → edges

With /next

/next shows ready issues; /canvas-gen can highlight them in canvas view.


Examples

Example 1: Current Work

/canvas-gen

✅ Canvas generated: obsidian-vault/canvas/beads-2026-01-26.canvas
Nodes: 5 | Edges: 2
Open in Obsidian to view

Example 2: Specific Epic

/canvas-gen beads-epic-001

✅ Canvas generated: obsidian-vault/canvas/epic-001.canvas
Nodes: 8 | Edges: 5
Epic: "MVP Implementation" with 7 child issues

Error Handling

Condition Recovery
No beads issues found Output empty canvas with note
bd command fails Fallback to reading .beads/issues.jsonl
Invalid epic ID Warn and show available epics

Notes

  • Canvas files are JSON, git-tracked
  • Regenerate anytime — canvas reflects current beads state
  • Manual edits to canvas preserved if regenerating with different filename
  • Use --output to avoid overwriting custom layouts