@stephendolan/omnifocus-cli 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -11
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@stephendolan/omnifocus-cli)
|
|
4
4
|
[](https://www.npmjs.com/package/@stephendolan/omnifocus-cli)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
[](https://bun.sh)
|
|
7
7
|
[](https://www.apple.com/macos/)
|
|
8
8
|
|
|
9
9
|
A powerful command-line interface for OmniFocus on macOS, inspired by the GitHub CLI (`gh`).
|
|
@@ -20,12 +20,15 @@ A powerful command-line interface for OmniFocus on macOS, inspired by the GitHub
|
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
23
|
+
Requires [Bun](https://bun.sh) runtime.
|
|
24
|
+
|
|
23
25
|
```bash
|
|
24
|
-
# Install globally
|
|
25
|
-
|
|
26
|
+
# Install globally with bun (recommended)
|
|
27
|
+
bun install -g @stephendolan/omnifocus-cli
|
|
26
28
|
|
|
27
29
|
# Or run directly without installing
|
|
28
|
-
|
|
30
|
+
bunx @stephendolan/omnifocus-cli task list
|
|
31
|
+
npx @stephendolan/omnifocus-cli task list # also works
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
### From Source
|
|
@@ -33,8 +36,8 @@ npx @stephendolan/omnifocus-cli task list
|
|
|
33
36
|
```bash
|
|
34
37
|
git clone https://github.com/stephendolan/omnifocus-cli.git
|
|
35
38
|
cd omnifocus-cli
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
bun install
|
|
40
|
+
bun run link # Build and link globally
|
|
38
41
|
```
|
|
39
42
|
|
|
40
43
|
Now you can use the `of` command anywhere in your terminal.
|
|
@@ -450,7 +453,7 @@ of tag delete "Obsolete Tag"
|
|
|
450
453
|
|
|
451
454
|
- macOS (OmniFocus is Mac-only)
|
|
452
455
|
- OmniFocus installed and running
|
|
453
|
-
-
|
|
456
|
+
- [Bun](https://bun.sh) 1.0+
|
|
454
457
|
|
|
455
458
|
## How It Works
|
|
456
459
|
|
|
@@ -460,16 +463,16 @@ The CLI uses JavaScript for Automation (JXA) to communicate directly with OmniFo
|
|
|
460
463
|
|
|
461
464
|
```bash
|
|
462
465
|
# Install dependencies
|
|
463
|
-
|
|
466
|
+
bun install
|
|
464
467
|
|
|
465
468
|
# Build TypeScript
|
|
466
|
-
|
|
469
|
+
bun run build
|
|
467
470
|
|
|
468
471
|
# Watch mode for development
|
|
469
|
-
|
|
472
|
+
bun run dev
|
|
470
473
|
|
|
471
474
|
# Link for local testing
|
|
472
|
-
|
|
475
|
+
bun link
|
|
473
476
|
```
|
|
474
477
|
|
|
475
478
|
## Troubleshooting
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command as Command8 } from "commander";
|
|
@@ -1294,7 +1294,7 @@ function createFolderCommand() {
|
|
|
1294
1294
|
|
|
1295
1295
|
// src/index.ts
|
|
1296
1296
|
var program = new Command8();
|
|
1297
|
-
program.name("of").description("A command-line interface for OmniFocus on macOS").version("
|
|
1297
|
+
program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.0.0").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
|
|
1298
1298
|
const options = thisCommand.opts();
|
|
1299
1299
|
setOutputOptions({
|
|
1300
1300
|
compact: options.compact
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/output.ts","../src/commands/task.ts","../src/lib/command-utils.ts","../src/lib/omnifocus.ts","../src/commands/project.ts","../src/commands/inbox.ts","../src/commands/search.ts","../src/commands/perspective.ts","../src/commands/tag.ts","../src/commands/folder.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { setOutputOptions } from './lib/output.js';\nimport { createTaskCommand } from './commands/task.js';\nimport { createProjectCommand } from './commands/project.js';\nimport { createInboxCommand } from './commands/inbox.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createPerspectiveCommand } from './commands/perspective.js';\nimport { createTagCommand } from './commands/tag.js';\nimport { createFolderCommand } from './commands/folder.js';\n\nconst program = new Command();\n\nprogram\n .name('of')\n .description('A command-line interface for OmniFocus on macOS')\n .version(__VERSION__)\n .option('-c, --compact', 'Minified JSON output (single line)')\n .hook('preAction', (thisCommand) => {\n const options = thisCommand.opts();\n setOutputOptions({\n compact: options.compact,\n });\n });\n\nprogram.addCommand(createTaskCommand());\nprogram.addCommand(createProjectCommand());\nprogram.addCommand(createInboxCommand());\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createPerspectiveCommand());\nprogram.addCommand(createTagCommand());\nprogram.addCommand(createFolderCommand());\n\nprogram.parseAsync().catch(() => {\n process.exit(1);\n});\n","export interface OutputOptions {\n compact?: boolean;\n}\n\nlet globalOutputOptions: OutputOptions = {};\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOutputOptions = options;\n}\n\nexport function outputJson(data: unknown, options: OutputOptions = {}): void {\n const mergedOptions = { ...globalOutputOptions, ...options };\n const jsonString = mergedOptions.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);\n\n console.log(jsonString);\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { TaskFilters, UpdateTaskOptions } from '../types.js';\n\nexport function createTaskCommand(): Command {\n const command = new Command('task');\n command.description('Manage OmniFocus tasks');\n\n command\n .command('list')\n .alias('ls')\n .description('List tasks')\n .option('-f, --flagged', 'Show only flagged tasks')\n .option('-p, --project <name>', 'Filter by project')\n .option('-t, --tag <name>', 'Filter by tag')\n .option('-c, --completed', 'Include completed tasks')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading tasks...',\n (of) => {\n const filters: TaskFilters = {\n includeCompleted: options.completed,\n ...(options.flagged && { flagged: true }),\n ...(options.project && { project: options.project }),\n ...(options.tag && { tag: options.tag }),\n };\n\n return of.listTasks(filters);\n },\n (tasks) => outputJson(tasks),\n 'Failed to load tasks'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new task')\n .option('-p, --project <name>', 'Assign to project')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-d, --due <date>', 'Set due date (ISO format)')\n .option('-D, --defer <date>', 'Set defer date (ISO format)')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating task...',\n (of) =>\n of.createTask({\n name,\n note: options.note,\n project: options.project,\n tags: options.tag,\n due: options.due,\n defer: options.defer,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n }),\n (task) => outputJson(task),\n 'Failed to create task'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing task')\n .option('-n, --name <name>', 'New name')\n .option('--note <text>', 'New note')\n .option('-p, --project <name>', 'Move to project')\n .option('-t, --tag <tags...>', 'Replace tags')\n .option('-d, --due <date>', 'Set due date (ISO format)')\n .option('-D, --defer <date>', 'Set defer date (ISO format)')\n .option('-f, --flag', 'Flag the task')\n .option('-F, --unflag', 'Unflag the task')\n .option('-c, --complete', 'Mark as completed')\n .option('-C, --incomplete', 'Mark as incomplete')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating task...',\n (of) => {\n const updates: UpdateTaskOptions = {\n ...(options.name && { name: options.name }),\n ...(options.note !== undefined && { note: options.note }),\n ...(options.project && { project: options.project }),\n ...(options.tag && { tags: options.tag }),\n ...(options.due !== undefined && { due: options.due }),\n ...(options.defer !== undefined && { defer: options.defer }),\n ...(options.flag && { flagged: true }),\n ...(options.unflag && { flagged: false }),\n ...(options.complete && { completed: true }),\n ...(options.incomplete && { completed: false }),\n ...(options.estimate !== undefined && { estimatedMinutes: options.estimate }),\n };\n\n return of.updateTask(idOrName, updates);\n },\n (task) => outputJson(task),\n 'Failed to update task'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a task')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting task...',\n (of) => of.deleteTask(idOrName),\n () => outputJson({ message: 'Task deleted successfully' }),\n 'Failed to delete task'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View task details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading task...',\n (of) => of.getTask(idOrName),\n (task) => outputJson(task),\n 'Failed to load task'\n );\n });\n\n command\n .command('stats')\n .description('Show task statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing tasks...',\n (of) => of.getTaskStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze tasks'\n );\n });\n\n return command;\n}\n","import ora from 'ora';\nimport chalk from 'chalk';\nimport { OmniFocus } from './omnifocus.js';\n\nexport async function executeCommand<T>(\n loadingMessage: string,\n action: () => Promise<T>,\n onSuccess?: (result: T) => void,\n failureMessage?: string\n): Promise<T> {\n const spinner = ora(loadingMessage).start();\n\n try {\n const result = await action();\n spinner.stop();\n onSuccess?.(result);\n return result;\n } catch (error) {\n spinner.fail(failureMessage || 'Command failed');\n console.error(chalk.red((error as Error).message));\n throw error;\n }\n}\n\nexport async function executeOmniFocusCommand<T>(\n loadingMessage: string,\n action: (of: OmniFocus) => Promise<T>,\n onSuccess?: (result: T) => void,\n failureMessage?: string\n): Promise<T> {\n const of = new OmniFocus();\n return executeCommand(loadingMessage, () => action(of), onSuccess, failureMessage);\n}\n","import { execFile } from 'child_process';\nimport { writeFile, unlink } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport type {\n Task,\n Project,\n TaskFilters,\n ProjectFilters,\n CreateTaskOptions,\n UpdateTaskOptions,\n CreateProjectOptions,\n UpdateProjectOptions,\n Perspective,\n Tag,\n TagListOptions,\n TagStats,\n TaskStats,\n ProjectStats,\n CreateTagOptions,\n UpdateTagOptions,\n Folder,\n FolderFilters,\n} from '../types.js';\n\nconst execFileAsync = promisify(execFile);\n\nexport class OmniFocus {\n private readonly PROJECT_STATUS_MAP = {\n active: 'Active',\n 'on hold': 'OnHold',\n dropped: 'Dropped',\n } as const;\n\n private readonly OMNI_HELPERS = `\n function serializeTask(task) {\n const containingProject = task.containingProject;\n const tagNames = task.tags.map(t => t.name);\n\n return {\n id: task.id.primaryKey,\n name: task.name,\n note: task.note || null,\n completed: task.completed,\n dropped: task.dropped,\n effectivelyActive: task.effectiveActive,\n flagged: task.flagged,\n project: containingProject ? containingProject.name : null,\n tags: tagNames,\n defer: task.deferDate ? task.deferDate.toISOString() : null,\n due: task.dueDate ? task.dueDate.toISOString() : null,\n estimatedMinutes: task.estimatedMinutes || null,\n completionDate: task.completionDate ? task.completionDate.toISOString() : null,\n added: task.added ? task.added.toISOString() : null,\n modified: task.modified ? task.modified.toISOString() : null\n };\n }\n\n function serializeProject(project) {\n const parentFolder = project.parentFolder;\n const allTasks = project.flattenedTasks;\n const remainingTasks = allTasks.filter(t => !t.completed);\n const tagNames = project.tags.map(t => t.name);\n\n return {\n id: project.id.primaryKey,\n name: project.name,\n note: project.note || null,\n status: projectStatusToString(project.status),\n folder: parentFolder ? parentFolder.name : null,\n sequential: project.sequential,\n taskCount: allTasks.length,\n remainingCount: remainingTasks.length,\n tags: tagNames\n };\n }\n\n function findTask(idOrName) {\n for (const task of flattenedTasks) {\n if (task.id.primaryKey === idOrName || task.name === idOrName) {\n return task;\n }\n }\n throw new Error(\"Task not found: \" + idOrName);\n }\n\n function findProject(idOrName) {\n for (const project of flattenedProjects) {\n if (project.id.primaryKey === idOrName || project.name === idOrName) {\n return project;\n }\n }\n throw new Error(\"Project not found: \" + idOrName);\n }\n\n function getTagPath(tag) {\n const parts = [tag.name];\n let current = tag.parent;\n while (current) {\n parts.unshift(current.name);\n current = current.parent;\n }\n return parts.join('/');\n }\n\n function findTag(idOrName) {\n for (const tag of flattenedTags) {\n if (tag.id.primaryKey === idOrName) {\n return tag;\n }\n }\n\n if (idOrName.includes('/')) {\n for (const tag of flattenedTags) {\n if (getTagPath(tag) === idOrName) {\n return tag;\n }\n }\n throw new Error(\"Tag not found: \" + idOrName);\n }\n\n const matches = flattenedTags.filter(tag => tag.name === idOrName);\n\n if (matches.length === 0) {\n throw new Error(\"Tag not found: \" + idOrName);\n }\n\n if (matches.length > 1) {\n const paths = matches.map(getTagPath);\n throw new Error(\"Multiple tags found with name '\" + idOrName + \"'. Please use full path:\\\\n \" + paths.join('\\\\n ') + \"\\\\nOr use tag ID: \" + matches.map(t => t.id.primaryKey).join(', '));\n }\n\n return matches[0];\n }\n\n function findByName(collection, name, typeName) {\n for (const item of collection) {\n if (item.name === name) {\n return item;\n }\n }\n throw new Error(typeName + \" not found: \" + name);\n }\n\n function assignTags(target, tagNames) {\n for (const tagName of tagNames) {\n const tag = findTag(tagName);\n target.addTag(tag);\n }\n }\n\n function replaceTagsOn(target, tagNames) {\n target.clearTags();\n assignTags(target, tagNames);\n }\n\n function statusToString(status, StatusEnum) {\n if (status === StatusEnum.Active) return 'active';\n if (status === StatusEnum.OnHold) return 'on hold';\n if (status === StatusEnum.Dropped) return 'dropped';\n if (status === StatusEnum.Done) return 'done';\n return 'dropped';\n }\n\n function stringToStatus(str, StatusEnum) {\n if (str === 'active') return StatusEnum.Active;\n if (str === 'on hold') return StatusEnum.OnHold;\n return StatusEnum.Dropped;\n }\n\n const projectStatusToString = (status) => statusToString(status, Project.Status);\n const tagStatusToString = (status) => statusToString(status, Tag.Status);\n const folderStatusToString = (status) => {\n if (status === Folder.Status.Active) return 'active';\n return 'dropped';\n };\n const stringToProjectStatus = (str) => stringToStatus(str, Project.Status);\n const stringToTagStatus = (str) => stringToStatus(str, Tag.Status);\n\n function serializeFolder(folder, includeDropped = false) {\n let childFolders = folder.folders;\n if (!includeDropped) {\n childFolders = childFolders.filter(c => c.effectiveActive);\n }\n\n return {\n id: folder.id.primaryKey,\n name: folder.name,\n status: folderStatusToString(folder.status),\n effectivelyActive: folder.effectiveActive,\n parent: folder.parent ? folder.parent.name : null,\n projectCount: folder.projects.length,\n remainingProjectCount: folder.projects.filter(p => p.effectiveActive).length,\n folderCount: folder.folders.length,\n children: childFolders.map(child => serializeFolder(child, includeDropped))\n };\n }\n\n function computeTopItems(items, keyFn, topN = 5) {\n return items\n .sort((a, b) => b[keyFn] - a[keyFn])\n .slice(0, topN)\n .map(item => ({ name: item.name, [keyFn]: item[keyFn] }));\n }\n\n function computeAverage(total, count) {\n return count > 0 ? Math.round((total / count) * 10) / 10 : 0;\n }\n\n function serializeTag(tag, activeOnly = false) {\n const tasks = tag.tasks;\n const remainingTasks = tag.remainingTasks;\n const includedTasks = activeOnly ? remainingTasks : tasks;\n\n const dates = [];\n if (tag.added) dates.push(tag.added);\n if (tag.modified) dates.push(tag.modified);\n\n for (const task of includedTasks) {\n if (task.added) dates.push(task.added);\n if (task.modified) dates.push(task.modified);\n if (!activeOnly && task.completionDate) dates.push(task.completionDate);\n if (!activeOnly && task.effectiveCompletionDate) dates.push(task.effectiveCompletionDate);\n }\n\n const lastActivity = dates.length > 0\n ? dates.reduce((latest, current) => current > latest ? current : latest)\n : null;\n\n return {\n id: tag.id.primaryKey,\n name: tag.name,\n taskCount: includedTasks.length,\n remainingTaskCount: remainingTasks.length,\n added: tag.added ? tag.added.toISOString() : null,\n modified: tag.modified ? tag.modified.toISOString() : null,\n lastActivity: lastActivity ? lastActivity.toISOString() : null,\n active: tag.active,\n status: tagStatusToString(tag.status),\n parent: tag.parent ? tag.parent.name : null,\n children: tag.children.map(c => c.name),\n allowsNextAction: tag.allowsNextAction\n };\n }\n `;\n\n private async executeJXA(script: string, timeoutMs = 30000): Promise<string> {\n const tmpFile = join(tmpdir(), `omnifocus-${Date.now()}.js`);\n\n try {\n await writeFile(tmpFile, script, 'utf-8');\n\n const { stdout } = await execFileAsync('osascript', ['-l', 'JavaScript', tmpFile], {\n timeout: timeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n });\n\n return stdout.trim();\n } finally {\n try {\n await unlink(tmpFile);\n } catch {\n /* ignore cleanup errors */\n }\n }\n }\n\n private escapeString(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n }\n\n private wrapOmniScript(omniScript: string): string {\n return `\n const app = Application('OmniFocus');\n app.includeStandardAdditions = true;\n const result = app.evaluateJavascript(${JSON.stringify(omniScript.trim())});\n result;\n `.trim();\n }\n\n private buildTaskFilters(filters: TaskFilters): string {\n const conditions: string[] = [];\n\n if (!filters.includeCompleted) {\n conditions.push('if (task.completed) continue;');\n }\n if (!filters.includeDropped) {\n conditions.push('if (!task.effectiveActive) continue;');\n }\n if (filters.flagged) {\n conditions.push('if (!task.flagged) continue;');\n conditions.push('if (task.taskStatus !== Task.Status.Available) continue;');\n }\n if (filters.project) {\n conditions.push(`\n if (!task.containingProject || task.containingProject.name !== \"${this.escapeString(filters.project)}\") {\n continue;\n }\n `);\n }\n if (filters.tag) {\n conditions.push(`\n if (!task.tags.some(t => t.name === \"${this.escapeString(filters.tag)}\")) {\n continue;\n }\n `);\n }\n\n return conditions.join('\\n ');\n }\n\n private buildProjectFilters(filters: ProjectFilters): string {\n const conditions: string[] = [];\n\n if (!filters.includeDropped) {\n conditions.push(\n 'if (project.status === Project.Status.Dropped || project.status === Project.Status.Done) continue;'\n );\n conditions.push(\n 'if (project.parentFolder && !project.parentFolder.effectiveActive) continue;'\n );\n }\n if (filters.status) {\n const statusCheck = this.PROJECT_STATUS_MAP[filters.status];\n conditions.push(`if (project.status !== Project.Status.${statusCheck}) continue;`);\n }\n if (filters.folder) {\n conditions.push(\n `if (!project.parentFolder || project.parentFolder.name !== \"${this.escapeString(filters.folder)}\") continue;`\n );\n }\n\n return conditions.join('\\n ');\n }\n\n private buildTaskUpdates(options: UpdateTaskOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`task.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.note !== undefined) {\n updates.push(`task.note = \"${this.escapeString(options.note)}\";`);\n }\n if (options.flagged !== undefined) {\n updates.push(`task.flagged = ${options.flagged};`);\n }\n if (options.completed !== undefined) {\n updates.push(`task.completed = ${options.completed};`);\n }\n if (options.estimatedMinutes !== undefined) {\n updates.push(`task.estimatedMinutes = ${options.estimatedMinutes};`);\n }\n if (options.defer !== undefined) {\n updates.push(\n options.defer\n ? `task.deferDate = new Date(${JSON.stringify(options.defer)});`\n : 'task.deferDate = null;'\n );\n }\n if (options.due !== undefined) {\n updates.push(\n options.due\n ? `task.dueDate = new Date(${JSON.stringify(options.due)});`\n : 'task.dueDate = null;'\n );\n }\n if (options.project !== undefined && options.project) {\n updates.push(`\n const targetProject = findByName(flattenedProjects, \"${this.escapeString(options.project)}\", \"Project\");\n moveTasks([task], targetProject);\n `);\n }\n if (options.tags !== undefined) {\n updates.push(`replaceTagsOn(task, ${JSON.stringify(options.tags)});`);\n }\n\n return updates.join('\\n ');\n }\n\n private buildTagUpdates(options: UpdateTagOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`tag.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.status !== undefined) {\n updates.push(`tag.status = stringToTagStatus(\"${options.status}\");`);\n }\n\n return updates.join('\\n ');\n }\n\n private buildProjectUpdates(options: UpdateProjectOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`project.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.note !== undefined) {\n updates.push(`project.note = \"${this.escapeString(options.note)}\";`);\n }\n if (options.sequential !== undefined) {\n updates.push(`project.sequential = ${options.sequential};`);\n }\n if (options.status !== undefined) {\n updates.push(`project.status = stringToProjectStatus(\"${options.status}\");`);\n }\n if (options.folder !== undefined && options.folder) {\n updates.push(`\n const targetFolder = findByName(flattenedFolders, \"${this.escapeString(options.folder)}\", \"Folder\");\n moveProjects([project], targetFolder);\n `);\n }\n if (options.tags !== undefined) {\n updates.push(`replaceTagsOn(project, ${JSON.stringify(options.tags)});`);\n }\n\n return updates.join('\\n ');\n }\n\n async listTasks(filters: TaskFilters = {}): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n for (const task of flattenedTasks) {\n ${this.buildTaskFilters(filters)}\n results.push(serializeTask(task));\n }\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createTask(options: CreateTaskOptions): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.project\n ? `const targetProject = findByName(flattenedProjects, \"${this.escapeString(options.project)}\", \"Project\");\n const task = new Task(\"${this.escapeString(options.name)}\", targetProject);`\n : `const task = new Task(\"${this.escapeString(options.name)}\");`\n }\n\n ${options.note ? `task.note = \"${this.escapeString(options.note)}\";` : ''}\n ${options.flagged ? 'task.flagged = true;' : ''}\n ${options.estimatedMinutes ? `task.estimatedMinutes = ${options.estimatedMinutes};` : ''}\n ${options.defer ? `task.deferDate = new Date(${JSON.stringify(options.defer)});` : ''}\n ${options.due ? `task.dueDate = new Date(${JSON.stringify(options.due)});` : ''}\n ${options.tags && options.tags.length > 0 ? `assignTags(task, ${JSON.stringify(options.tags)});` : ''}\n\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateTask(idOrName: string, options: UpdateTaskOptions): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const task = findTask(\"${this.escapeString(idOrName)}\");\n ${this.buildTaskUpdates(options)}\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteTask(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findTask(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async listProjects(filters: ProjectFilters = {}): Promise<Project[]> {\n const filterCode = this.buildProjectFilters(filters);\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n for (const project of flattenedProjects) {\n ${filterCode}\n results.push(serializeProject(project));\n }\n return JSON.stringify(results);\n })();\n `;\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createProject(options: CreateProjectOptions): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.folder\n ? `const targetFolder = findByName(flattenedFolders, \"${this.escapeString(options.folder)}\", \"Folder\");\n const project = new Project(\"${this.escapeString(options.name)}\", targetFolder);`\n : `const project = new Project(\"${this.escapeString(options.name)}\");`\n }\n\n ${options.note ? `project.note = \"${this.escapeString(options.note)}\";` : ''}\n ${options.sequential !== undefined ? `project.sequential = ${options.sequential};` : ''}\n ${options.status ? `project.status = stringToProjectStatus(\"${options.status}\");` : ''}\n ${options.tags && options.tags.length > 0 ? `assignTags(project, ${JSON.stringify(options.tags)});` : ''}\n\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateProject(idOrName: string, options: UpdateProjectOptions): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const project = findProject(\"${this.escapeString(idOrName)}\");\n ${this.buildProjectUpdates(options)}\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteProject(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findProject(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async listInboxTasks(): Promise<Task[]> {\n return this.getPerspectiveTasks('Inbox');\n }\n\n async getInboxCount(): Promise<number> {\n const tasks = await this.getPerspectiveTasks('Inbox');\n return tasks.length;\n }\n\n async searchTasks(query: string): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n const searchQuery = \"${this.escapeString(query)}\".toLowerCase();\n\n for (const task of flattenedTasks) {\n if (task.completed) continue;\n if (!task.effectiveActive) continue;\n\n const name = task.name.toLowerCase();\n const note = (task.note || '').toLowerCase();\n\n if (name.includes(searchQuery) || note.includes(searchQuery)) {\n results.push(serializeTask(task));\n }\n }\n\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getTask(idOrName: string): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const task = findTask(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getProject(idOrName: string): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const project = findProject(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async listPerspectives(): Promise<Perspective[]> {\n const omniScript = `\n (() => {\n const results = [];\n\n const builtInNames = ['Inbox', 'Flagged', 'Forecast', 'Projects', 'Tags', 'Nearby', 'Review'];\n for (const name of builtInNames) {\n results.push({ id: name, name: name });\n }\n\n const customPerspectives = Perspective.Custom.all;\n for (const perspective of customPerspectives) {\n results.push({ id: perspective.name, name: perspective.name });\n }\n\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getPerspectiveTasks(perspectiveName: string): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const doc = document;\n const windows = doc.windows;\n\n if (windows.length === 0) {\n throw new Error(\"No OmniFocus window is open. Please open an OmniFocus window and try again.\");\n }\n\n const win = windows[0];\n const perspectiveName = \"${this.escapeString(perspectiveName)}\";\n\n const builtInPerspectives = {\n 'inbox': Perspective.BuiltIn.Inbox,\n 'flagged': Perspective.BuiltIn.Flagged,\n 'forecast': Perspective.BuiltIn.Forecast,\n 'projects': Perspective.BuiltIn.Projects,\n 'tags': Perspective.BuiltIn.Tags,\n 'nearby': Perspective.BuiltIn.Nearby,\n 'review': Perspective.BuiltIn.Review\n };\n\n const lowerName = perspectiveName.toLowerCase();\n if (builtInPerspectives[lowerName]) {\n win.perspective = builtInPerspectives[lowerName];\n } else {\n const customPerspective = Perspective.Custom.byName(perspectiveName);\n if (customPerspective) {\n win.perspective = customPerspective;\n } else {\n throw new Error(\"Perspective not found: \" + perspectiveName);\n }\n }\n\n const content = win.content;\n if (!content) {\n throw new Error(\"No content available in window\");\n }\n\n const tasks = [];\n content.rootNode.apply(node => {\n const obj = node.object;\n if (obj instanceof Task) {\n tasks.push(serializeTask(obj));\n }\n });\n\n return JSON.stringify(tasks);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript), 60000);\n return JSON.parse(output);\n }\n\n async listTags(options: TagListOptions = {}): Promise<Tag[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n const now = new Date();\n const activeOnly = ${!!options.activeOnly};\n\n for (const tag of flattenedTags) {\n const serialized = serializeTag(tag, activeOnly);\n results.push(serialized);\n }\n\n ${\n options.unusedDays\n ? `\n const cutoffDate = new Date(now.getTime() - (${options.unusedDays} * 24 * 60 * 60 * 1000));\n const filtered = results.filter(tag => {\n if (!tag.lastActivity) return true;\n return new Date(tag.lastActivity) < cutoffDate;\n });\n return JSON.stringify(filtered);\n `\n : 'return JSON.stringify(results);'\n }\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n const tags = JSON.parse(output);\n\n return this.sortTags(tags, options.sortBy);\n }\n\n private sortTags(tags: Tag[], sortBy: string = 'name'): Tag[] {\n const sortFns: Record<string, (a: Tag, b: Tag) => number> = {\n usage: (a, b) => b.taskCount - a.taskCount,\n activity: (a, b) => {\n if (!a.lastActivity && !b.lastActivity) return 0;\n if (!a.lastActivity) return 1;\n if (!b.lastActivity) return -1;\n return new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime();\n },\n name: (a, b) => a.name.localeCompare(b.name),\n };\n\n return tags.sort(sortFns[sortBy] || sortFns.name);\n }\n\n async getTagStats(): Promise<TagStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allTags = [];\n for (const tag of flattenedTags) {\n allTags.push(serializeTag(tag));\n }\n\n const activeTags = allTags.filter(t => t.active);\n const tagsWithTasks = allTags.filter(t => t.taskCount > 0);\n const unusedTags = allTags.filter(t => t.taskCount === 0);\n\n const totalTasks = tagsWithTasks.reduce((sum, t) => sum + t.taskCount, 0);\n const avgTasksPerTag = computeAverage(totalTasks, tagsWithTasks.length);\n\n const mostUsedTags = computeTopItems(allTags, 'taskCount');\n const leastUsedTags = computeTopItems(\n tagsWithTasks.map(t => ({ ...t, taskCount: -t.taskCount })),\n 'taskCount'\n ).map(t => ({ name: t.name, taskCount: -t.taskCount }));\n\n const now = new Date();\n const thirtyDaysAgo = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n const staleTags = allTags\n .filter(t => t.lastActivity && new Date(t.lastActivity) < thirtyDaysAgo)\n .map(t => ({\n name: t.name,\n daysSinceActivity: Math.floor((now - new Date(t.lastActivity)) / (24 * 60 * 60 * 1000))\n }))\n .sort((a, b) => b.daysSinceActivity - a.daysSinceActivity);\n\n return JSON.stringify({\n totalTags: allTags.length,\n activeTags: activeTags.length,\n tagsWithTasks: tagsWithTasks.length,\n unusedTags: unusedTags.length,\n avgTasksPerTag,\n mostUsedTags,\n leastUsedTags,\n staleTags\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createTag(options: CreateTagOptions): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.parent\n ? `const parentTag = findTag(\"${this.escapeString(options.parent)}\");\n const tag = new Tag(\"${this.escapeString(options.name)}\", parentTag);`\n : `const tag = new Tag(\"${this.escapeString(options.name)}\", tags.beginning);`\n }\n\n ${options.status ? `tag.status = stringToTagStatus(\"${options.status}\");` : ''}\n\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getTag(idOrName: string): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const tag = findTag(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateTag(idOrName: string, options: UpdateTagOptions): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const tag = findTag(\"${this.escapeString(idOrName)}\");\n ${this.buildTagUpdates(options)}\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteTag(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findTag(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async getTaskStats(): Promise<TaskStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allTasks = Array.from(flattenedTasks);\n const now = new Date();\n\n const activeTasks = allTasks.filter(t => !t.completed && t.effectiveActive);\n const completedTasks = allTasks.filter(t => t.completed);\n const flaggedTasks = activeTasks.filter(t => t.flagged);\n const overdueActiveTasks = activeTasks.filter(t => t.dueDate && t.dueDate < now);\n\n const tasksWithEstimates = allTasks.filter(t => t.estimatedMinutes && t.estimatedMinutes > 0);\n const totalEstimatedMinutes = tasksWithEstimates.reduce((sum, t) => sum + (t.estimatedMinutes || 0), 0);\n const avgEstimatedMinutes = tasksWithEstimates.length > 0\n ? Math.round(totalEstimatedMinutes / tasksWithEstimates.length)\n : null;\n\n const totalNonDropped = allTasks.filter(t => t.effectiveActive || t.completed).length;\n const completionRate = totalNonDropped > 0\n ? Math.round((completedTasks.length / totalNonDropped) * 100)\n : 0;\n\n const projectCounts = {};\n for (const task of allTasks) {\n if (!task.effectiveActive && !task.completed) continue;\n const projectName = task.containingProject ? task.containingProject.name : 'Inbox';\n projectCounts[projectName] = (projectCounts[projectName] || 0) + 1;\n }\n const tasksByProject = computeTopItems(\n Object.entries(projectCounts).map(([name, count]) => ({ name, taskCount: count })),\n 'taskCount'\n );\n\n const tagCounts = {};\n for (const task of allTasks) {\n if (!task.effectiveActive && !task.completed) continue;\n for (const tag of task.tags) {\n tagCounts[tag.name] = (tagCounts[tag.name] || 0) + 1;\n }\n }\n const tasksByTag = computeTopItems(\n Object.entries(tagCounts).map(([name, count]) => ({ name, taskCount: count })),\n 'taskCount'\n );\n\n return JSON.stringify({\n totalTasks: allTasks.length,\n activeTasks: activeTasks.length,\n completedTasks: completedTasks.length,\n flaggedTasks: flaggedTasks.length,\n overdueActiveTasks: overdueActiveTasks.length,\n avgEstimatedMinutes,\n tasksWithEstimates: tasksWithEstimates.length,\n completionRate,\n tasksByProject,\n tasksByTag\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getProjectStats(): Promise<ProjectStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allProjects = Array.from(flattenedProjects);\n\n function isProjectEffectivelyActive(p) {\n if (p.status === Project.Status.Dropped || p.status === Project.Status.Done) return false;\n if (p.parentFolder && !p.parentFolder.effectiveActive) return false;\n return true;\n }\n\n const effectivelyActiveProjects = allProjects.filter(isProjectEffectivelyActive);\n const activeProjects = effectivelyActiveProjects.filter(p => p.status === Project.Status.Active);\n const onHoldProjects = effectivelyActiveProjects.filter(p => p.status === Project.Status.OnHold);\n const droppedProjects = allProjects.filter(p => p.status === Project.Status.Dropped);\n const doneProjects = allProjects.filter(p => p.status === Project.Status.Done);\n const sequentialProjects = effectivelyActiveProjects.filter(p => p.sequential);\n const parallelProjects = effectivelyActiveProjects.filter(p => !p.sequential);\n\n const totalTasks = effectivelyActiveProjects.reduce((sum, p) => sum + p.flattenedTasks.length, 0);\n const totalRemaining = effectivelyActiveProjects.reduce((sum, p) => {\n return sum + p.flattenedTasks.filter(t => !t.completed).length;\n }, 0);\n\n const avgTasksPerProject = computeAverage(totalTasks, effectivelyActiveProjects.length);\n const avgRemainingPerProject = computeAverage(totalRemaining, effectivelyActiveProjects.length);\n\n const completionRates = effectivelyActiveProjects\n .filter(p => p.flattenedTasks.length > 0)\n .map(p => {\n const total = p.flattenedTasks.length;\n const completed = p.flattenedTasks.filter(t => t.completed).length;\n return (completed / total) * 100;\n });\n\n const avgCompletionRate = completionRates.length > 0\n ? Math.round(completionRates.reduce((sum, rate) => sum + rate, 0) / completionRates.length)\n : 0;\n\n const projectsWithMostTasks = computeTopItems(\n effectivelyActiveProjects.map(p => ({ name: p.name, taskCount: p.flattenedTasks.length })),\n 'taskCount'\n );\n\n const projectsWithMostRemaining = computeTopItems(\n effectivelyActiveProjects\n .map(p => ({ name: p.name, remainingCount: p.flattenedTasks.filter(t => !t.completed).length }))\n .filter(p => p.remainingCount > 0),\n 'remainingCount'\n );\n\n return JSON.stringify({\n totalProjects: allProjects.length,\n activeProjects: activeProjects.length,\n onHoldProjects: onHoldProjects.length,\n droppedProjects: droppedProjects.length,\n doneProjects: doneProjects.length,\n sequentialProjects: sequentialProjects.length,\n parallelProjects: parallelProjects.length,\n avgTasksPerProject,\n avgRemainingPerProject,\n avgCompletionRate,\n projectsWithMostTasks,\n projectsWithMostRemaining\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async listFolders(filters: FolderFilters = {}): Promise<Folder[]> {\n const includeDropped = filters.includeDropped ?? false;\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const includeDropped = ${includeDropped};\n const results = [];\n for (const folder of folders) {\n if (!includeDropped && !folder.effectiveActive) continue;\n results.push(serializeFolder(folder, includeDropped));\n }\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getFolder(idOrName: string, filters: FolderFilters = {}): Promise<Folder> {\n const includeDropped = filters.includeDropped ?? false;\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const includeDropped = ${includeDropped};\n\n function findFolder(idOrName) {\n for (const folder of flattenedFolders) {\n if (folder.id.primaryKey === idOrName || folder.name === idOrName) {\n return folder;\n }\n }\n throw new Error(\"Folder not found: \" + idOrName);\n }\n\n const folder = findFolder(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeFolder(folder, includeDropped));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { ProjectFilters, UpdateProjectOptions } from '../types.js';\n\nexport function createProjectCommand(): Command {\n const command = new Command('project');\n command.description('Manage OmniFocus projects');\n\n command\n .command('list')\n .alias('ls')\n .description('List projects')\n .option('-f, --folder <name>', 'Filter by folder')\n .option('-s, --status <status>', 'Filter by status (active, on hold, dropped)')\n .option('-d, --dropped', 'Include dropped projects')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading projects...',\n (of) => {\n const filters: ProjectFilters = {\n includeDropped: options.dropped,\n ...(options.folder && { folder: options.folder }),\n ...(options.status && { status: options.status }),\n };\n\n return of.listProjects(filters);\n },\n (projects) => outputJson(projects),\n 'Failed to load projects'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new project')\n .option('-f, --folder <name>', 'Assign to folder')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-s, --sequential', 'Make it a sequential project')\n .option('--status <status>', 'Set status (active, on hold, dropped)')\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating project...',\n (of) =>\n of.createProject({\n name,\n note: options.note,\n folder: options.folder,\n tags: options.tag,\n sequential: options.sequential,\n status: options.status,\n }),\n (project) => outputJson(project),\n 'Failed to create project'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing project')\n .option('-n, --name <name>', 'Rename project')\n .option('--note <text>', 'New note')\n .option('-f, --folder <name>', 'Move to folder')\n .option('-t, --tag <tags...>', 'Replace tags')\n .option('-s, --sequential', 'Make it sequential')\n .option('-p, --parallel', 'Make it parallel')\n .option('--status <status>', 'Set status (active, on hold, dropped)')\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating project...',\n (of) => {\n const updates: UpdateProjectOptions = {\n ...(options.name && { name: options.name }),\n ...(options.note !== undefined && { note: options.note }),\n ...(options.folder && { folder: options.folder }),\n ...(options.tag && { tags: options.tag }),\n ...(options.sequential && { sequential: true }),\n ...(options.parallel && { sequential: false }),\n ...(options.status && { status: options.status }),\n };\n\n return of.updateProject(idOrName, updates);\n },\n (project) => outputJson(project),\n 'Failed to update project'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a project')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting project...',\n (of) => of.deleteProject(idOrName),\n () => outputJson({ message: 'Project deleted successfully' }),\n 'Failed to delete project'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View project details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading project...',\n (of) => of.getProject(idOrName),\n (project) => outputJson(project),\n 'Failed to load project'\n );\n });\n\n command\n .command('stats')\n .description('Show project statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing projects...',\n (of) => of.getProjectStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze projects'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createInboxCommand(): Command {\n const command = new Command('inbox');\n command.description('Manage OmniFocus inbox');\n\n command\n .command('list')\n .alias('ls')\n .description('List inbox tasks')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Loading inbox...',\n (of) => of.listInboxTasks(),\n (tasks) => outputJson(tasks),\n 'Failed to load inbox'\n );\n });\n\n command\n .command('count')\n .description('Get inbox count')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Counting inbox items...',\n (of) => of.getInboxCount(),\n (count) => outputJson({ count }),\n 'Failed to get inbox count'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createSearchCommand(): Command {\n const command = new Command('search');\n command.description('Search tasks by name or note');\n command.argument('<query>', 'Search query');\n\n command.action(async (query) => {\n await executeOmniFocusCommand(\n 'Searching...',\n (of) => of.searchTasks(query),\n (tasks) => outputJson(tasks),\n 'Search failed'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createPerspectiveCommand(): Command {\n const command = new Command('perspective');\n command.description('Manage OmniFocus perspectives');\n\n command\n .command('list')\n .alias('ls')\n .description('List all perspectives')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Loading perspectives...',\n (of) => of.listPerspectives(),\n (perspectives) => outputJson(perspectives),\n 'Failed to load perspectives'\n );\n });\n\n command\n .command('view <name>')\n .description('View tasks in a perspective')\n .action(async (name) => {\n await executeOmniFocusCommand(\n `Loading perspective \"${name}\"...`,\n (of) => of.getPerspectiveTasks(name),\n (tasks) => outputJson(tasks),\n 'Failed to load perspective'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { UpdateTagOptions } from '../types.js';\n\nexport function createTagCommand(): Command {\n const command = new Command('tag');\n command.description('Manage and analyze OmniFocus tags');\n\n command\n .command('list')\n .alias('ls')\n .description('List tags with usage information')\n .option('-u, --unused-days <days>', 'Show tags unused for N days', parseInt)\n .option('-s, --sort <field>', 'Sort by: name, usage, activity (default: name)', 'name')\n .option('-a, --active-only', 'Only count active (incomplete) tasks')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading tags...',\n (of) =>\n of.listTags({\n unusedDays: options.unusedDays,\n sortBy: options.sort,\n activeOnly: options.activeOnly,\n }),\n (tags) => outputJson(tags),\n 'Failed to load tags'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new tag')\n .option('-p, --parent <name>', 'Create as child of parent tag')\n .option('-s, --status <status>', 'Set status (active, on hold, dropped)')\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating tag...',\n (of) =>\n of.createTag({\n name,\n parent: options.parent,\n status: options.status,\n }),\n (tag) => outputJson(tag),\n 'Failed to create tag'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View tag details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading tag...',\n (of) => of.getTag(idOrName),\n (tag) => outputJson(tag),\n 'Failed to load tag'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing tag')\n .option('-n, --name <name>', 'Rename tag')\n .option('-s, --status <status>', 'Set status (active, on hold, dropped)')\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating tag...',\n (of) => {\n const updates: UpdateTagOptions = {\n ...(options.name && { name: options.name }),\n ...(options.status && { status: options.status }),\n };\n return of.updateTag(idOrName, updates);\n },\n (tag) => outputJson(tag),\n 'Failed to update tag'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a tag')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting tag...',\n (of) => of.deleteTag(idOrName),\n () => outputJson({ message: 'Tag deleted successfully' }),\n 'Failed to delete tag'\n );\n });\n\n command\n .command('stats')\n .description('Show tag usage statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing tags...',\n (of) => of.getTagStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze tags'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { FolderFilters } from '../types.js';\n\nexport function createFolderCommand(): Command {\n const command = new Command('folder');\n command.description('View OmniFocus folder hierarchy');\n\n command\n .command('list')\n .alias('ls')\n .description('List top-level folders with nested children')\n .option('-d, --dropped', 'Include dropped folders')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading folders...',\n (of) => of.listFolders({ includeDropped: options.dropped }),\n (folders) => outputJson(folders),\n 'Failed to load folders'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View folder details and children')\n .option('-d, --dropped', 'Include dropped child folders')\n .action(async (idOrName, options) => {\n const filters: FolderFilters = { includeDropped: options.dropped };\n await executeOmniFocusCommand(\n 'Loading folder...',\n (of) => of.getFolder(idOrName, filters),\n (folder) => outputJson(folder),\n 'Failed to load folder'\n );\n });\n\n return command;\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/output.ts","../src/commands/task.ts","../src/lib/command-utils.ts","../src/lib/omnifocus.ts","../src/commands/project.ts","../src/commands/inbox.ts","../src/commands/search.ts","../src/commands/perspective.ts","../src/commands/tag.ts","../src/commands/folder.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { Command } from 'commander';\nimport { setOutputOptions } from './lib/output.js';\nimport { createTaskCommand } from './commands/task.js';\nimport { createProjectCommand } from './commands/project.js';\nimport { createInboxCommand } from './commands/inbox.js';\nimport { createSearchCommand } from './commands/search.js';\nimport { createPerspectiveCommand } from './commands/perspective.js';\nimport { createTagCommand } from './commands/tag.js';\nimport { createFolderCommand } from './commands/folder.js';\n\nconst program = new Command();\n\nprogram\n .name('of')\n .description('A command-line interface for OmniFocus on macOS')\n .version(__VERSION__)\n .option('-c, --compact', 'Minified JSON output (single line)')\n .hook('preAction', (thisCommand) => {\n const options = thisCommand.opts();\n setOutputOptions({\n compact: options.compact,\n });\n });\n\nprogram.addCommand(createTaskCommand());\nprogram.addCommand(createProjectCommand());\nprogram.addCommand(createInboxCommand());\nprogram.addCommand(createSearchCommand());\nprogram.addCommand(createPerspectiveCommand());\nprogram.addCommand(createTagCommand());\nprogram.addCommand(createFolderCommand());\n\nprogram.parseAsync().catch(() => {\n process.exit(1);\n});\n","export interface OutputOptions {\n compact?: boolean;\n}\n\nlet globalOutputOptions: OutputOptions = {};\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOutputOptions = options;\n}\n\nexport function outputJson(data: unknown, options: OutputOptions = {}): void {\n const mergedOptions = { ...globalOutputOptions, ...options };\n const jsonString = mergedOptions.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);\n\n console.log(jsonString);\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { TaskFilters, UpdateTaskOptions } from '../types.js';\n\nexport function createTaskCommand(): Command {\n const command = new Command('task');\n command.description('Manage OmniFocus tasks');\n\n command\n .command('list')\n .alias('ls')\n .description('List tasks')\n .option('-f, --flagged', 'Show only flagged tasks')\n .option('-p, --project <name>', 'Filter by project')\n .option('-t, --tag <name>', 'Filter by tag')\n .option('-c, --completed', 'Include completed tasks')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading tasks...',\n (of) => {\n const filters: TaskFilters = {\n includeCompleted: options.completed,\n ...(options.flagged && { flagged: true }),\n ...(options.project && { project: options.project }),\n ...(options.tag && { tag: options.tag }),\n };\n\n return of.listTasks(filters);\n },\n (tasks) => outputJson(tasks),\n 'Failed to load tasks'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new task')\n .option('-p, --project <name>', 'Assign to project')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-d, --due <date>', 'Set due date (ISO format)')\n .option('-D, --defer <date>', 'Set defer date (ISO format)')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating task...',\n (of) =>\n of.createTask({\n name,\n note: options.note,\n project: options.project,\n tags: options.tag,\n due: options.due,\n defer: options.defer,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n }),\n (task) => outputJson(task),\n 'Failed to create task'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing task')\n .option('-n, --name <name>', 'New name')\n .option('--note <text>', 'New note')\n .option('-p, --project <name>', 'Move to project')\n .option('-t, --tag <tags...>', 'Replace tags')\n .option('-d, --due <date>', 'Set due date (ISO format)')\n .option('-D, --defer <date>', 'Set defer date (ISO format)')\n .option('-f, --flag', 'Flag the task')\n .option('-F, --unflag', 'Unflag the task')\n .option('-c, --complete', 'Mark as completed')\n .option('-C, --incomplete', 'Mark as incomplete')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating task...',\n (of) => {\n const updates: UpdateTaskOptions = {\n ...(options.name && { name: options.name }),\n ...(options.note !== undefined && { note: options.note }),\n ...(options.project && { project: options.project }),\n ...(options.tag && { tags: options.tag }),\n ...(options.due !== undefined && { due: options.due }),\n ...(options.defer !== undefined && { defer: options.defer }),\n ...(options.flag && { flagged: true }),\n ...(options.unflag && { flagged: false }),\n ...(options.complete && { completed: true }),\n ...(options.incomplete && { completed: false }),\n ...(options.estimate !== undefined && { estimatedMinutes: options.estimate }),\n };\n\n return of.updateTask(idOrName, updates);\n },\n (task) => outputJson(task),\n 'Failed to update task'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a task')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting task...',\n (of) => of.deleteTask(idOrName),\n () => outputJson({ message: 'Task deleted successfully' }),\n 'Failed to delete task'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View task details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading task...',\n (of) => of.getTask(idOrName),\n (task) => outputJson(task),\n 'Failed to load task'\n );\n });\n\n command\n .command('stats')\n .description('Show task statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing tasks...',\n (of) => of.getTaskStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze tasks'\n );\n });\n\n return command;\n}\n","import ora from 'ora';\nimport chalk from 'chalk';\nimport { OmniFocus } from './omnifocus.js';\n\nexport async function executeCommand<T>(\n loadingMessage: string,\n action: () => Promise<T>,\n onSuccess?: (result: T) => void,\n failureMessage?: string\n): Promise<T> {\n const spinner = ora(loadingMessage).start();\n\n try {\n const result = await action();\n spinner.stop();\n onSuccess?.(result);\n return result;\n } catch (error) {\n spinner.fail(failureMessage || 'Command failed');\n console.error(chalk.red((error as Error).message));\n throw error;\n }\n}\n\nexport async function executeOmniFocusCommand<T>(\n loadingMessage: string,\n action: (of: OmniFocus) => Promise<T>,\n onSuccess?: (result: T) => void,\n failureMessage?: string\n): Promise<T> {\n const of = new OmniFocus();\n return executeCommand(loadingMessage, () => action(of), onSuccess, failureMessage);\n}\n","import { execFile } from 'child_process';\nimport { writeFile, unlink } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport type {\n Task,\n Project,\n TaskFilters,\n ProjectFilters,\n CreateTaskOptions,\n UpdateTaskOptions,\n CreateProjectOptions,\n UpdateProjectOptions,\n Perspective,\n Tag,\n TagListOptions,\n TagStats,\n TaskStats,\n ProjectStats,\n CreateTagOptions,\n UpdateTagOptions,\n Folder,\n FolderFilters,\n} from '../types.js';\n\nconst execFileAsync = promisify(execFile);\n\nexport class OmniFocus {\n private readonly PROJECT_STATUS_MAP = {\n active: 'Active',\n 'on hold': 'OnHold',\n dropped: 'Dropped',\n } as const;\n\n private readonly OMNI_HELPERS = `\n function serializeTask(task) {\n const containingProject = task.containingProject;\n const tagNames = task.tags.map(t => t.name);\n\n return {\n id: task.id.primaryKey,\n name: task.name,\n note: task.note || null,\n completed: task.completed,\n dropped: task.dropped,\n effectivelyActive: task.effectiveActive,\n flagged: task.flagged,\n project: containingProject ? containingProject.name : null,\n tags: tagNames,\n defer: task.deferDate ? task.deferDate.toISOString() : null,\n due: task.dueDate ? task.dueDate.toISOString() : null,\n estimatedMinutes: task.estimatedMinutes || null,\n completionDate: task.completionDate ? task.completionDate.toISOString() : null,\n added: task.added ? task.added.toISOString() : null,\n modified: task.modified ? task.modified.toISOString() : null\n };\n }\n\n function serializeProject(project) {\n const parentFolder = project.parentFolder;\n const allTasks = project.flattenedTasks;\n const remainingTasks = allTasks.filter(t => !t.completed);\n const tagNames = project.tags.map(t => t.name);\n\n return {\n id: project.id.primaryKey,\n name: project.name,\n note: project.note || null,\n status: projectStatusToString(project.status),\n folder: parentFolder ? parentFolder.name : null,\n sequential: project.sequential,\n taskCount: allTasks.length,\n remainingCount: remainingTasks.length,\n tags: tagNames\n };\n }\n\n function findTask(idOrName) {\n for (const task of flattenedTasks) {\n if (task.id.primaryKey === idOrName || task.name === idOrName) {\n return task;\n }\n }\n throw new Error(\"Task not found: \" + idOrName);\n }\n\n function findProject(idOrName) {\n for (const project of flattenedProjects) {\n if (project.id.primaryKey === idOrName || project.name === idOrName) {\n return project;\n }\n }\n throw new Error(\"Project not found: \" + idOrName);\n }\n\n function getTagPath(tag) {\n const parts = [tag.name];\n let current = tag.parent;\n while (current) {\n parts.unshift(current.name);\n current = current.parent;\n }\n return parts.join('/');\n }\n\n function findTag(idOrName) {\n for (const tag of flattenedTags) {\n if (tag.id.primaryKey === idOrName) {\n return tag;\n }\n }\n\n if (idOrName.includes('/')) {\n for (const tag of flattenedTags) {\n if (getTagPath(tag) === idOrName) {\n return tag;\n }\n }\n throw new Error(\"Tag not found: \" + idOrName);\n }\n\n const matches = flattenedTags.filter(tag => tag.name === idOrName);\n\n if (matches.length === 0) {\n throw new Error(\"Tag not found: \" + idOrName);\n }\n\n if (matches.length > 1) {\n const paths = matches.map(getTagPath);\n throw new Error(\"Multiple tags found with name '\" + idOrName + \"'. Please use full path:\\\\n \" + paths.join('\\\\n ') + \"\\\\nOr use tag ID: \" + matches.map(t => t.id.primaryKey).join(', '));\n }\n\n return matches[0];\n }\n\n function findByName(collection, name, typeName) {\n for (const item of collection) {\n if (item.name === name) {\n return item;\n }\n }\n throw new Error(typeName + \" not found: \" + name);\n }\n\n function assignTags(target, tagNames) {\n for (const tagName of tagNames) {\n const tag = findTag(tagName);\n target.addTag(tag);\n }\n }\n\n function replaceTagsOn(target, tagNames) {\n target.clearTags();\n assignTags(target, tagNames);\n }\n\n function statusToString(status, StatusEnum) {\n if (status === StatusEnum.Active) return 'active';\n if (status === StatusEnum.OnHold) return 'on hold';\n if (status === StatusEnum.Dropped) return 'dropped';\n if (status === StatusEnum.Done) return 'done';\n return 'dropped';\n }\n\n function stringToStatus(str, StatusEnum) {\n if (str === 'active') return StatusEnum.Active;\n if (str === 'on hold') return StatusEnum.OnHold;\n return StatusEnum.Dropped;\n }\n\n const projectStatusToString = (status) => statusToString(status, Project.Status);\n const tagStatusToString = (status) => statusToString(status, Tag.Status);\n const folderStatusToString = (status) => {\n if (status === Folder.Status.Active) return 'active';\n return 'dropped';\n };\n const stringToProjectStatus = (str) => stringToStatus(str, Project.Status);\n const stringToTagStatus = (str) => stringToStatus(str, Tag.Status);\n\n function serializeFolder(folder, includeDropped = false) {\n let childFolders = folder.folders;\n if (!includeDropped) {\n childFolders = childFolders.filter(c => c.effectiveActive);\n }\n\n return {\n id: folder.id.primaryKey,\n name: folder.name,\n status: folderStatusToString(folder.status),\n effectivelyActive: folder.effectiveActive,\n parent: folder.parent ? folder.parent.name : null,\n projectCount: folder.projects.length,\n remainingProjectCount: folder.projects.filter(p => p.effectiveActive).length,\n folderCount: folder.folders.length,\n children: childFolders.map(child => serializeFolder(child, includeDropped))\n };\n }\n\n function computeTopItems(items, keyFn, topN = 5) {\n return items\n .sort((a, b) => b[keyFn] - a[keyFn])\n .slice(0, topN)\n .map(item => ({ name: item.name, [keyFn]: item[keyFn] }));\n }\n\n function computeAverage(total, count) {\n return count > 0 ? Math.round((total / count) * 10) / 10 : 0;\n }\n\n function serializeTag(tag, activeOnly = false) {\n const tasks = tag.tasks;\n const remainingTasks = tag.remainingTasks;\n const includedTasks = activeOnly ? remainingTasks : tasks;\n\n const dates = [];\n if (tag.added) dates.push(tag.added);\n if (tag.modified) dates.push(tag.modified);\n\n for (const task of includedTasks) {\n if (task.added) dates.push(task.added);\n if (task.modified) dates.push(task.modified);\n if (!activeOnly && task.completionDate) dates.push(task.completionDate);\n if (!activeOnly && task.effectiveCompletionDate) dates.push(task.effectiveCompletionDate);\n }\n\n const lastActivity = dates.length > 0\n ? dates.reduce((latest, current) => current > latest ? current : latest)\n : null;\n\n return {\n id: tag.id.primaryKey,\n name: tag.name,\n taskCount: includedTasks.length,\n remainingTaskCount: remainingTasks.length,\n added: tag.added ? tag.added.toISOString() : null,\n modified: tag.modified ? tag.modified.toISOString() : null,\n lastActivity: lastActivity ? lastActivity.toISOString() : null,\n active: tag.active,\n status: tagStatusToString(tag.status),\n parent: tag.parent ? tag.parent.name : null,\n children: tag.children.map(c => c.name),\n allowsNextAction: tag.allowsNextAction\n };\n }\n `;\n\n private async executeJXA(script: string, timeoutMs = 30000): Promise<string> {\n const tmpFile = join(tmpdir(), `omnifocus-${Date.now()}.js`);\n\n try {\n await writeFile(tmpFile, script, 'utf-8');\n\n const { stdout } = await execFileAsync('osascript', ['-l', 'JavaScript', tmpFile], {\n timeout: timeoutMs,\n maxBuffer: 10 * 1024 * 1024,\n });\n\n return stdout.trim();\n } finally {\n try {\n await unlink(tmpFile);\n } catch {\n /* ignore cleanup errors */\n }\n }\n }\n\n private escapeString(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n }\n\n private wrapOmniScript(omniScript: string): string {\n return `\n const app = Application('OmniFocus');\n app.includeStandardAdditions = true;\n const result = app.evaluateJavascript(${JSON.stringify(omniScript.trim())});\n result;\n `.trim();\n }\n\n private buildTaskFilters(filters: TaskFilters): string {\n const conditions: string[] = [];\n\n if (!filters.includeCompleted) {\n conditions.push('if (task.completed) continue;');\n }\n if (!filters.includeDropped) {\n conditions.push('if (!task.effectiveActive) continue;');\n }\n if (filters.flagged) {\n conditions.push('if (!task.flagged) continue;');\n conditions.push('if (task.taskStatus !== Task.Status.Available) continue;');\n }\n if (filters.project) {\n conditions.push(`\n if (!task.containingProject || task.containingProject.name !== \"${this.escapeString(filters.project)}\") {\n continue;\n }\n `);\n }\n if (filters.tag) {\n conditions.push(`\n if (!task.tags.some(t => t.name === \"${this.escapeString(filters.tag)}\")) {\n continue;\n }\n `);\n }\n\n return conditions.join('\\n ');\n }\n\n private buildProjectFilters(filters: ProjectFilters): string {\n const conditions: string[] = [];\n\n if (!filters.includeDropped) {\n conditions.push(\n 'if (project.status === Project.Status.Dropped || project.status === Project.Status.Done) continue;'\n );\n conditions.push(\n 'if (project.parentFolder && !project.parentFolder.effectiveActive) continue;'\n );\n }\n if (filters.status) {\n const statusCheck = this.PROJECT_STATUS_MAP[filters.status];\n conditions.push(`if (project.status !== Project.Status.${statusCheck}) continue;`);\n }\n if (filters.folder) {\n conditions.push(\n `if (!project.parentFolder || project.parentFolder.name !== \"${this.escapeString(filters.folder)}\") continue;`\n );\n }\n\n return conditions.join('\\n ');\n }\n\n private buildTaskUpdates(options: UpdateTaskOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`task.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.note !== undefined) {\n updates.push(`task.note = \"${this.escapeString(options.note)}\";`);\n }\n if (options.flagged !== undefined) {\n updates.push(`task.flagged = ${options.flagged};`);\n }\n if (options.completed !== undefined) {\n updates.push(`task.completed = ${options.completed};`);\n }\n if (options.estimatedMinutes !== undefined) {\n updates.push(`task.estimatedMinutes = ${options.estimatedMinutes};`);\n }\n if (options.defer !== undefined) {\n updates.push(\n options.defer\n ? `task.deferDate = new Date(${JSON.stringify(options.defer)});`\n : 'task.deferDate = null;'\n );\n }\n if (options.due !== undefined) {\n updates.push(\n options.due\n ? `task.dueDate = new Date(${JSON.stringify(options.due)});`\n : 'task.dueDate = null;'\n );\n }\n if (options.project !== undefined && options.project) {\n updates.push(`\n const targetProject = findByName(flattenedProjects, \"${this.escapeString(options.project)}\", \"Project\");\n moveTasks([task], targetProject);\n `);\n }\n if (options.tags !== undefined) {\n updates.push(`replaceTagsOn(task, ${JSON.stringify(options.tags)});`);\n }\n\n return updates.join('\\n ');\n }\n\n private buildTagUpdates(options: UpdateTagOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`tag.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.status !== undefined) {\n updates.push(`tag.status = stringToTagStatus(\"${options.status}\");`);\n }\n\n return updates.join('\\n ');\n }\n\n private buildProjectUpdates(options: UpdateProjectOptions): string {\n const updates: string[] = [];\n\n if (options.name !== undefined) {\n updates.push(`project.name = \"${this.escapeString(options.name)}\";`);\n }\n if (options.note !== undefined) {\n updates.push(`project.note = \"${this.escapeString(options.note)}\";`);\n }\n if (options.sequential !== undefined) {\n updates.push(`project.sequential = ${options.sequential};`);\n }\n if (options.status !== undefined) {\n updates.push(`project.status = stringToProjectStatus(\"${options.status}\");`);\n }\n if (options.folder !== undefined && options.folder) {\n updates.push(`\n const targetFolder = findByName(flattenedFolders, \"${this.escapeString(options.folder)}\", \"Folder\");\n moveProjects([project], targetFolder);\n `);\n }\n if (options.tags !== undefined) {\n updates.push(`replaceTagsOn(project, ${JSON.stringify(options.tags)});`);\n }\n\n return updates.join('\\n ');\n }\n\n async listTasks(filters: TaskFilters = {}): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n for (const task of flattenedTasks) {\n ${this.buildTaskFilters(filters)}\n results.push(serializeTask(task));\n }\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createTask(options: CreateTaskOptions): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.project\n ? `const targetProject = findByName(flattenedProjects, \"${this.escapeString(options.project)}\", \"Project\");\n const task = new Task(\"${this.escapeString(options.name)}\", targetProject);`\n : `const task = new Task(\"${this.escapeString(options.name)}\");`\n }\n\n ${options.note ? `task.note = \"${this.escapeString(options.note)}\";` : ''}\n ${options.flagged ? 'task.flagged = true;' : ''}\n ${options.estimatedMinutes ? `task.estimatedMinutes = ${options.estimatedMinutes};` : ''}\n ${options.defer ? `task.deferDate = new Date(${JSON.stringify(options.defer)});` : ''}\n ${options.due ? `task.dueDate = new Date(${JSON.stringify(options.due)});` : ''}\n ${options.tags && options.tags.length > 0 ? `assignTags(task, ${JSON.stringify(options.tags)});` : ''}\n\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateTask(idOrName: string, options: UpdateTaskOptions): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const task = findTask(\"${this.escapeString(idOrName)}\");\n ${this.buildTaskUpdates(options)}\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteTask(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findTask(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async listProjects(filters: ProjectFilters = {}): Promise<Project[]> {\n const filterCode = this.buildProjectFilters(filters);\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n for (const project of flattenedProjects) {\n ${filterCode}\n results.push(serializeProject(project));\n }\n return JSON.stringify(results);\n })();\n `;\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createProject(options: CreateProjectOptions): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.folder\n ? `const targetFolder = findByName(flattenedFolders, \"${this.escapeString(options.folder)}\", \"Folder\");\n const project = new Project(\"${this.escapeString(options.name)}\", targetFolder);`\n : `const project = new Project(\"${this.escapeString(options.name)}\");`\n }\n\n ${options.note ? `project.note = \"${this.escapeString(options.note)}\";` : ''}\n ${options.sequential !== undefined ? `project.sequential = ${options.sequential};` : ''}\n ${options.status ? `project.status = stringToProjectStatus(\"${options.status}\");` : ''}\n ${options.tags && options.tags.length > 0 ? `assignTags(project, ${JSON.stringify(options.tags)});` : ''}\n\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateProject(idOrName: string, options: UpdateProjectOptions): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const project = findProject(\"${this.escapeString(idOrName)}\");\n ${this.buildProjectUpdates(options)}\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteProject(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findProject(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async listInboxTasks(): Promise<Task[]> {\n return this.getPerspectiveTasks('Inbox');\n }\n\n async getInboxCount(): Promise<number> {\n const tasks = await this.getPerspectiveTasks('Inbox');\n return tasks.length;\n }\n\n async searchTasks(query: string): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n const searchQuery = \"${this.escapeString(query)}\".toLowerCase();\n\n for (const task of flattenedTasks) {\n if (task.completed) continue;\n if (!task.effectiveActive) continue;\n\n const name = task.name.toLowerCase();\n const note = (task.note || '').toLowerCase();\n\n if (name.includes(searchQuery) || note.includes(searchQuery)) {\n results.push(serializeTask(task));\n }\n }\n\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getTask(idOrName: string): Promise<Task> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const task = findTask(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeTask(task));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getProject(idOrName: string): Promise<Project> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const project = findProject(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeProject(project));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async listPerspectives(): Promise<Perspective[]> {\n const omniScript = `\n (() => {\n const results = [];\n\n const builtInNames = ['Inbox', 'Flagged', 'Forecast', 'Projects', 'Tags', 'Nearby', 'Review'];\n for (const name of builtInNames) {\n results.push({ id: name, name: name });\n }\n\n const customPerspectives = Perspective.Custom.all;\n for (const perspective of customPerspectives) {\n results.push({ id: perspective.name, name: perspective.name });\n }\n\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getPerspectiveTasks(perspectiveName: string): Promise<Task[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const doc = document;\n const windows = doc.windows;\n\n if (windows.length === 0) {\n throw new Error(\"No OmniFocus window is open. Please open an OmniFocus window and try again.\");\n }\n\n const win = windows[0];\n const perspectiveName = \"${this.escapeString(perspectiveName)}\";\n\n const builtInPerspectives = {\n 'inbox': Perspective.BuiltIn.Inbox,\n 'flagged': Perspective.BuiltIn.Flagged,\n 'forecast': Perspective.BuiltIn.Forecast,\n 'projects': Perspective.BuiltIn.Projects,\n 'tags': Perspective.BuiltIn.Tags,\n 'nearby': Perspective.BuiltIn.Nearby,\n 'review': Perspective.BuiltIn.Review\n };\n\n const lowerName = perspectiveName.toLowerCase();\n if (builtInPerspectives[lowerName]) {\n win.perspective = builtInPerspectives[lowerName];\n } else {\n const customPerspective = Perspective.Custom.byName(perspectiveName);\n if (customPerspective) {\n win.perspective = customPerspective;\n } else {\n throw new Error(\"Perspective not found: \" + perspectiveName);\n }\n }\n\n const content = win.content;\n if (!content) {\n throw new Error(\"No content available in window\");\n }\n\n const tasks = [];\n content.rootNode.apply(node => {\n const obj = node.object;\n if (obj instanceof Task) {\n tasks.push(serializeTask(obj));\n }\n });\n\n return JSON.stringify(tasks);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript), 60000);\n return JSON.parse(output);\n }\n\n async listTags(options: TagListOptions = {}): Promise<Tag[]> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const results = [];\n const now = new Date();\n const activeOnly = ${!!options.activeOnly};\n\n for (const tag of flattenedTags) {\n const serialized = serializeTag(tag, activeOnly);\n results.push(serialized);\n }\n\n ${\n options.unusedDays\n ? `\n const cutoffDate = new Date(now.getTime() - (${options.unusedDays} * 24 * 60 * 60 * 1000));\n const filtered = results.filter(tag => {\n if (!tag.lastActivity) return true;\n return new Date(tag.lastActivity) < cutoffDate;\n });\n return JSON.stringify(filtered);\n `\n : 'return JSON.stringify(results);'\n }\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n const tags = JSON.parse(output);\n\n return this.sortTags(tags, options.sortBy);\n }\n\n private sortTags(tags: Tag[], sortBy: string = 'name'): Tag[] {\n const sortFns: Record<string, (a: Tag, b: Tag) => number> = {\n usage: (a, b) => b.taskCount - a.taskCount,\n activity: (a, b) => {\n if (!a.lastActivity && !b.lastActivity) return 0;\n if (!a.lastActivity) return 1;\n if (!b.lastActivity) return -1;\n return new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime();\n },\n name: (a, b) => a.name.localeCompare(b.name),\n };\n\n return tags.sort(sortFns[sortBy] || sortFns.name);\n }\n\n async getTagStats(): Promise<TagStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allTags = [];\n for (const tag of flattenedTags) {\n allTags.push(serializeTag(tag));\n }\n\n const activeTags = allTags.filter(t => t.active);\n const tagsWithTasks = allTags.filter(t => t.taskCount > 0);\n const unusedTags = allTags.filter(t => t.taskCount === 0);\n\n const totalTasks = tagsWithTasks.reduce((sum, t) => sum + t.taskCount, 0);\n const avgTasksPerTag = computeAverage(totalTasks, tagsWithTasks.length);\n\n const mostUsedTags = computeTopItems(allTags, 'taskCount');\n const leastUsedTags = computeTopItems(\n tagsWithTasks.map(t => ({ ...t, taskCount: -t.taskCount })),\n 'taskCount'\n ).map(t => ({ name: t.name, taskCount: -t.taskCount }));\n\n const now = new Date();\n const thirtyDaysAgo = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n const staleTags = allTags\n .filter(t => t.lastActivity && new Date(t.lastActivity) < thirtyDaysAgo)\n .map(t => ({\n name: t.name,\n daysSinceActivity: Math.floor((now - new Date(t.lastActivity)) / (24 * 60 * 60 * 1000))\n }))\n .sort((a, b) => b.daysSinceActivity - a.daysSinceActivity);\n\n return JSON.stringify({\n totalTags: allTags.length,\n activeTags: activeTags.length,\n tagsWithTasks: tagsWithTasks.length,\n unusedTags: unusedTags.length,\n avgTasksPerTag,\n mostUsedTags,\n leastUsedTags,\n staleTags\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async createTag(options: CreateTagOptions): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n ${\n options.parent\n ? `const parentTag = findTag(\"${this.escapeString(options.parent)}\");\n const tag = new Tag(\"${this.escapeString(options.name)}\", parentTag);`\n : `const tag = new Tag(\"${this.escapeString(options.name)}\", tags.beginning);`\n }\n\n ${options.status ? `tag.status = stringToTagStatus(\"${options.status}\");` : ''}\n\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getTag(idOrName: string): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const tag = findTag(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async updateTag(idOrName: string, options: UpdateTagOptions): Promise<Tag> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const tag = findTag(\"${this.escapeString(idOrName)}\");\n ${this.buildTagUpdates(options)}\n return JSON.stringify(serializeTag(tag));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async deleteTag(idOrName: string): Promise<void> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n deleteObject(findTag(\"${this.escapeString(idOrName)}\"));\n })();\n `;\n\n await this.executeJXA(this.wrapOmniScript(omniScript));\n }\n\n async getTaskStats(): Promise<TaskStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allTasks = Array.from(flattenedTasks);\n const now = new Date();\n\n const activeTasks = allTasks.filter(t => !t.completed && t.effectiveActive);\n const completedTasks = allTasks.filter(t => t.completed);\n const flaggedTasks = activeTasks.filter(t => t.flagged);\n const overdueActiveTasks = activeTasks.filter(t => t.dueDate && t.dueDate < now);\n\n const tasksWithEstimates = allTasks.filter(t => t.estimatedMinutes && t.estimatedMinutes > 0);\n const totalEstimatedMinutes = tasksWithEstimates.reduce((sum, t) => sum + (t.estimatedMinutes || 0), 0);\n const avgEstimatedMinutes = tasksWithEstimates.length > 0\n ? Math.round(totalEstimatedMinutes / tasksWithEstimates.length)\n : null;\n\n const totalNonDropped = allTasks.filter(t => t.effectiveActive || t.completed).length;\n const completionRate = totalNonDropped > 0\n ? Math.round((completedTasks.length / totalNonDropped) * 100)\n : 0;\n\n const projectCounts = {};\n for (const task of allTasks) {\n if (!task.effectiveActive && !task.completed) continue;\n const projectName = task.containingProject ? task.containingProject.name : 'Inbox';\n projectCounts[projectName] = (projectCounts[projectName] || 0) + 1;\n }\n const tasksByProject = computeTopItems(\n Object.entries(projectCounts).map(([name, count]) => ({ name, taskCount: count })),\n 'taskCount'\n );\n\n const tagCounts = {};\n for (const task of allTasks) {\n if (!task.effectiveActive && !task.completed) continue;\n for (const tag of task.tags) {\n tagCounts[tag.name] = (tagCounts[tag.name] || 0) + 1;\n }\n }\n const tasksByTag = computeTopItems(\n Object.entries(tagCounts).map(([name, count]) => ({ name, taskCount: count })),\n 'taskCount'\n );\n\n return JSON.stringify({\n totalTasks: allTasks.length,\n activeTasks: activeTasks.length,\n completedTasks: completedTasks.length,\n flaggedTasks: flaggedTasks.length,\n overdueActiveTasks: overdueActiveTasks.length,\n avgEstimatedMinutes,\n tasksWithEstimates: tasksWithEstimates.length,\n completionRate,\n tasksByProject,\n tasksByTag\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getProjectStats(): Promise<ProjectStats> {\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const allProjects = Array.from(flattenedProjects);\n\n function isProjectEffectivelyActive(p) {\n if (p.status === Project.Status.Dropped || p.status === Project.Status.Done) return false;\n if (p.parentFolder && !p.parentFolder.effectiveActive) return false;\n return true;\n }\n\n const effectivelyActiveProjects = allProjects.filter(isProjectEffectivelyActive);\n const activeProjects = effectivelyActiveProjects.filter(p => p.status === Project.Status.Active);\n const onHoldProjects = effectivelyActiveProjects.filter(p => p.status === Project.Status.OnHold);\n const droppedProjects = allProjects.filter(p => p.status === Project.Status.Dropped);\n const doneProjects = allProjects.filter(p => p.status === Project.Status.Done);\n const sequentialProjects = effectivelyActiveProjects.filter(p => p.sequential);\n const parallelProjects = effectivelyActiveProjects.filter(p => !p.sequential);\n\n const totalTasks = effectivelyActiveProjects.reduce((sum, p) => sum + p.flattenedTasks.length, 0);\n const totalRemaining = effectivelyActiveProjects.reduce((sum, p) => {\n return sum + p.flattenedTasks.filter(t => !t.completed).length;\n }, 0);\n\n const avgTasksPerProject = computeAverage(totalTasks, effectivelyActiveProjects.length);\n const avgRemainingPerProject = computeAverage(totalRemaining, effectivelyActiveProjects.length);\n\n const completionRates = effectivelyActiveProjects\n .filter(p => p.flattenedTasks.length > 0)\n .map(p => {\n const total = p.flattenedTasks.length;\n const completed = p.flattenedTasks.filter(t => t.completed).length;\n return (completed / total) * 100;\n });\n\n const avgCompletionRate = completionRates.length > 0\n ? Math.round(completionRates.reduce((sum, rate) => sum + rate, 0) / completionRates.length)\n : 0;\n\n const projectsWithMostTasks = computeTopItems(\n effectivelyActiveProjects.map(p => ({ name: p.name, taskCount: p.flattenedTasks.length })),\n 'taskCount'\n );\n\n const projectsWithMostRemaining = computeTopItems(\n effectivelyActiveProjects\n .map(p => ({ name: p.name, remainingCount: p.flattenedTasks.filter(t => !t.completed).length }))\n .filter(p => p.remainingCount > 0),\n 'remainingCount'\n );\n\n return JSON.stringify({\n totalProjects: allProjects.length,\n activeProjects: activeProjects.length,\n onHoldProjects: onHoldProjects.length,\n droppedProjects: droppedProjects.length,\n doneProjects: doneProjects.length,\n sequentialProjects: sequentialProjects.length,\n parallelProjects: parallelProjects.length,\n avgTasksPerProject,\n avgRemainingPerProject,\n avgCompletionRate,\n projectsWithMostTasks,\n projectsWithMostRemaining\n });\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async listFolders(filters: FolderFilters = {}): Promise<Folder[]> {\n const includeDropped = filters.includeDropped ?? false;\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const includeDropped = ${includeDropped};\n const results = [];\n for (const folder of folders) {\n if (!includeDropped && !folder.effectiveActive) continue;\n results.push(serializeFolder(folder, includeDropped));\n }\n return JSON.stringify(results);\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n\n async getFolder(idOrName: string, filters: FolderFilters = {}): Promise<Folder> {\n const includeDropped = filters.includeDropped ?? false;\n const omniScript = `\n ${this.OMNI_HELPERS}\n (() => {\n const includeDropped = ${includeDropped};\n\n function findFolder(idOrName) {\n for (const folder of flattenedFolders) {\n if (folder.id.primaryKey === idOrName || folder.name === idOrName) {\n return folder;\n }\n }\n throw new Error(\"Folder not found: \" + idOrName);\n }\n\n const folder = findFolder(\"${this.escapeString(idOrName)}\");\n return JSON.stringify(serializeFolder(folder, includeDropped));\n })();\n `;\n\n const output = await this.executeJXA(this.wrapOmniScript(omniScript));\n return JSON.parse(output);\n }\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { ProjectFilters, UpdateProjectOptions } from '../types.js';\n\nexport function createProjectCommand(): Command {\n const command = new Command('project');\n command.description('Manage OmniFocus projects');\n\n command\n .command('list')\n .alias('ls')\n .description('List projects')\n .option('-f, --folder <name>', 'Filter by folder')\n .option('-s, --status <status>', 'Filter by status (active, on hold, dropped)')\n .option('-d, --dropped', 'Include dropped projects')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading projects...',\n (of) => {\n const filters: ProjectFilters = {\n includeDropped: options.dropped,\n ...(options.folder && { folder: options.folder }),\n ...(options.status && { status: options.status }),\n };\n\n return of.listProjects(filters);\n },\n (projects) => outputJson(projects),\n 'Failed to load projects'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new project')\n .option('-f, --folder <name>', 'Assign to folder')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-s, --sequential', 'Make it a sequential project')\n .option('--status <status>', 'Set status (active, on hold, dropped)')\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating project...',\n (of) =>\n of.createProject({\n name,\n note: options.note,\n folder: options.folder,\n tags: options.tag,\n sequential: options.sequential,\n status: options.status,\n }),\n (project) => outputJson(project),\n 'Failed to create project'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing project')\n .option('-n, --name <name>', 'Rename project')\n .option('--note <text>', 'New note')\n .option('-f, --folder <name>', 'Move to folder')\n .option('-t, --tag <tags...>', 'Replace tags')\n .option('-s, --sequential', 'Make it sequential')\n .option('-p, --parallel', 'Make it parallel')\n .option('--status <status>', 'Set status (active, on hold, dropped)')\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating project...',\n (of) => {\n const updates: UpdateProjectOptions = {\n ...(options.name && { name: options.name }),\n ...(options.note !== undefined && { note: options.note }),\n ...(options.folder && { folder: options.folder }),\n ...(options.tag && { tags: options.tag }),\n ...(options.sequential && { sequential: true }),\n ...(options.parallel && { sequential: false }),\n ...(options.status && { status: options.status }),\n };\n\n return of.updateProject(idOrName, updates);\n },\n (project) => outputJson(project),\n 'Failed to update project'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a project')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting project...',\n (of) => of.deleteProject(idOrName),\n () => outputJson({ message: 'Project deleted successfully' }),\n 'Failed to delete project'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View project details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading project...',\n (of) => of.getProject(idOrName),\n (project) => outputJson(project),\n 'Failed to load project'\n );\n });\n\n command\n .command('stats')\n .description('Show project statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing projects...',\n (of) => of.getProjectStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze projects'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createInboxCommand(): Command {\n const command = new Command('inbox');\n command.description('Manage OmniFocus inbox');\n\n command\n .command('list')\n .alias('ls')\n .description('List inbox tasks')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Loading inbox...',\n (of) => of.listInboxTasks(),\n (tasks) => outputJson(tasks),\n 'Failed to load inbox'\n );\n });\n\n command\n .command('count')\n .description('Get inbox count')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Counting inbox items...',\n (of) => of.getInboxCount(),\n (count) => outputJson({ count }),\n 'Failed to get inbox count'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createSearchCommand(): Command {\n const command = new Command('search');\n command.description('Search tasks by name or note');\n command.argument('<query>', 'Search query');\n\n command.action(async (query) => {\n await executeOmniFocusCommand(\n 'Searching...',\n (of) => of.searchTasks(query),\n (tasks) => outputJson(tasks),\n 'Search failed'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\n\nexport function createPerspectiveCommand(): Command {\n const command = new Command('perspective');\n command.description('Manage OmniFocus perspectives');\n\n command\n .command('list')\n .alias('ls')\n .description('List all perspectives')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Loading perspectives...',\n (of) => of.listPerspectives(),\n (perspectives) => outputJson(perspectives),\n 'Failed to load perspectives'\n );\n });\n\n command\n .command('view <name>')\n .description('View tasks in a perspective')\n .action(async (name) => {\n await executeOmniFocusCommand(\n `Loading perspective \"${name}\"...`,\n (of) => of.getPerspectiveTasks(name),\n (tasks) => outputJson(tasks),\n 'Failed to load perspective'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { UpdateTagOptions } from '../types.js';\n\nexport function createTagCommand(): Command {\n const command = new Command('tag');\n command.description('Manage and analyze OmniFocus tags');\n\n command\n .command('list')\n .alias('ls')\n .description('List tags with usage information')\n .option('-u, --unused-days <days>', 'Show tags unused for N days', parseInt)\n .option('-s, --sort <field>', 'Sort by: name, usage, activity (default: name)', 'name')\n .option('-a, --active-only', 'Only count active (incomplete) tasks')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading tags...',\n (of) =>\n of.listTags({\n unusedDays: options.unusedDays,\n sortBy: options.sort,\n activeOnly: options.activeOnly,\n }),\n (tags) => outputJson(tags),\n 'Failed to load tags'\n );\n });\n\n command\n .command('create <name>')\n .description('Create a new tag')\n .option('-p, --parent <name>', 'Create as child of parent tag')\n .option('-s, --status <status>', 'Set status (active, on hold, dropped)')\n .action(async (name, options) => {\n await executeOmniFocusCommand(\n 'Creating tag...',\n (of) =>\n of.createTag({\n name,\n parent: options.parent,\n status: options.status,\n }),\n (tag) => outputJson(tag),\n 'Failed to create tag'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View tag details')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Loading tag...',\n (of) => of.getTag(idOrName),\n (tag) => outputJson(tag),\n 'Failed to load tag'\n );\n });\n\n command\n .command('update <idOrName>')\n .description('Update an existing tag')\n .option('-n, --name <name>', 'Rename tag')\n .option('-s, --status <status>', 'Set status (active, on hold, dropped)')\n .action(async (idOrName, options) => {\n await executeOmniFocusCommand(\n 'Updating tag...',\n (of) => {\n const updates: UpdateTagOptions = {\n ...(options.name && { name: options.name }),\n ...(options.status && { status: options.status }),\n };\n return of.updateTag(idOrName, updates);\n },\n (tag) => outputJson(tag),\n 'Failed to update tag'\n );\n });\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a tag')\n .action(async (idOrName) => {\n await executeOmniFocusCommand(\n 'Deleting tag...',\n (of) => of.deleteTag(idOrName),\n () => outputJson({ message: 'Tag deleted successfully' }),\n 'Failed to delete tag'\n );\n });\n\n command\n .command('stats')\n .description('Show tag usage statistics')\n .action(async () => {\n await executeOmniFocusCommand(\n 'Analyzing tags...',\n (of) => of.getTagStats(),\n (stats) => outputJson(stats),\n 'Failed to analyze tags'\n );\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { executeOmniFocusCommand } from '../lib/command-utils.js';\nimport type { FolderFilters } from '../types.js';\n\nexport function createFolderCommand(): Command {\n const command = new Command('folder');\n command.description('View OmniFocus folder hierarchy');\n\n command\n .command('list')\n .alias('ls')\n .description('List top-level folders with nested children')\n .option('-d, --dropped', 'Include dropped folders')\n .action(async (options) => {\n await executeOmniFocusCommand(\n 'Loading folders...',\n (of) => of.listFolders({ includeDropped: options.dropped }),\n (folders) => outputJson(folders),\n 'Failed to load folders'\n );\n });\n\n command\n .command('view <idOrName>')\n .description('View folder details and children')\n .option('-d, --dropped', 'Include dropped child folders')\n .action(async (idOrName, options) => {\n const filters: FolderFilters = { includeDropped: options.dropped };\n await executeOmniFocusCommand(\n 'Loading folder...',\n (of) => of.getFolder(idOrName, filters),\n (folder) => outputJson(folder),\n 'Failed to load folder'\n );\n });\n\n return command;\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stephendolan/omnifocus-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A command-line interface for OmniFocus on macOS",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
"of": "dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsup",
|
|
12
|
-
"dev": "
|
|
13
|
-
"start": "
|
|
14
|
-
"lint": "oxlint src",
|
|
15
|
-
"format": "biome format --write src",
|
|
16
|
-
"format:check": "biome format src",
|
|
17
|
-
"typecheck": "tsc --noEmit",
|
|
18
|
-
"test": "vitest run",
|
|
19
|
-
"link": "
|
|
20
|
-
"prepublishOnly": "
|
|
11
|
+
"build": "bun run tsup",
|
|
12
|
+
"dev": "bun run src/index.ts",
|
|
13
|
+
"start": "bun dist/index.js",
|
|
14
|
+
"lint": "bun run oxlint src",
|
|
15
|
+
"format": "bun run biome format --write src",
|
|
16
|
+
"format:check": "bun run biome format src",
|
|
17
|
+
"typecheck": "bun run tsc --noEmit",
|
|
18
|
+
"test": "bun run vitest run",
|
|
19
|
+
"link": "bun run build && bun link",
|
|
20
|
+
"prepublishOnly": "bun run build"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"omnifocus",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"LICENSE"
|
|
46
46
|
],
|
|
47
47
|
"engines": {
|
|
48
|
-
"
|
|
48
|
+
"bun": ">=1.0.0"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"chalk": "^5.3.0",
|