A command-line interface for OmniFocus, built with Bun. Zero external dependencies.
- macOS (OmniFocus is macOS-only)
- Bun runtime
- OmniFocus 4+ with Omni Automation enabled
# Clone the repository
git clone <repo-url>
cd tools_for_omnifocus
# Run directly with Bun
bun run omnifocus <command>
# Or compile to a single binary
bun build omnifocus.ts --compile --outfile omnifocus
./omnifocus <command>Bun can compile the CLI to a standalone executable:
# Basic compilation
bun build omnifocus.ts --compile --outfile omnifocus
# With minification (smaller binary)
bun build omnifocus.ts --compile --minify --outfile omnifocus
# Install globally (optional)
sudo mv omnifocus /usr/local/bin/The compiled binary (~52MB) includes the Bun runtime and all dependencies, so it can run on any macOS machine without Bun installed.
These options are available on all commands:
| Option | Short | Description |
|---|---|---|
--help |
-h |
Show help for the command |
Get tasks from the OmniFocus inbox.
omnifocus inbox
omnifocus inbox --format json
omnifocus inbox --format nushell
omnifocus inbox --include-completed| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--include-completed |
Include completed tasks |
Get flagged tasks.
omnifocus flagged
omnifocus flagged --format json
omnifocus flagged --project "Work"
omnifocus flagged --include-completed| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--project <name> |
-p |
Filter by project name |
--include-completed |
Include completed tasks |
Get forecast tasks (due/deferred in upcoming days).
omnifocus forecast
omnifocus forecast --days 14
omnifocus forecast --format json
omnifocus forecast --deferred-only| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--days <n> |
-d |
Number of days to look ahead (default: 7) |
--include-completed |
Include completed tasks | |
--deferred-only |
Only show deferred tasks |
Get today's completed tasks.
omnifocus completed
omnifocus completed --limit 50
omnifocus completed --format json| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--limit <n> |
-l |
Limit number of tasks (default: 20) |
Get a specific task by ID or name. Returns full task details including dates, flags, and hierarchy.
omnifocus get "Task Name"
omnifocus get --id "abc123"
omnifocus get --name "Task Name"
omnifocus get --id "abc123" --format json| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--id <id> |
Task ID | |
--name <name> |
Task name |
Returns: id, name, note, dueDate, deferDate, flagged, estimatedMinutes, parentId, parentName, projectId, projectName, hasChildren, childrenCount
Get tasks by tag.
omnifocus tag "work"
omnifocus tag "home" --exact
omnifocus tag "errands" --format json
omnifocus tag "waiting" --include-completed| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--exact |
Exact match only (default: partial match) | |
--include-completed |
Include completed tasks |
Get tasks from a custom perspective.
omnifocus perspective "Today"
omnifocus perspective "Weekly Review" --format json
omnifocus perspective "Errands" --limit 10
omnifocus perspective "Projects" --hierarchy| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--include-completed |
Include completed tasks | |
--limit <n> |
-l |
Limit number of tasks |
--hierarchy |
Show task hierarchy |
List all custom perspectives.
omnifocus perspectives
omnifocus perspectives --format detailed| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: simple, detailed (default: simple) |
Advanced task filtering with multiple criteria.
omnifocus filter --flagged
omnifocus filter --project "Work" --tag "urgent"
omnifocus filter --search "meeting"
omnifocus filter --completed-today --format json
omnifocus filter --perspective inbox --limit 10| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
|
--perspective <type> |
Filter by perspective: inbox, flagged, all |
|
--project <name> |
-p |
Filter by project name |
--tag <name> |
-t |
Filter by tag name |
--search <text> |
-s |
Search in name/note |
--flagged |
Only flagged tasks | |
--not-flagged |
Only non-flagged tasks | |
--status <status> |
Filter by status: Available, Blocked, Next, DueSoon, Completed, Dropped (can use multiple times) |
|
--completed-today |
Tasks completed today | |
--completed-yesterday |
Tasks completed yesterday | |
--completed-this-week |
Tasks completed this week | |
--limit <n> |
-l |
Limit results |
--sort <field> |
Sort by field: name, completedDate |
|
--desc |
Sort descending |
Add a new task to OmniFocus.
omnifocus add task "Buy groceries"
omnifocus add task "Call dentist" --note "Ask about appointment"
omnifocus add task "Review PR" --project "Work" --flagged
omnifocus add task "Subtask" --parent-name "Parent Task"
omnifocus add task "Tagged task" --tag "urgent" --tag "work"
omnifocus add task "Submit report" --due-date "2026-01-31" --defer-date "2026-01-15"
omnifocus add task "Meeting prep" --due-date "2026-01-25T14:30" # With specific time| Option | Short | Description |
|---|---|---|
--note <text> |
-n |
Add a note to the task |
--project <name> |
-p |
Add task to a specific project |
--parent-id <id> |
Create as subtask of task with ID | |
--parent-name <name> |
Create as subtask of task with name | |
--flagged |
Flag the task | |
--estimate <min> |
-e |
Set estimated minutes |
--tag <name> |
-t |
Add a tag (can use multiple times) |
--due-date <datetime> |
Set due date/time (see Date/Time Formats) | |
--defer-date <datetime> |
Set defer date/time (see Date/Time Formats) |
Add a new project to OmniFocus.
omnifocus add project "New Website"
omnifocus add project "Home Renovation" --folder "Personal"
omnifocus add project "Q4 Goals" --sequential --flagged
omnifocus add project "Research" --note "Background research" --tag "work"
omnifocus add project "Tax Filing" --due-date "2026-04-15"| Option | Short | Description |
|---|---|---|
--note <text> |
-n |
Add a note to the project |
--folder <name> |
Add project to a specific folder | |
--flagged |
Flag the project | |
--sequential |
Make tasks sequential | |
--estimate <min> |
-e |
Set estimated minutes |
--tag <name> |
-t |
Add a tag (can use multiple times) |
--due-date <datetime> |
Set due date/time (see Date/Time Formats) | |
--defer-date <datetime> |
Set defer date/time (see Date/Time Formats) |
Edit a task or project.
omnifocus edit --type task --name "Old Name" --new-name "New Name"
omnifocus edit --type task --id "abc123" --flagged
omnifocus edit --type task --name "Task" --complete
omnifocus edit --type project --name "Project" --sequential
omnifocus edit --type task --name "Task" --add-tag "urgent" --remove-tag "later"| Option | Short | Description |
|---|---|---|
--type <type> |
Type: task or project (required) |
|
--id <id> |
ID of the item to edit | |
--name <name> |
Name of the item to edit | |
--new-name <name> |
Set new name | |
--new-note <text> |
Set new note | |
--flagged |
Flag the item | |
--unflagged |
Unflag the item | |
--estimate <min> |
-e |
Set estimated minutes |
--complete |
Mark as completed | |
--drop |
Mark as dropped | |
--incomplete |
Mark as incomplete | |
--add-tag <name> |
Add a tag (can use multiple times) | |
--remove-tag <name> |
Remove a tag (can use multiple times) | |
--sequential |
Make project sequential | |
--parallel |
Make project parallel |
Remove a task or project.
omnifocus remove --type task --id "abc123"
omnifocus remove --type task --name "Task to Delete"
omnifocus remove --type project --name "Old Project"| Option | Short | Description |
|---|---|---|
--type <type> |
Type: task or project (required) |
|
--id <id> |
ID of the item to remove | |
--name <name> |
Name of the item to remove |
Batch add tasks and projects from a JSON file.
omnifocus batch add items.jsonJSON format:
[
{
"type": "task",
"name": "Task 1",
"note": "Optional note",
"projectName": "Project",
"flagged": true,
"tags": ["tag1", "tag2"]
},
{
"type": "project",
"name": "New Project",
"folderName": "Folder",
"sequential": true
}
]Task properties: type, name, note, dueDate, deferDate, flagged, estimatedMinutes, tags, projectName, parentTaskId, parentTaskName
Project properties: type, name, note, dueDate, deferDate, flagged, estimatedMinutes, tags, folderName, sequential
Note: Use ISO 8601 format for dates (e.g., "2026-01-25" or "2026-01-25T14:30"). See Date/Time Formats.
Batch remove tasks and projects from a JSON file.
omnifocus batch remove items.jsonJSON format:
[
{ "itemType": "task", "id": "abc123" },
{ "itemType": "project", "name": "Project to Delete" }
]Dump the entire OmniFocus database.
omnifocus dump
omnifocus dump --format json > database.json
omnifocus dump --format nushell | from json| Option | Short | Description |
|---|---|---|
--format <format> |
-f |
Output format: text, json, nushell (default: text) |
--nushell |
Shorthand for --format nushell |
All query commands support three output formats:
- text (default): Human-readable formatted output
- json: Structured JSON for programmatic use
- nushell: Flattened JSON array optimized for Nushell pipelines
You can specify the format with --format <format> or -f <format>. For nushell output, you can also use the shorthand --nushell flag.
Example with Nushell:
omnifocus inbox --nushell | from json | where flagged == true | select name project
# Or equivalently:
omnifocus inbox --format nushell | from json | where flagged == true | select name projectThe CLI uses ISO 8601 format for all date and time inputs. This provides unambiguous, locale-independent date handling.
| Format | Example | Description |
|---|---|---|
YYYY-MM-DD |
2026-01-25 |
Date only (time defaults to midnight) |
YYYY-MM-DDTHH:MM |
2026-01-25T14:30 |
Date with time (24-hour format) |
YYYY-MM-DDTHH:MM:SS |
2026-01-25T14:30:00 |
Date with time and seconds |
# Date only - due at midnight
omnifocus add task "Submit report" --due-date "2026-01-31"
# Date with specific time
omnifocus add task "Team meeting" --due-date "2026-01-25T14:30"
# Defer until morning, due in evening
omnifocus add task "Daily review" --defer-date "2026-01-25T09:00" --due-date "2026-01-25T17:00"When retrieving tasks with omnifocus get, dates are returned in ISO 8601 format:
$ omnifocus get --id "abc123"
# Task: Team meeting
#
# - ID: abc123
# - Due: 2026-01-25T14:30
# - Defer: 2026-01-25T09:00
# - Has Children: false (0)JSON output includes dueDate and deferDate fields:
{
"success": true,
"task": {
"id": "abc123",
"name": "Team meeting",
"dueDate": "2026-01-25T14:30",
"deferDate": "2026-01-25T09:00",
"flagged": false,
"estimatedMinutes": 0
}
}On first run, macOS will prompt for automation permissions. Grant OmniFocus automation access in:
System Settings → Privacy & Security → Automation
The project includes comprehensive tests using bun:test. Tests are co-located with source files.
# Run all tests
bun test
# Run specific test file
bun test omnifocus/operations/addTask.test.ts
# Run tests matching a pattern
bun test --grep "formatDate"
# Watch mode (re-run on changes)
bun test --watch| Area | Test File | Description |
|---|---|---|
| Argument parsing | cli/arg_parser.test.ts |
CLI argument parsing and option extraction |
| Command handlers | cli/commands.test.ts |
Format selection and command routing |
| Add task | omnifocus/operations/addTask.test.ts |
Task creation, dates, tags |
| Add project | omnifocus/operations/addProject.test.ts |
Project creation, dates, folders |
| Edit item | omnifocus/operations/editItem.test.ts |
Task/project editing, completion |
| Filter tasks | omnifocus/operations/filterTasks.test.ts |
Task filtering and formatting |
| Batch add | omnifocus/operations/batchAddItems.test.ts |
Batch add JSON format |
| Batch remove | omnifocus/operations/batchRemoveItems.test.ts |
Batch remove JSON format |
| Script execution | omnifocus/utils/scriptExecution.test.ts |
AppleScript parameter injection |
| Filter script | omnifocus/utils/omnifocusScripts/filterTasks.test.ts |
Filter script structure |
omnifocus-cli/
├── omnifocus.ts # Main CLI entry point
├── cli/
│ ├── arg_parser.ts # Argument parser
│ ├── arg_parser.test.ts # Argument parser tests
│ ├── commands.ts # Command handlers
│ ├── commands.test.ts # Command handler tests
│ └── help.ts # Help text
├── omnifocus/
│ ├── operations/ # Core OmniFocus operations
│ │ ├── addTask.ts
│ │ ├── addTask.test.ts
│ │ ├── addProject.ts
│ │ ├── addProject.test.ts
│ │ ├── editItem.ts
│ │ ├── editItem.test.ts
│ │ ├── removeItem.ts
│ │ ├── batchAddItems.ts
│ │ ├── batchAddItems.test.ts
│ │ ├── batchRemoveItems.ts
│ │ ├── batchRemoveItems.test.ts
│ │ ├── filterTasks.ts
│ │ ├── filterTasks.test.ts
│ │ └── ... # Other operations
│ └── utils/
│ ├── scriptExecution.ts
│ ├── scriptExecution.test.ts
│ └── omnifocusScripts/
│ ├── filterTasks.js
│ └── filterTasks.test.ts
├── CONTRIBUTING.md # Contribution guidelines
└── package.json
We welcome contributions! Please see CONTRIBUTING.md for guidelines, including:
- Development setup and running tests
- Code style and commit message format
- How to pair with Claude for AI-assisted development
- Guidance for AI assistants on testing with tmux
MIT