Authoring Extensions
This guide walks you through creating, testing, and publishing OctoFlow extensions.
Extension Manifest
Every extension starts with a manifest.json file:
{ "id": "my-extension", "name": "My Extension", "description": "A brief description of what this extension does.", "version": "1.0.0", "author": "Your Name", "category": "utilities", "actions": [ { "id": "my-action", "name": "My Action", "type": "javascript", "script": "return text.toUpperCase();", "icon": "arrow-up" } ]}Manifest Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier (lowercase, hyphens) |
name | string | Yes | Display name |
description | string | Yes | Brief description |
version | string | Yes | Semver version |
author | string | Yes | Author name |
category | string | Yes | One of: ai, search, writing, developer, productivity, notes, translation, utilities |
actions | Action[] | Yes | Array of action definitions |
Action Type Reference
URL Action
Opens a URL in the default browser. Use {text} as a placeholder for the selected text (URL-encoded automatically).
{ "type": "url", "url": "https://google.com/search?q={text}"}Shell Action
Runs a shell command. The selected text is passed via stdin.
{ "type": "shell", "command": "wc -w", "shell": "/bin/bash"}AppleScript Action
Executes AppleScript. The variable selectedText is available.
{ "type": "applescript", "script": "tell application \"Notes\" to make new note with properties {body:selectedText}"}JavaScript Action
Runs JavaScript. The variable text contains the selected text. Return a string to replace the selection.
{ "type": "javascript", "script": "return text.split('').reverse().join('');"}Keypress Action
Simulates keyboard shortcuts.
{ "type": "keypress", "key": "c", "modifiers": ["command"]}Shortcut Action
Runs a macOS Shortcuts app shortcut by name. The selected text is passed as input.
{ "type": "shortcut", "shortcutName": "My Shortcut"}AI Prompt Action
Sends the selected text to the configured AI provider with a custom system prompt.
{ "type": "ai-prompt", "systemPrompt": "Summarize the following text in 2-3 sentences:", "model": "default"}Detect Action
Auto-detects content type and suggests relevant actions.
{ "type": "detect", "patterns": [ { "regex": "^https?://", "suggestAction": "open-url" }, { "regex": "@", "suggestAction": "send-email" } ]}The .octoclip Format
A .octoclip file is a single-action extension — just a JSON file with a different extension:
# Create a .octoclip filecp manifest.json my-extension.octoclipUsers can install it by double-clicking or dragging it onto the OctoFlow icon.
The .octoext Format
A .octoext file is a directory bundle for multi-action extensions:
my-extension.octoext/ manifest.json scripts/ action1.js action2.applescript icon.pngTesting
- Place your extension in
~/Library/Application Support/OctoFlow/Extensions/ - Reload extensions: menu bar icon > Reload Extensions
- Select some text and verify your action appears in the toolbar
Publishing
To publish your extension to the OctoFlow Extensions Directory:
- Create a GitHub repository for your extension
- Tag a release with the version number (e.g.,
v1.0.0) - Attach the
.octoclipor.octoextfile as a release asset - Submit a PR to octoflow/extensions-registry adding your extension’s metadata
Registry Entry Format
{ "id": "my-extension", "name": "My Extension", "description": "What it does", "category": "utilities", "actionType": "javascript", "author": "Your Name", "version": "1.0.0", "isFree": true, "installUrl": "https://github.com/you/my-extension/releases/download/v1.0.0/my-extension.octoclip", "sourceUrl": "https://github.com/you/my-extension", "tags": ["text", "utility"]}Your extension will be reviewed for security and quality, then published to the directory.