omnigraffle

Generate native OmniGraffle .graffle files programmatically. Use this skill whenever the user asks to create, build, or generate an OmniGraffle diagram, network diagram, architecture diagram, flowchart, or any visual diagram that should be saved as a .graffle file. Also trigger when the user mentions "OmniGraffle", ".graffle", "graffle file", or asks for diagrams specifically for macOS/iOS diagramming. This skill generates zipped binary plist packages that open natively in OmniGraffle 7+ without any conversion or import steps. Supports: rectangles with colored fills, text labels (RTF), named layers, line connections between shapes, arrows, groups, rotation, dashed lines, multi-point paths, and magnets for connection snapping.

OmniGraffle File Generator

Generate native .graffle files that open directly in OmniGraffle 7+ on macOS and iOS.

How It Works

OmniGraffle files are ZIP archives containing a binary Apple plist (data.plist) and a preview JPEG. This skill uses Python's plistlib to assemble the document structure and zipfile to package it. The output matches OmniGraffle 7's native format (GraphDocumentVersion 16, zipped).

Step 1: Copy Scripts

Before generating any file, copy the builder scripts to your working directory:

cp -r /path/to/this/skill/src/ /home/claude/omnigraffle-src/

Then import:

import sys
sys.path.insert(0, '/home/claude/omnigraffle-scripts')
from src.graffle_builder import GraffleBuilder, create_network_diagram, COLORS

Step 2: Understand the User's Diagram

Ask or infer:

  1. What type of diagram? Network architecture, flowchart, org chart, system diagram
  2. What are the nodes/shapes? Names, positions, colors, groupings
  3. What are the connections? Which nodes connect, line colors, arrows
  4. What layers are needed? Logical groupings (e.g., "hardware", "network", "labels")

Step 3: Build the Diagram

Option A: Low-Level Builder API

For full control over every element:

from src.graffle_builder import GraffleBuilder

b = GraffleBuilder(title="My Diagram", creator="User Name")

# Clear default layer and add custom ones
b._layers = []
l_hw = b.add_layer("hardware")
l_net = b.add_layer("network")

# Add shapes (returns shape ID for connections)
srv = b.add_shape(x=100, y=100, w=120, h=40,
                  text="Server1", fill_color="blue",
                  layer=l_hw, name="Server1")

sw = b.add_shape(x=300, y=100, w=120, h=40,
                 text="Switch", fill_color="green",
                 layer=l_net, name="Switch")

# Connect shapes
b.add_line(from_id=srv, to_id=sw, color="blue", width=2.0,
           layer=l_net, head_arrow="FilledArrow")

# Add floating text labels
b.add_text_label(100, 60, "Rack 1", font_size=14,
                 text_color=(0,0,0), bold=True)

# Group shapes together
group_id = b.add_group([srv, sw], layer=l_hw)

# Save
b.save("/mnt/user-data/outputs/diagram.graffle")

Option B: High-Level Network Diagram

For quick network/architecture diagrams from structured data:

from src.graffle_builder import create_network_diagram

builder = create_network_diagram(
    title="Data Center Network",
    layers=["servers", "switches", "storage"],
    nodes=[
        {"name": "Web-1", "x": 100, "y": 50, "color": "blue"},
        {"name": "Web-2", "x": 250, "y": 50, "color": "blue"},
        {"name": "LB",    "x": 175, "y": 150, "w": 140, "color": "green"},
        {"name": "DB",    "x": 175, "y": 250, "color": "red", "layer": 2},
    ],
    connections=[
        {"from_name": "Web-1", "to_name": "LB", "color": "yellow", "width": 2},
        {"from_name": "Web-2", "to_name": "LB", "color": "yellow", "width": 2},
        {"from_name": "LB", "to_name": "DB", "arrow": True, "width": 2},
    ],
)
builder.save("/mnt/user-data/outputs/network.graffle")

API Reference

GraffleBuilder(title, creator, orientation, paper_size)

ParamDefaultValues
title"Canvas 1"Canvas name
creator"Claude"Author metadata
orientation"landscape""landscape" or "portrait"
paper_size"A4""A4", "letter", "A3"

add_layer(name, locked, visible, printable) → layer_index

add_shape(x, y, w, h, ...) → shape_id

ParamDefaultNotes
text""Label inside shape
fill_colorNoneRGB (0-1) tuple or color name string
text_color(255,255,255)RGB (0-255)
font_size10Points
font"HelveticaNeue"Font name
layer0Layer index
nameNoneShape identifier
rotationNoneDegrees (e.g., 90.0)
magnetsTrueConnection snap points
strokeFalseDraw border
stroke_colorNoneBorder RGB (0-1)
stroke_width1.0Border width
boldFalseBold text
fit_textFalseAuto-resize to fit text

add_text_label(x, y, text, ...) → shape_id

Convenience for borderless/fillless text. Same params as add_shape minus fill/stroke.

add_line(from_id, to_id, ...) → line_id

ParamDefaultNotes
from_id/to_idNoneShape IDs for connected lines
from_point/to_pointNone(x,y) for unconnected endpoints
colorNoneRGB (0-1) or color name
width1.0Line width
layer0Layer index
head_arrowNone"FilledArrow" for arrowhead
dashedFalseDashed line style

add_line_multi_point(points, ...) → line_id

For multi-segment paths. points is a list of (x,y) tuples.

add_group(shape_ids, layer) → group_id

Groups existing shapes. Removes them from main list and nests under group.

save(filepath)

Writes the .graffle ZIP file.

Available Named Colors

Use these strings for fill_color or color parameters:

blue, red, green, yellow, orange, purple, cyan, pink, brown, white, lightgray, darkgray, black, lightblue, lightgreen, lightcyan, lightpink, lightyellow, darkblue, darkgreen, darkred

Or pass any RGB tuple like (0.5, 0.8, 0.2) in the 0-1 range.

Layout Tips

  • OmniGraffle coordinate system: origin is top-left, units are points (1/72 inch)
  • Typical node sizes: 100-150w × 30-50h for labels, 40-60w × 14-20h for small tags
  • Vertical spacing: 80-120 points between rows
  • Horizontal spacing: 40-80 points between columns
  • Use layers to separate logical diagram elements (hardware, networks, labels)
  • Name important shapes so they can be found in OmniGraffle's sidebar

Limitations

  • All shapes are rectangles (no circles, ovals, or custom paths yet)
  • No image fills or embedded images
  • No stencil references
  • Auto-layout must be done in OmniGraffle after opening
  • Preview JPEG is a blank placeholder (OmniGraffle regenerates it on first save)