Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ A CLI tool for OmniFocus on macOS that uses JavaScript for Automation (JXA) to i
```bash
bun install # Install dependencies
bun run build # Build TypeScript to dist/
bun run dev # Watch mode for development
bun link # Link binary for local testing (creates `of` command)
bun run dev # Run CLI directly via bun (no build required)
bun run link # Build + link binary globally (creates `of` command)
bun run lint # Lint with oxlint
bun run format # Format with Biome (writes changes)
bun run typecheck # Type-check without emitting
bun run test # Run all tests with vitest
bun run vitest run <file> # Run a single test file
```

### Testing the CLI
After `bun link`, use `of` command globally:
After `bun run link`, use `of` command globally:
```bash
of task list # List tasks
of project list # List projects
Expand Down Expand Up @@ -50,6 +55,10 @@ Files:
- `src/commands/perspective.ts` - Perspective switching and viewing
- `src/commands/search.ts` - Task search
- `src/commands/tag.ts` - Tag management and statistics
- `src/commands/folder.ts` - Folder hierarchy (list, view)
- `src/commands/mcp.ts` + `src/mcp/server.ts` - MCP server (`of mcp`) exposing all OmniFocus operations as MCP tools via stdio transport
- `src/lib/display.ts` - Formatting helpers (estimates, dates, tags)
- `src/lib/output.ts` - `outputJson()` for all command output (supports compact mode)

### Type Definitions

Expand Down
6 changes: 6 additions & 0 deletions src/commands/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function createTaskCommand(): Command {
.option('-t, --tag <tags...>', 'Add tags')
.option('-d, --due <date>', 'Set due date')
.option('-D, --defer <date>', 'Set defer date')
.option('-P, --planned <date>', 'Set planned date')
.option('-f, --flagged', 'Flag the task')
.option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)
.action(
Expand All @@ -51,6 +52,7 @@ export function createTaskCommand(): Command {
tags: options.tag,
due: options.due ? parseDateTime(options.due) : undefined,
defer: options.defer ? parseDateTime(options.defer) : undefined,
planned: options.planned ? parseDateTime(options.planned) : undefined,
flagged: options.flagged,
estimatedMinutes: options.estimate,
});
Expand All @@ -67,6 +69,7 @@ export function createTaskCommand(): Command {
.option('-t, --tag <tags...>', 'Replace tags')
.option('-d, --due <date>', 'Set due date')
.option('-D, --defer <date>', 'Set defer date')
.option('-P, --planned <date>', 'Set planned date')
.option('-f, --flag', 'Flag the task')
.option('-F, --unflag', 'Unflag the task')
.option('-c, --complete', 'Mark as completed')
Expand All @@ -86,6 +89,9 @@ export function createTaskCommand(): Command {
...(options.defer !== undefined && {
defer: options.defer ? parseDateTime(options.defer) : null,
}),
...(options.planned !== undefined && {
planned: options.planned ? parseDateTime(options.planned) : null,
}),
...(options.flag && { flagged: true }),
...(options.unflag && { flagged: false }),
...(options.complete && { completed: true }),
Expand Down
9 changes: 9 additions & 0 deletions src/lib/omnifocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class OmniFocus {
tags: tagNames,
defer: task.deferDate ? task.deferDate.toISOString() : null,
due: task.dueDate ? task.dueDate.toISOString() : null,
planned: task.plannedDate ? task.plannedDate.toISOString() : null,
estimatedMinutes: task.estimatedMinutes || null,
completionDate: task.completionDate ? task.completionDate.toISOString() : null,
added: task.added ? task.added.toISOString() : null,
Expand Down Expand Up @@ -371,6 +372,13 @@ export class OmniFocus {
: 'task.dueDate = null;'
);
}
if (options.planned !== undefined) {
updates.push(
options.planned
? `task.plannedDate = new Date(${JSON.stringify(options.planned)});`
: 'task.plannedDate = null;'
);
}
if (options.project !== undefined && options.project) {
updates.push(`
const targetProject = findByName(flattenedProjects, "${this.escapeString(options.project)}", "Project");
Expand Down Expand Up @@ -458,6 +466,7 @@ export class OmniFocus {
${options.estimatedMinutes ? `task.estimatedMinutes = ${options.estimatedMinutes};` : ''}
${options.defer ? `task.deferDate = new Date(${JSON.stringify(options.defer)});` : ''}
${options.due ? `task.dueDate = new Date(${JSON.stringify(options.due)});` : ''}
${options.planned ? `task.plannedDate = new Date(${JSON.stringify(options.planned)});` : ''}
${options.tags && options.tags.length > 0 ? `assignTags(task, ${JSON.stringify(options.tags)});` : ''}

return JSON.stringify(serializeTask(task));
Expand Down
2 changes: 2 additions & 0 deletions src/mcp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ server.tool(
tags: z.array(z.string()).optional().describe('Tags to assign'),
defer: z.string().optional().describe('Defer date (ISO 8601)'),
due: z.string().optional().describe('Due date (ISO 8601)'),
planned: z.string().optional().describe('Planned date (ISO 8601)'),
flagged: z.boolean().optional().describe('Flag the task'),
estimatedMinutes: z.number().optional().describe('Estimated duration in minutes'),
},
Expand All @@ -89,6 +90,7 @@ server.tool(
tags: z.array(z.string()).optional().describe('Replace tags'),
defer: z.string().optional().describe('New defer date (ISO 8601)'),
due: z.string().optional().describe('New due date (ISO 8601)'),
planned: z.string().optional().describe('New planned date (ISO 8601)'),
flagged: z.boolean().optional().describe('Flag/unflag the task'),
estimatedMinutes: z.number().optional().describe('New estimated duration'),
completed: z.boolean().optional().describe('Mark complete/incomplete'),
Expand Down
7 changes: 5 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface Task {
tags: string[];
defer: string | null;
due: string | null;
planned: string | null;
estimatedMinutes: number | null;
completionDate: string | null;
added: string | null;
Expand Down Expand Up @@ -49,6 +50,7 @@ export interface CreateTaskOptions {
tags?: string[];
defer?: string;
due?: string;
planned?: string;
flagged?: boolean;
estimatedMinutes?: number;
}
Expand All @@ -58,8 +60,9 @@ export interface UpdateTaskOptions {
note?: string;
project?: string;
tags?: string[];
defer?: string;
due?: string;
defer?: string | null;
due?: string | null;
planned?: string | null;
flagged?: boolean;
estimatedMinutes?: number;
completed?: boolean;
Expand Down