Master Sketch Plugin Development: From Bundle Structure to Advanced UI Panels

This guide walks you through Sketch plugin architecture, manifest configuration, command definitions, Actions and JavaScript APIs, CocoaScript bridging, UI panel creation with AppKit, sidebar navigation, debugging techniques, logging methods, and using SketchTool for automation, providing practical code examples for each step.

Aotu Lab
Aotu Lab
Aotu Lab
Master Sketch Plugin Development: From Bundle Structure to Advanced UI Panels

Sketch Plugin Structure

A Sketch plugin is a collection of scripts that define one or more commands . It is packaged as a .sketchplugin folder, which is an OS X bundle with a standardized directory hierarchy.

Bundle Folder Layout

mrwalker.sketchplugin
  Contents/
    Sketch/
      manifest.json
      shared.js
      Select Circles.cocoascript
      Select Rectangles.cocoascript
    Resources/
      Screenshot.png
      Icon.png

The manifest.json file is the core metadata descriptor. It defines the plugin name, description, author, version, identifier, compatible Sketch version, commands, and menu items.

{
  "name": "Select Shapes",
  "description": "Plugins to select and deselect shapes",
  "author": "Joe Bloggs",
  "homepage": "https://github.com/example/sketchplugins",
  "version": "1.0",
  "identifier": "com.example.sketch.shape-plugins",
  "compatibleVersion": "3",
  "bundleVersion": 1,
  "commands": [
    {"name": "All", "identifier": "all", "shortcut": "ctrl shift a", "script": "shared.js", "handler": "selectAll"},
    {"name": "Circles", "identifier": "circles", "script": "Select Circles.cocoascript"},
    {"name": "Rectangles", "identifier": "rectangles", "script": "Select Rectangles.cocoascript"}
  ],
  "menu": {"items": ["all", "circles", "rectangles"]}
}

Command Definition

script

: script file implementing the command. handler: function name invoked by Sketch (defaults to onRun if omitted). shortcut: keyboard shortcut. name: label shown in the Plugins menu. identifier: unique reverse‑DNS string (e.g., com.example.myplugin).

Menu Section

Sketch reads the menu array in the manifest to order commands in the Plugins menu.

Sketch Actions API

The Actions API lets plugins listen for user actions such as OpenDocument, CloseDocument, or SelectionChanged. Handlers are declared in manifest.json under a handlers.actions object.

"commands": [
  {
    "script": "my-action-listener.js",
    "name": "My Action Listener",
    "handlers": {"actions": {"OpenDocument": "onOpenDocument"}},
    "identifier": "my-action-listener"
  }
]

Example handler:

export function onOpenDocument(context) {
  context.actionContext.document.showMessage('Document Opened')
}

Sketch JavaScript API

Three development approaches exist:

Pure CocoaScript.

Hybrid JavaScript + CocoaScript.

Objective‑C + AppKit.

Sketch recommends the JavaScript API, which wraps native Sketch objects ( Document, Artboard, Group, Layer) for easier manipulation. Low‑level features may still require CocoaScript or Objective‑C.

CocoaScript

CocoaScript bridges JavaScript to the Objective‑C runtime, allowing calls to macOS frameworks via Apple’s JavaScriptCore engine.

// Objective‑C style
NSString *value = [command valueForKey:kAutoresizingMask onLayer:currentLayer];
// CocoaScript equivalent
const value = command.valueForKey_onLayer(kAutoresizingMask, currentLayer);

// Showing a dialog via NSApplication
const app = NSApplication.sharedApplication();
app.displayDialog_withTitle('Choose a location…', 'Export');

Objective‑C Classes

Sketch’s internal classes (prefixed with MS) are exposed to JavaScript via the Bridge. Introspection methods include properties(), instanceMethods(), and classMethods().

String(context.document.class()) // => "MSDocument"
const mocha = context.document.class().mocha()
mocha.properties() // array of MSDocument properties

Context Object

When a command runs, Sketch passes a context object containing:

command : MSPluginCommand instance.

document : MSDocument instance.

plugin : MSPluginBundle instance.

scriptPath : absolute path of the script.

scriptURL : NSURL of the script.

selection : NSArray of selected MSLayer objects.

Development Setup

Useful defaults for a smoother development cycle:

Disable automatic safe mode after a crash:

defaults write com.bohemiancoding.sketch3 disableAutomaticSafeMode true

