Live OmniFocus access via native Omni Automation — tasks, projects, inbox, tags. Use for ANY OmniFocus query: 'show my tasks', 'what's in my inbox', 'omnifoc...
---
name: omnifocus4
description: "Live OmniFocus access via native Omni Automation — tasks, projects, inbox, tags. Use for ANY OmniFocus query: 'show my tasks', 'what's in my inbox', 'omnifocus summary', 'what's due today', 'flagged items', 'add a task', 'complete a task', 'search omnifocus', 'show my projects', 'GTD review'. Always run a command to get live data — never answer from memory."
---
# OmniFocus
**IMPORTANT:** OmniFocus data is live. When asked anything about tasks, projects, inbox, flagged items, due dates, or reviews — RUN A COMMAND. Do not answer from memory, do not say you cannot access OmniFocus, do not ask clarifying questions. Just run the appropriate command below and return the result.
## How to invoke
Call `of` directly with the **Bash tool**. Do **not** wrap in AppleScript `do shell script "..."` and do **not** route through `mcp__Control_your_Mac__osascript` — the script handles the AppleScript → Omni Automation bridge internally.
- **Local Claude Code (macOS)**: the sandbox blocks inter-process AppleScript. Pass `dangerouslyDisableSandbox: true` on every Bash call. An error like `-600 "Application isn't running"` is a sandbox symptom, not a real OmniFocus state.
- **Cowork / remote / other environments**: just call Bash. If the host has no access to a running OmniFocus, commands will fail with a real connection error — report that to the user rather than retrying with AppleScript wrappers.
| User asks about… | Command to run |
|------------------|----------------|
| summary / overview / stats | `.claude/skills/omnifocus4/scripts/of summary` |
| inbox | `.claude/skills/omnifocus4/scripts/of inbox` |
| today / overdue / due | `.claude/skills/omnifocus4/scripts/of today` |
| flagged tasks | `.claude/skills/omnifocus4/scripts/of flagged` |
| what to do / available tasks | `.claude/skills/omnifocus4/scripts/of available 10` |
| projects | `.claude/skills/omnifocus4/scripts/of projects` |
| search for something | `.claude/skills/omnifocus4/scripts/of search "query"` |
Control OmniFocus via Omni Automation JS, called from a Python wrapper.
## Requirements
- macOS with OmniFocus 3 or 4 installed
- OmniFocus must be running (or will auto-launch)
- Python 3 (system Python is fine)
## Quick Reference
```bash
.claude/skills/omnifocus4/scripts/of <command> [args...]
```
All commands return JSON to stdout. Errors print `{"error": "..."}` and exit 1.
## Commands
### Read
| Command | Args | Description |
|---------|------|-------------|
| `inbox` | | List inbox tasks |
| `folders` | | List all folders |
| `projects` | `[folder] [--all]` | List active projects (default); `--all` includes on-hold, dropped, completed |
| `tasks` | `<project>` | List tasks in a project |
| `tags` | `[--all]` | List tags with available tasks (default); `--all` includes empty tags |
| `today` | | Tasks due today or overdue |
| `flagged` | | Flagged incomplete tasks |
| `search` | `<query>` | Search tasks by name or note |
| `info` | `<taskId>` | Full task details by ID |
| `summary` | | Database counts (projects, tasks, flagged, due, available, inbox) |
| `project-tree` | `<name> [limit]` | Recursive subtask tree with depth |
| `project-search` | `<term> [limit]` | Find projects by partial name |
| `folder` | `<name> [limit]` | Detail a folder: child folders + projects (default limit 50 — use a higher limit for large folders) |
| `root` | `[limit]` | Top-level folders and unfiled projects |
| `tag-summary` | `<name> [limit]` | Tasks for a tag, grouped by folder/project |
| `tag-family` | `<name> [limit]` | Tasks across a tag and all its children |
| `available` | `[limit]` | All available (actionable) tasks |
| `review` | `[limit] [--all]` | Active projects with task counts (default); `--all` includes all statuses |
### Create
| Command | Args | Description |
|---------|------|-------------|
| `add` | `<name> [project]` | Add task to inbox or project |
| `newproject` | `<name> [folder]` | Create project |
| `newfolder` | `<name>` | Create top-level folder |
| `newtag` | `<name>` | Create or get tag |
### Modify
| Command | Args | Description |
|---------|------|-------------|
| `complete` | `<taskId>` | Mark complete |
| `uncomplete` | `<taskId>` | Mark incomplete |
| `delete` | `<taskId>` | Permanently delete |
| `rename` | `<taskId> <name>` | Rename task |
| `note` | `<taskId> <text>` | Append to note |
| `setnote` | `<taskId> <text>` | Replace note |
| `defer` | `<taskId> <date>` | Set defer date (YYYY-MM-DD) |
| `due` | `<taskId> <date>` | Set due date (YYYY-MM-DD) |
| `flag` | `<taskId> [true\|false]` | Set flagged (default true) |
| `tag` | `<taskId> <tag>` | Add tag (creates if needed) |
| `untag` | `<taskId> <tag>` | Remove tag |
| `move` | `<taskId> <project>` | Move to project |
### Repeat
```bash
# repeat <taskId> <method> <interval> <unit>
.claude/skills/omnifocus4/scripts/of repeat abc123 fixed 1 weeks
.claude/skills/omnifocus4/scripts/of repeat abc123 due-after-completion 2 days
.claude/skills/omnifocus4/scripts/of repeat abc123 defer-after-completion 1 months
.claude/skills/omnifocus4/scripts/of unrepeat abc123
```
Methods: `fixed`, `due-after-completion`, `defer-after-completion`
Units: `days`, `weeks`, `months`, `years`
## Output Format
All commands return JSON. Task records include:
```json
{
"id": "abc123",
"name": "Task name",
"note": "Notes here",
"flagged": false,
"completed": false,
"available": true,
"deferDate": "2026-04-01",
"dueDate": "2026-04-10",
"effectiveDueDate": "2026-04-10",
"completionDate": null,
"estimatedMinutes": 30,
"project": "Project Name",
"folder": "Folder Name",
"tags": ["tag1", "tag2"],
"repeat": {"method": "fixed", "recurrence": "FREQ=WEEKLY;INTERVAL=1"}
}
```
Write commands return `{"success": true, "task": {...}}`.
## Examples
```bash
# Add task to inbox
.claude/skills/omnifocus4/scripts/of add "Buy groceries"
# Add task to specific project
.claude/skills/omnifocus4/scripts/of add "Review docs" "Work Projects"
# Get today's tasks
.claude/skills/omnifocus4/scripts/of today
# Search name and notes
.claude/skills/omnifocus4/scripts/of search "quarterly report"
# Set due date and flag
.claude/skills/omnifocus4/scripts/of due abc123 2026-04-10
.claude/skills/omnifocus4/scripts/of flag abc123 true
# Add tags
.claude/skills/omnifocus4/scripts/of tag abc123 "urgent"
# Create recurring task
.claude/skills/omnifocus4/scripts/of add "Weekly review" "Habits"
.claude/skills/omnifocus4/scripts/of repeat xyz789 fixed 1 weeks
# Hierarchical views
.claude/skills/omnifocus4/scripts/of summary
.claude/skills/omnifocus4/scripts/of root
.claude/skills/omnifocus4/scripts/of folder "Personal"
.claude/skills/omnifocus4/scripts/of project-tree "Work" 50
.claude/skills/omnifocus4/scripts/of tag-family "review"
```
## Performance
OmniJS loads all task objects on first access (~5-7 s for large databases).
Commands are grouped by expected latency:
**Fast (<1 s):** `inbox`, `folders`, `root`, `folder`, `projects`, `project-search`,
`project-tree`, `tags`, `tag-summary`, `tag-family`
**Medium (4-6 s):** `summary`, `flagged`, `today`, `search`, `available`, `review`
Prefer fast structural commands for navigation. Use medium commands only when
task-level data is actually needed — and batch related queries when possible
(e.g. ask for `flagged` once rather than `flagged` + `available` separately).
## Technical Details
Uses Omni Automation JS evaluated inside OmniFocus via AppleScript
`evaluate javascript`. This is more reliable than JXA for OmniFocus-specific
APIs — no cross-process type-conversion bugs.
Key implementation patterns:
- `filter()` not `byName()` — `byName()` returns an ObjectSpecifier proxy
whose child collections fail to enumerate
- `asArray()` helper — `Array.isArray()` returns false for OmniJS collection types
- `safe()` wrapper — prevents crashes on null/undefined properties
- `id.primaryKey` — stable canonical ID in Omni Automation
- `effectiveDueDate` — respects project-cascaded due dates
- Dates output as ISO 8601 YYYY-MM-DD via `Date.toISOString()`
- `isAvailableApprox` — fast approximation: not completed + not deferred to future
- `listTaskRecord` / `listProjectRecord` — slim records for bulk list commands
**First run:** OmniFocus may prompt to allow automation access. Enable in
System Settings > Privacy & Security > Automation.
## Notes
- Task IDs are OmniFocus internal primary keys (returned in all task responses)
- Dates use ISO 8601: YYYY-MM-DD
- Project and tag names are case-sensitive
- Tags are created automatically when using `tag` command
- `isAvailableApprox` respects defer dates but not sequential project ordering
don't have the plugin yet? install it then click "run inline in claude" again.
restructured into six required components with explicit decision points for sandbox/network errors, added edge case handling for empty results and timeouts, formalized output contract with task record schema, and clarified execution context for local vs remote environments.
this skill gives you live read/write access to OmniFocus 3 or 4 via native Omni Automation. use it for any question about tasks, projects, inbox state, tags, due dates, or flags. never answer from cached knowledge. run the appropriate command and return real data. covers full GTD workflows: inbox processing, project views, tag hierarchies, searching, task creation, completion, scheduling, and recurrence setup.
OmniFocus environment:
execution context:
dangerouslyDisableSandbox: true on every bash call. the sandbox blocks inter-process AppleScript. errors like -600 "Application isn't running" signal sandbox, not real OmniFocus state.command invocation:
call .claude/skills/omnifocus4/scripts/of directly via bash tool only. do not wrap in AppleScript do shell script or route through mcp__Control_your_Mac__osascript. the script handles the AppleScript to Omni Automation bridge internally.
all commands run via bash and return JSON to stdout. errors return {"error": "..."} with exit code 1.
inbox , call .claude/skills/omnifocus4/scripts/of inbox
today / overdue / due , call .claude/skills/omnifocus4/scripts/of today
flagged , call .claude/skills/omnifocus4/scripts/of flagged
available tasks , call .claude/skills/omnifocus4/scripts/of available [limit]
summary , call .claude/skills/omnifocus4/scripts/of summary
search , call .claude/skills/omnifocus4/scripts/of search "query"
projects , call .claude/skills/omnifocus4/scripts/of projects [folder] [--all]
--all flag (default: active projects only)folders , call .claude/skills/omnifocus4/scripts/of folders
root , call .claude/skills/omnifocus4/scripts/of root [limit]
folder details , call .claude/skills/omnifocus4/scripts/of folder "name" [limit]
project tree , call .claude/skills/omnifocus4/scripts/of project-tree "name" [limit]
project search , call .claude/skills/omnifocus4/scripts/of project-search "term" [limit]
tags , call .claude/skills/omnifocus4/scripts/of tags [--all]
--all flag (default: tags with available tasks only)tag summary , call .claude/skills/omnifocus4/scripts/of tag-summary "name" [limit]
tag family , call .claude/skills/omnifocus4/scripts/of tag-family "name" [limit]
task info , call .claude/skills/omnifocus4/scripts/of info "taskId"
review , call .claude/skills/omnifocus4/scripts/of review [limit] [--all]
--all (default: active projects only)add task , call .claude/skills/omnifocus4/scripts/of add "name" [project]
{"success": true, "task": {...}}complete task , call .claude/skills/omnifocus4/scripts/of complete "taskId"
{"success": true, "task": {...}}uncomplete task , call .claude/skills/omnifocus4/scripts/of uncomplete "taskId"
{"success": true, "task": {...}}delete task , call .claude/skills/omnifocus4/scripts/of delete "taskId"
{"success": true}rename task , call .claude/skills/omnifocus4/scripts/of rename "taskId" "newname"
{"success": true, "task": {...}}set note , call .claude/skills/omnifocus4/scripts/of setnote "taskId" "text"
{"success": true, "task": {...}}append note , call .claude/skills/omnifocus4/scripts/of note "taskId" "text"
{"success": true, "task": {...}}set due date , call .claude/skills/omnifocus4/scripts/of due "taskId" "YYYY-MM-DD"
{"success": true, "task": {...}}set defer date , call .claude/skills/omnifocus4/scripts/of defer "taskId" "YYYY-MM-DD"
{"success": true, "task": {...}}set flag , call .claude/skills/omnifocus4/scripts/of flag "taskId" [true|false]
{"success": true, "task": {...}}add tag , call .claude/skills/omnifocus4/scripts/of tag "taskId" "tagname"
{"success": true, "task": {...}}remove tag , call .claude/skills/omnifocus4/scripts/of untag "taskId" "tagname"
{"success": true, "task": {...}}move task , call .claude/skills/omnifocus4/scripts/of move "taskId" "projectname"
{"success": true, "task": {...}}create project , call .claude/skills/omnifocus4/scripts/of newproject "name" [folder]
{"success": true, "task": {...}}create folder , call .claude/skills/omnifocus4/scripts/of newfolder "name"
{"success": true, "task": {...}}create/get tag , call .claude/skills/omnifocus4/scripts/of newtag "name"
{"success": true, "task": {...}}set repeat , call .claude/skills/omnifocus4/scripts/of repeat "taskId" "method" "interval" "unit"
fixed, due-after-completion, defer-after-completion), interval (integer), unit (days, weeks, months, years){"success": true, "task": {...}}remove repeat , call .claude/skills/omnifocus4/scripts/of unrepeat "taskId"
{"success": true, "task": {...}}search command for broad name/note matching, or project-tree / tag-family for hierarchical navigation.available [limit] to show actionable tasks.{"error": "..."} on macOS local Claude Code: check if sandbox is enabled. pass dangerouslyDisableSandbox: true on bash call. if error persists, report to user.add). for move/project operations, require explicit target or ask user.all commands return JSON:
{"success": true, "task": {...}} or {"success": true} (delete only){"error": "message"} with exit code 1task record structure:
{
"id": "abc123",
"name": "Task name",
"note": "Notes here",
"flagged": false,
"completed": false,
"available": true,
"deferDate": "2026-04-01",
"dueDate": "2026-04-10",
"effectiveDueDate": "2026-04-10",
"completionDate": null,
"estimatedMinutes": 30,
"project": "Project Name",
"folder": "Folder Name",
"tags": ["tag1", "tag2"],
"repeat": {"method": "fixed", "recurrence": "FREQ=WEEKLY;INTERVAL=1"}
}
dates are ISO 8601 (YYYY-MM-DD). null values mean unset. effectiveDueDate respects project cascading. available is true if not completed and not deferred to future (ignores sequential ordering).
of inbox and display tasks. user sees their real inbox state.of complete taskId and return confirmation with updated task. user sees completion marked in output.of today and list overdue and due tasks. user gets sorted list by due date.of add "name" [project] and return success with new task ID. user can immediately reference task by ID for further edits.of search "X" and return matches. user sees name and note context.of projects and return project list. user sees active/all project status based on flag.dangerouslyDisableSandbox: true.