This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A CLI tool for OmniFocus on macOS that uses JavaScript for Automation (JXA) to interact with OmniFocus via AppleScript. The CLI provides gh-style commands for managing tasks, projects, inbox, perspectives, and search.
bun install # Install dependencies
bun run build # Build TypeScript to dist/
bun run dev # Watch mode for development
bun link # Link binary for local testing (creates `of` command)After bun link, use of command globally:
of task list # List tasks
of project list # List projects
of inbox count # Get inbox countThe OmniFocus class is the central integration point:
- JXA Execution: Writes JavaScript to temp files and executes via
osascript -l JavaScript - Omni Automation API: Uses OmniFocus's Omni Automation JavaScript API (formerly JXA)
- Helper Functions:
OMNI_HELPERSconstant contains reusable JXA functions for serialization, finding objects, and tag management - Script Wrapping:
wrapOmniScript()wraps Omni Automation code in the required Application boilerplate - Filter Building: Dynamic filter generation for tasks and projects via
buildTaskFilters()andbuildProjectFilters()
Commands follow Commander.js patterns:
- Each command module exports a
createXCommand()function returning a configured Command - Commands use
executeOmniFocusCommand()helper that handles spinner, OmniFocus instance, and error handling - All commands output JSON for machine-readable automation
Files:
src/cli.ts- Main entry point, registers all commandssrc/commands/task.ts- Task CRUD operationssrc/commands/project.ts- Project CRUD operationssrc/commands/inbox.ts- Inbox list/countsrc/commands/perspective.ts- Perspective switching and viewingsrc/commands/search.ts- Task searchsrc/commands/tag.ts- Tag management and statistics
Core types in src/types.ts:
Task- Includes id, name, completed, flagged, project, tags, defer/due dates, estimatesProject- Status (active/on hold/dropped), folder, sequential flag, task counts- Filter interfaces for tasks and projects
- Create/update option interfaces
src/types/omniautomation.d.ts provides TypeScript definitions for OmniFocus's JavaScript API objects like Task, Project, Folder, Tag, Perspective.
- Build JavaScript string with embedded helper functions
- Use
escapeString()for all user input to prevent injection - Wrap in
wrapOmniScript()to add Application boilerplate - Write to temp file, execute via osascript, clean up temp file
- Parse JSON output from serialized OmniFocus objects
Commands use withErrorHandling() HOF which:
- Catches errors and outputs JSON error objects to stdout
- Calls
process.exit(1)on failure - Error format:
{"error": {"name": "...", "detail": "...", "statusCode": ...}} - OmniFocus API errors (like "Task not found") bubble up from JXA execution
getPerspectiveTasks() requires an OmniFocus window to be open because it:
- Switches window to the specified perspective
- Traverses the visible content tree
- Collects Task objects from the tree nodes
- Uses 60s timeout (longer than default 30s) due to perspective switching delay
- macOS Only: Uses osascript which is macOS-specific
- OmniFocus Required: Must have OmniFocus installed and running
- Window Requirement: Perspective viewing requires an OmniFocus window to be open
- Permissions: First run requires granting Automation permissions in System Settings
- ESM Modules: Uses ES modules (type: "module" in package.json), all imports need .js extensions
- Accept ISO format strings:
YYYY-MM-DDor full ISO like2024-01-15T10:00:00 - Store and output as ISO strings in Task objects
- Client applications can parse and format dates as needed
Both findTask() and findProject() JXA helpers accept:
- Primary key ID (e.g., "kXu3B-LZfFH")
- Exact name match
Commands use "idOrName" pattern for flexible lookups.