|
@@ -0,0 +1,197 @@
|
|
|
|
|
+---
|
|
|
|
|
+name: omnigraffle
|
|
|
|
|
+description: >
|
|
|
|
|
+ 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:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cp -r /path/to/this/skill/src/ /home/claude/omnigraffle-src/
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Then import:
|
|
|
|
|
+```python
|
|
|
|
|
+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:
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+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:
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+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)
|
|
|
|
|
+
|
|
|
|
|
+| Param | Default | Values |
|
|
|
|
|
+|-------|---------|--------|
|
|
|
|
|
+| 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
|
|
|
|
|
+
|
|
|
|
|
+| Param | Default | Notes |
|
|
|
|
|
+|-------|---------|-------|
|
|
|
|
|
+| text | "" | Label inside shape |
|
|
|
|
|
+| fill_color | None | RGB (0-1) tuple or color name string |
|
|
|
|
|
+| text_color | (255,255,255) | RGB (0-255) |
|
|
|
|
|
+| font_size | 10 | Points |
|
|
|
|
|
+| font | "HelveticaNeue" | Font name |
|
|
|
|
|
+| layer | 0 | Layer index |
|
|
|
|
|
+| name | None | Shape identifier |
|
|
|
|
|
+| rotation | None | Degrees (e.g., 90.0) |
|
|
|
|
|
+| magnets | True | Connection snap points |
|
|
|
|
|
+| stroke | False | Draw border |
|
|
|
|
|
+| stroke_color | None | Border RGB (0-1) |
|
|
|
|
|
+| stroke_width | 1.0 | Border width |
|
|
|
|
|
+| bold | False | Bold text |
|
|
|
|
|
+| fit_text | False | Auto-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
|
|
|
|
|
+
|
|
|
|
|
+| Param | Default | Notes |
|
|
|
|
|
+|-------|---------|-------|
|
|
|
|
|
+| from_id/to_id | None | Shape IDs for connected lines |
|
|
|
|
|
+| from_point/to_point | None | (x,y) for unconnected endpoints |
|
|
|
|
|
+| color | None | RGB (0-1) or color name |
|
|
|
|
|
+| width | 1.0 | Line width |
|
|
|
|
|
+| layer | 0 | Layer index |
|
|
|
|
|
+| head_arrow | None | "FilledArrow" for arrowhead |
|
|
|
|
|
+| dashed | False | Dashed 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)
|