agentleFS
manazoid4manazoid4/maz-works-knowledge-vault/skills/canvas/SKILL.md

canvas

Skill0 starsChanged 3 months agoMITView on GitHub

Visual layer of the wiki. Add images, text cards, PDFs, and wiki pages to Obsidian canvas files with auto-positioning inside zones. Integrates with /banana for image capture. Triggers on: /canvas, canvas new, canvas add image, canvas add text, canvas add pdf, canvas add note, canvas zone, canvas list, canvas from banana, add to canvas, put this on the canvas, open canvas, create canvas.

47 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

Used with

Projects with it also use taskflow-inbox-triage, update-cli-config and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • AtomicBot-aiSkill

    taskflow-inbox-triage

    Also in 5 projects that use this

  • PandelisZSkill

    update-cli-config

    View and modify Cursor CLI configuration settings in ~/.cursor/cli-config.json. Use when the user wants to change CLI settings, configure permissions, switch approval mode, enable vim mode, toggle display options, configure sandbox, or manage any CLI preferences.

    Also in 6 projects that use this

  • jiulingyunSkill

    BlueBubbles

    为Clawdbot构建或更新BlueBubbles外部通道插件(扩展包,REST发送/探测,webhook入站)。

    Also in 15 projects that use this

  • seedprodSkill

    voice-call

    Start voice calls via the OpenClaw voice-call plugin.

    Also in 14 projects that use this

  • 32103210Skill

    migrate-to-skills

    Convert 'Applied intelligently' Cursor rules (.cursor/rules/*.mdc) and slash commands (.cursor/commands/*.md) to Agent Skills format (.cursor/skills/). Use when you want to migrate rules or commands to skills, convert .mdc rules to SKILL.md format, or consolidate commands into the skills directory.

    Also in 6 projects that use this

  • 32103210Skill

    update-cursor-settings

    Modify Cursor/VSCode user settings in settings.json. Use when you want to change editor settings, preferences, configuration, themes, font size, tab size, format on save, auto save, keybindings, or any settings.json values.

    Also in 6 projects that use this

  • +1 more from 32103210

The file

Show its rules and text

We split this skill into the rules it gives an agent

32 rules. 0 are common, 12 are distinctive, and 20 are very specific to this project.

  • 0

    Common

    Most of the 44 edited versions we read keep these.

  • 12

    Distinctive

    This author's own choices. Worth a look.

  • 20

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If it does not exist, create it:

    line 24
  2. Very specific:

    Check if wiki/canvases/main.canvas exists.

    line 52
  3. Distinctive:

    If yes: read it, count nodes by type, list all group node labels (zone names).

    line 53
  4. Distinctive:

    If no: create it with the starter structure above.

    line 55
  5. Very specific:

    Create wiki/canvases/[slug].canvas with the starter structure, title updated to # [Name].

    line 64
  6. Very specific:

    Add entry to wiki/overview.md under a "## Canvases" subsection (append after the Current State section).

    line 65
  7. Very specific:

    If URL (starts with http): download with curl -sL [url] -o _attachments/images/canvas/[filename] Derive filename from URL path, or use …

    line 73
  8. Very specific:

    If local path outside vault: cp [path] _attachments/images/canvas/

    line 75
  9. Distinctive:

    If already vault-relative: use as-is.

    line 76
  10. Very specific:

    Create _attachments/images/canvas/ if it doesn't exist.

    line 78
  11. Very specific:

    Use python3 -c "from PIL import Image.

    line 81
  12. Distinctive:

    Create a text node:

    line 94
  13. Very specific:

    Search wiki/ for a file matching the page name (case-insensitive, partial match ok).

    line 121
  14. Very specific:

    Use the vault-relative path as the file field.

    line 122
  15. Very specific:

    Use "type": "file" (not "type": "link"): .md files use file nodes, not link nodes.

    line 123
  16. Distinctive:

    Create a file node: width=300, height=100.

    line 125
  17. Distinctive:

    Create a group node:

    line 144
  18. Very specific:

    Check wiki/canvases/.recent-images.txt first (session log of newly written images).

    line 180
  19. Very specific:

    If not found or empty: use find with correct precedence (parentheses required.

    line 181
  20. Distinctive:

    If still none: show the 5 most recently modified images.

    line 187
  21. Very specific:

    Read references/canvas-spec.md for the full coordinate system.

    line 195
  22. Distinctive:

    Read the canvas, collect all existing IDs.

    line 238
  23. Distinctive:

    Use the full Unix timestamp (10 digits) to avoid collisions in batch operations.

    line 242
  24. Very specific:

    If a collision is detected (ID already exists in the canvas), append -2, -3, etc.

    line 246
  25. Very specific:

    If wiki/canvases/.recent-images.txt exists, append any new image path written to _attachments/images/ during this session (one path per …

    line 252
  26. Very specific:

    After any /banana run in the same session, if the user says "add to canvas" or "put on canvas", treat it as /canvas from banana.

    line 260
  27. Very specific:

    When /banana finishes generating images, suggest:

    line 262
  28. Distinctive:

    Read canvas-spec.md before editing any canvas JSON.

    line 269
  29. Distinctive:

    Always read the canvas file before writing.

    line 270
  30. Very specific:

    Create _attachments/images/canvas/ for downloaded/copied images.

    line 271
  31. Very specific:

    Update wiki/index.md when creating new canvases.

    line 272
  32. Very specific:

    When working on this skill, apply the 10-principle loop.

    line 286

“Common” is measured: kept by at least 6 in 10 of the 44 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

canvas: Visual Reference Layer

The three knowledge capture layers:

  • /save → text synthesis (wiki/questions/, wiki/concepts/)
  • /autoresearch → structured knowledge (wiki/sources/, wiki/concepts/)
  • /canvas → visual references (wiki/canvases/)

A canvas is a JSON file Obsidian renders as an infinite visual board. This skill reads and writes canvas JSON directly. Read references/canvas-spec.md for the full format reference before making any edits. This spec aligns with the JSON Canvas open standard.

Substrate preference (v1.7+): This skill is a self-contained fallback. Prefer kepano/obsidian-skills as the authoritative substrate — its json-canvas skill is the canonical spec reference. If a separate json-canvas skill is available, use it for spec questions. Continue to use this canvas skill for Maz Works vault workflows such as positioning into wiki/canvases/, image integration, and zone layout. Install kepano with claude plugin marketplace add kepano/obsidian-skills.


Default Canvas

wiki/canvases/main.canvas

If it does not exist, create it:

{
  "nodes": [
    {
      "id": "title",
      "type": "text",
      "text": "# Visual Reference\n\nDrop images, PDFs, and notes here.",
      "x": -400, "y": -300, "width": 400, "height": 120, "color": "6"
    },
    {
      "id": "zone-default",
      "type": "group",
      "label": "General",
      "x": -400, "y": -140, "width": 800, "height": 400, "color": "4"
    }
  ],
  "edges": []
}

Operations

open / status (/canvas with no args)

  1. Check if wiki/canvases/main.canvas exists.
  2. If yes: read it, count nodes by type, list all group node labels (zone names). Report: "Canvas has N nodes: X images, Y text cards, Z wiki pages. Zones: [list]"
  3. If no: create it with the starter structure above. Report: "Created main.canvas with a General zone."
  4. Tell user: "Open wiki/canvases/main.canvas in Obsidian to view."

new (/canvas new [name])

  1. Slugify the name: lowercase, spaces → hyphens, strip special chars.
  2. Create wiki/canvases/[slug].canvas with the starter structure, title updated to # [Name].
  3. Add entry to wiki/overview.md under a "## Canvases" subsection (append after the Current State section). Do not modify wiki/index.md. It uses a fixed section schema (Domains, Entities, Concepts, Sources, Questions, Comparisons).
  4. Report: "Created wiki/canvases/[slug].canvas"

add image (/canvas add image [path or url])

Resolve the image:

  • If URL (starts with http): download with curl -sL [url] -o _attachments/images/canvas/[filename] Derive filename from URL path, or use img-[timestamp].jpg if unclear.
  • If local path outside vault: cp [path] _attachments/images/canvas/
  • If already vault-relative: use as-is.

Create _attachments/images/canvas/ if it doesn't exist.

Detect aspect ratio: Use python3 -c "from PIL import Image; img=Image.open('[path]'); print(img.width, img.height)" or identify -format '%w %h' [path]. See references/canvas-spec.md for the full aspect ratio → canvas size table (7 ratios including 4:3, 3:4, ultra-wide). Do not use an inline table here. The spec is the single source of truth for sizing.

Position using auto-layout (see Auto-Positioning section below).

Append node to canvas JSON and write.

Report: "Added [filename] to [zone] zone at position ([x], [y])."


add text (/canvas add text [content])

Create a text node:

{
  "id": "text-[timestamp]",
  "type": "text",
  "text": "[content]",
  "x": [auto], "y": [auto],
  "width": 300, "height": 120,
  "color": "4"
}

Position using auto-layout. Write and report.


add pdf (/canvas add pdf [path])

Same as add image. Obsidian renders PDFs natively as file nodes.

  • Copy to _attachments/pdfs/canvas/ if outside vault.
  • Fixed size: width=400, height=520.
  • Report page count if you can determine it.

add note (/canvas add note [wiki-page])

  1. Search wiki/ for a file matching the page name (case-insensitive, partial match ok).
  2. Use the vault-relative path as the file field.
    • Use "type": "file" (not "type": "link"): .md files use file nodes, not link nodes.
    • "type": "link" takes a url: "https://...": it is for web URLs only.
  3. Create a file node: width=300, height=100.
  4. Position using auto-layout.
{
  "id": "note-[timestamp]",
  "type": "file",
  "file": "wiki/concepts/LLM Wiki Pattern.md",
  "x": [auto], "y": [auto],
  "width": 300, "height": 100
}

zone (/canvas zone [name] [color])

  1. Read canvas JSON.
  2. Find max_y: max(node.y + node.height for all nodes) + 60. Use 280 if no nodes (leaves room above the starter title node).
  3. Create a group node:
{
  "id": "zone-[slug]",
  "type": "group",
  "label": "[name]",
  "x": -400,
  "y": [max_y],
  "width": 1000,
  "height": 400,
  "color": "[color or '3']"
}

Valid colors: "1"=red "2"=orange "3"=yellow "4"=green "5"=cyan "6"=purple

Write and report.


list (/canvas list)

  1. glob wiki/canvases/*.canvas
  2. For each canvas: read JSON, count nodes by type.
  3. Report:
wiki/canvases/main.canvas      . 14 nodes (8 images, 3 text, 2 file, 1 group)
wiki/canvases/design-ideas.canvas. 42 nodes (30 images, 4 text, 8 groups)

from banana (/canvas from banana) (if the banana-claude plugin is installed)

  1. Check wiki/canvases/.recent-images.txt first (session log of newly written images).
  2. If not found or empty: use find with correct precedence (parentheses required. Without them -newer only binds to the last -name clause):
    python3 -c "import time,os; open('/tmp/ten-min-ago','w').close(); os.utime('/tmp/ten-min-ago',(time.time()-600,time.time()-600))"
    find _attachments/images -newer /tmp/ten-min-ago \( -name "*.png" -o -name "*.jpg" \)
    Note: /banana is an optional external skill not shipped in this plugin. If the user has it installed, the .recent-images.txt log will be populated. If not, the find command above is the fallback.
  3. If still none: show the 5 most recently modified images.
  4. Present list: "Found N recent images: [list]. Add to canvas? Which zone? (zone name / 'new [name]' / 'skip')"
  5. On confirmation: add each using the add image logic.

Auto-Positioning Algorithm

Read references/canvas-spec.md for the full coordinate system.

def next_position(canvas_nodes, target_zone_label, new_w, new_h):
    # Find zone group node
    zone = next((n for n in canvas_nodes
                 if n.get('type') == 'group'
                 and n.get('label') == target_zone_label), None)

    if zone is None:
        # No zone: place below all content
        max_y = max((n['y'] + n.get('height', 0) for n in canvas_nodes), default=-140)
        return -400, max_y + 60

    zx, zy = zone['x'], zone['y']
    zw, zh = zone['width'], zone['height']

    # Nodes inside this zone
    inside = [n for n in canvas_nodes
              if n.get('type') != 'group'
              and zx <= n['x'] < zx + zw
              and zy <= n['y'] < zy + zh]

    if not inside:
        return zx + 20, zy + 20

    rightmost_x = max(n['x'] + n.get('width', 0) for n in inside)
    next_x = rightmost_x + 40

    if next_x + new_w > zx + zw:
        # New row
        max_row_y = max(n['y'] + n.get('height', 0) for n in inside)
        return zx + 20, max_row_y + 20

    # Same row: align to the top of all existing nodes in the zone
    current_row_y = min(n['y'] for n in inside)
    return next_x, current_row_y

ID Generation

Read the canvas, collect all existing IDs. Never reuse one.

Safe ID pattern: [type]-[content-slug]-[full-unix-timestamp]

Use the full Unix timestamp (10 digits) to avoid collisions in batch operations.

Examples: img-cover-1744032823, text-note-1744032845, zone-branding-1744032901

If a collision is detected (ID already exists in the canvas), append -2, -3, etc.


Session Log (optional hook)

If wiki/canvases/.recent-images.txt exists, append any new image path written to _attachments/images/ during this session (one path per line, keep last 20).

/canvas from banana reads this file first, making it instant without filesystem search.


Banana Integration (if the banana-claude plugin is installed)

After any /banana run in the same session, if the user says "add to canvas" or "put on canvas", treat it as /canvas from banana.

When /banana finishes generating images, suggest:

"Add generated images to canvas? Run /canvas from banana"


Summary

  1. Read canvas-spec.md before editing any canvas JSON.
  2. Always read the canvas file before writing. Parse existing nodes to avoid ID collisions and calculate auto-positions.
  3. Create _attachments/images/canvas/ for downloaded/copied images.
  4. Update wiki/index.md when creating new canvases.
  5. Report position and zone after every add operation.

See Also

For standalone visual production (12 templates, 6 layout algorithms, AI generation, presentations), see claude-canvas. This skill handles wiki-scoped visual boards. claude-canvas handles full-featured canvas orchestration for any project.


How to think (10-principle mapping)

When working on this skill, apply the 10-principle loop. See skills/think/SKILL.md for the canonical framework.

#PrincipleApplication here
1OBSERVE (ext)Which images, PDFs, notes belong on this canvas? Read each before adding.
2OBSERVE (int)Am I aestheticizing or actually communicating? Pretty canvases that don't inform are noise.
3LISTENThe user's mental model of how these items relate. The canvas should mirror that, not impose another.
4THINKLayout, group hierarchy, edge structure. Spatial reasoning matters; arbitrary positions confuse.
5CONNECT (lat)Edges between canvas nodes reveal hidden structure not visible in the linear wiki.
6CONNECT (sys)JSON Canvas 1.0 spec + Obsidian-native rendering + banana skill for AI image gen.
7FEELA canvas should be readable at first glance, not a maze of arrows.
8ACCEPTNot every project needs a canvas. Admit when prose is enough.
9CREATEWrite the .canvas JSON with stable IDs and sensible positions.
10GROWWhich canvases get reopened? Which are abandoned? That signal informs canvas-worthiness over time.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.