Omnigraffle
Use whenever an OmniGraffle document or .graffle, .gtemplate, or .gstencil file is involved, including reading, inspecting, extracting, creating, editing, repairing, rendering, validating, or converting SVG, PDF, Visio, and other supported formats to or from OmniGraffle.From its SKILL.md
npx -y skills add smartaicoach/skills --skill omnigraffleAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT License. Public. See LICENSE.txt.. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.6 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it
OmniGraffle
Written by the repository maintainer, 2026. Public — MIT License (see LICENSE.txt).
Work with OmniGraffle documents (.graffle, .gtemplate, .gstencil) safely and correctly: inspect
them, convert other formats into them, edit or repair them, and export them back out. OmniGraffle
files are not plain text and not one fixed binary shape — the same .graffle extension can hide a
zip archive, a Finder-style package directory, a gzip-compressed plist, a raw XML plist, or a binary
plist. Treat every document as unknown until detected, and prefer OmniGraffle itself to write, import,
render, and validate the result rather than hand-editing serialized data.
Before doing anything: restate scope
State the source path and the requested output path (or, for pure inspection, just the source path). Classify the request into one of: inspect, modify, create, import (into OmniGraffle), export (out of OmniGraffle), repair, or validate. This classification decides which section below applies and what "done" means.
Non-negotiable safety rules
- Never overwrite the source file. Always write to a new output path or a timestamped backup
before touching anything. If the user gave an output path, use it; if they didn't and this is a
modification of an existing document, create
<name>_<YYYYMMDD-HHMMSS>.grafflenext to the original rather than replacing it, and say so. - Never upload a customer or user document to any online converter or web service. All
conversion happens locally through OmniGraffle itself,
plutil,plistlib, or the bundled scripts. - Never treat a binary
.graffleas ordinary text. Don'tcat,sed, orgrep -texta raw document. Detect its variant first (scripts/grafflectl detect) and use the matching reader. - Never do a blind search-and-replace inside
data.plist. Plists are typed, nested structures; a text-level replace can corrupt a value's type, truncate binary data, or land inside the wrong key entirely. Load it structurally (plistlib, orplutil -convert) before changing anything. - Never regenerate a whole document from a simplified JSON summary. A JSON inventory built for
Claude to read is deliberately lossy (see
references/file-formats.md). Writing a document back from that summary silently drops unknown keys, embedded assets, styles, and metadata. Only the typed-JSON round trip described inreferences/file-formats.mdis safe to write back from, and even then only as a controlled fallback (see Rule 7). - Preserve everything not explicitly being changed — unknown plist keys, binary values, embedded assets, styles, layers, IDs, and relationships. When in doubt, copy the input forward unchanged rather than reconstructing it.
- Prefer OmniGraffle itself as the writer, importer, renderer, and validator. Direct plist
patching (
references/file-formats.md,references/validation.md) is a controlled fallback for the narrow case where native automation genuinely cannot expose the needed property — not a default path. - Work in a temporary directory for extraction and intermediate files (
mktemp -d). Don't leave scratch files next to the user's documents. - Do not claim a creation, edit, or conversion is complete until the output has been saved, closed,
and reopened in OmniGraffle without error, per
references/validation.md. Inspection-only tasks don't require this (OmniGraffle doesn't need to be running to read a file), but anything that writes a document does. - If OmniGraffle is unavailable, or its installed license can't write the required format, report the blocker plainly rather than silently falling back to something weaker. Say what's missing and what would unblock it.
Step 1: Environment discovery
Run this once per session (skip if already done this session):
scripts/grafflectl doctor
This confirms: macOS, OmniGraffle's install path/version/build/bundle identifier, whether its
scripting dictionary exposes the operations this skill needs, Python 3 + plistlib, the standard
CLI tools (file, unzip, gzip, ditto, plutil, osascript, sdef, open), and temp-directory
write access. Read references/automation.md for what the doctor output means and how to react to a
missing capability (e.g. OmniGraffle not found, or an older version whose dictionary lacks an
operation this task needs).
Locate OmniGraffle by bundle identifier, not by a hardcoded application name — a user may have
OmniGraffle 6, 7, or a renamed/relocated copy. scripts/omnigraffle_bridge.applescript application-info does this and records path, version, build, bundle ID, and (via sdef) which
scripting commands are actually available. Never call an AppleScript or Omni Automation command that
sdef didn't confirm exists.
Step 2: Detect and inspect the input
For any existing .graffle/.gtemplate/.gstencil, or any SVG/PDF/Visio file being converted in:
scripts/grafflectl detect "<input>"
scripts/grafflectl inspect "<input>"
detect identifies which of the five OmniGraffle variants (or which foreign format) this file is,
using magic bytes and file/unzip -l/plutil — never by guessing from the extension. inspect
prints a short structural summary (canvas count, layer count, top-level graphic counts, embedded
asset count, document/app version) without dumping the full plist into context. Full detail lives in
references/file-formats.md.
Do not put the raw plist or the raw SVG source into your own context as a first move. Build a concise inventory instead:
scripts/grafflectl inventory "<input>" /tmp/<workdir>/inventory.json
Then read the resulting JSON (it's small) rather than the source document. The inventory covers
document/application versions; canvas names, IDs, sizes, order; layer names, order, visibility,
locking, printability; the graphic hierarchy, classes, names, and user data; text; bounds and
rotation; shape types; groups and nested groups; lines and endpoints; connections and magnets; fill,
stroke, font, and text properties; image references; embedded asset filenames; notes/metadata; and
cross-references. See references/file-formats.md for what each of these looks like inside the plist
and how the script builds them defensively (OmniGraffle's plist schema varies slightly by document
and app version — the script introspects rather than assuming a fixed shape, and so should any manual
follow-up).
Step 3: Choose the method — native automation first
| Task | Preferred method | Fallback |
|---|---|---|
| Create a new document, add/edit canvases, layers, shapes, lines, text, groups, styles | OmniGraffle native object model via AppleScript / Omni Automation JavaScript (scripts/omnigraffle_bridge.applescript) | Direct plist patch only if the property truly isn't exposed |
Import SVG → native .graffle | OmniGraffle's own SVG open/import | Never hand-roll an SVG→plist translator |
Export .graffle → PDF/PNG/SVG | OmniGraffle's own export | — |
| Repair a damaged document | Open in OmniGraffle if it opens at all; otherwise the plist-patch fallback in references/validation.md | — |
| Read-only inspection | scripts/graffle_plist.py (no OmniGraffle required) | — |
Read references/automation.md before calling the bridge: it explains how the bridge determines
which AppleScript verbs and which Omni Automation JavaScript entry points are actually available for
the installed version, and how to fall back correctly when one path isn't exposed. Never hard-code an
application name, file-type identifier, or scripting command the installed dictionary hasn't
confirmed.
Step 4: Do the work
- SVG → OmniGraffle: follow
references/conversion-workflows.mdin full — it covers SVG inventory (viewBox, paths, groups, text, fonts, transforms, gradients, clipping, masks, markers, embedded/external images), resource resolution, the native import call, whether the result stayed vector-editable or got flattened into one object, and the visual diff pass against the source. - Export: use
scripts/omnigraffle_bridge.applescript export-pdf|export-png|export-svg. Confirm canvas count and dimensions match expectations before declaring the export done. - Direct plist patching (fallback only): follow the procedure in
references/file-formats.md("Direct plist patching") exactly — extract to a temp workspace, parse withplistlib, apply a narrow deterministic change, preserve every untouched key and asset, re-serialize, rebuild any zip archive with files at the archive root (no extra enclosing directory), then hand the provisional result back to OmniGraffle for open → save → close → reopen → render before trusting it.
Step 5: Validate
Every task that produced or changed a document goes through references/validation.md's checklist
before you report success: structural validity (archive integrity, data.plist parses, every
referenced asset exists), OmniGraffle opens it without error, saves it, closes it, reopens the saved
copy, and every relevant canvas renders. For conversions specifically, check for missing graphics,
displaced objects, changed colors, broken gradients, wrong transparency or clipping, font
substitution, altered text, wrong line endings, and unexpected flattening — and fix confirmed
differences, then re-run the save/close/reopen/render cycle.
If something in this checklist can't be completed (OmniGraffle isn't installed, a needed operation isn't in the scripting dictionary, a feature genuinely doesn't survive import), that is a reported limitation, not a silent gap.
Step 6: Report
Close with a completion report — see references/validation.md for the exact fields (source path,
output path, backup path, OmniGraffle version used, writing/import method, whether objects stayed
editable, canvas/layer/graphic/asset counts, structural validation result, reopen test result, render
validation result, confirmed limitations). Don't claim something was copied, matched, converted, or
validated unless it actually happened in this session.
Reference map
| File | Read it when |
|---|---|
references/file-formats.md | Detecting a variant, understanding data.plist structure, building an inventory, or doing a plist-patch fallback |
references/automation.md | Calling the AppleScript/Omni Automation bridge, or reacting to a missing capability from doctor |
references/conversion-workflows.md | Converting SVG (or another format) into .graffle, or exporting out |
references/validation.md | Before reporting any create/edit/import/export/repair as complete |
Scripts
| Script | Purpose |
|---|---|
scripts/grafflectl | Single entry point: detect, inspect, extract, inventory, import-svg, render, export, validate, compare, doctor |
scripts/graffle_plist.py | Format-agnostic plist operations: detect, inspect, extract, inventory, plist↔typed-JSON, validate, compare-structure. Works without OmniGraffle installed. |
scripts/omnigraffle_bridge.applescript | Native automation: application-info, open, create, save-copy, close, reopen, import-svg, combine-svgs, export-pdf/png/svg, inventory-native, validate-open |
grafflectl shells out to both of the above — call grafflectl for everyday use, and drop to the
underlying scripts directly only when a task needs an operation grafflectl doesn't wrap yet.
What ships with it: 8 files
70.2 KB alongside SKILL.md, 3 of them executable
references/
- automation.md8.0 KB
- conversion-workflows.md7.2 KB
- file-formats.md7.5 KB
- validation.md4.2 KB
scripts/
- grafflectlruns5.4 KB
- graffle_plist.pyruns20.1 KB
- omnigraffle_bridge.applescriptruns16.8 KB
- LICENSE.txt1.0 KB