Enable script reload on each run:

defaults write com.bohemiancoding.sketch3 AlwaysReloadScript -bool YES

Enable WebView debugging:

defaults write com.bohemiancoding.sketch3 WebKitDeveloperExtras -bool YES

Creating an Auxiliary Panel

Use NSPanel (a subclass of NSWindow) for a floating panel and NSVisualEffectView for a blurred background.

const panelWidth = 80;
const panelHeight = 240;
const panel = NSPanel.alloc().init();
panel.setFrame_display(NSMakeRect(0, 0, panelWidth, panelHeight), true);
panel.setStyleMask(NSTexturedBackgroundWindowMask | NSTitledWindowMask | NSClosableWindowMask | NSFullSizeContentViewWindowMask);
panel.setBackgroundColor(NSColor.whiteColor());
panel.title = "";
panel.titlebarAppearsTransparent = true;
panel.center();
panel.makeKeyAndOrderFront(null);
panel.setLevel(NSFloatingWindowLevel);
COScript.currentCOScript().setShouldKeepAround(true);
panel.standardWindowButton(NSWindowMiniaturizeButton).setHidden(true);
panel.standardWindowButton(NSWindowZoomButton).setHidden(true);

Add a blurred background:

const vibrancy = NSVisualEffectView.alloc().initWithFrame(NSMakeRect(0, 0, panelWidth, panelHeight));
vibrancy.setAppearance(NSAppearance.appearanceNamed(NSAppearanceNameVibrantLight));
vibrancy.setBlendingMode(NSVisualEffectBlendingModeBehindWindow);
panel.contentView().addSubview(vibrancy);

Insert a WKWebView to render HTML content:

const wkwebviewConfig = WKWebViewConfiguration.alloc().init();
const webView = WKWebView.alloc().initWithFrame_configuration(CGRectMake(0, 0, panelWidth, panelWidth), wkwebviewConfig);
panel.contentView().addSubview(webView);
webView.loadFileURL_allowingReadAccessToURL(NSURL.URLWithString(url), NSURL.URLWithString('file:///'));

Sidebar Navigation Development

Typical AppKit classes for a toolbar include NSStackView, NSBox, NSImageView, and NSButton.

const toolbar = NSStackView.alloc().initWithFrame(NSMakeRect(0, 0, 40, 400));
toolbar.identifier = SidePanelIdentifier;
toolbar.setSpacing(8);
toolbar.setFlipped(true);
toolbar.setBackgroundColor(NSColor.windowBackgroundColor());
toolbar.orientation = 1;
// Add logo image view
const Logo = createImageView(NSMakeRect(0, 0, 40, 30), 'logo', NSMakeSize(40, 28));
toolbar.addSubview(Logo);
// Insert toolbar into the main window's stage view
const contentView = context.document.documentWindow().contentView();
const stageView = contentView.subviews().objectAtIndex(0);
const views = stageView.subviews();
// Merge toolbar with existing views (simplified example)
stageView.subviews = views.concat([toolbar]);
stageView.adjustSubviews();

Full source code is available at https://github.com/o2team/sketch-plugin-boilerplate.

Debugging

Sketch creates a JavaScript context for each plugin. Enable Safari’s Web Inspector via

Developer → YourMachine → Automatically Show Web Inspector for JSContexts

and pause on connection to inspect variables and set breakpoints.

Logging

Use console.log or console.error in scripts. Logs can be viewed through:

Console.app (filter for Sketch).

File ~/Library/Logs/com.bohemiancoding.sketch3/Plugin Output.log. skpm log (or skpm log -f for streaming).

If using skpm, install sketch-dev-tools to view logs in the UI.

SketchTool (CLI)

sketchtool

is a command‑line utility bundled with Sketch for exporting artboards, layers, pages, checking documents, dumping JSON data, and running plugins.

alias sketchtool="/Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool"
sketchtool -h                     # show help
sketchtool export artboards path/to/document.sketch   # export artboards
sketchtool dump path/to/document.sketch               # export JSON data
sketchtool metadata path/to/document.sketch         # view metadata
sketchtool run [Plugin path]                       # run a plugin

Note: SketchTool requires macOS 10.11 or later.

JavaScriptpluginSketchskpmAppKitCocoaScript
Aotu Lab
Written by

Aotu Lab

Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.