@stephendolan/omnifocus-cli 2.2.1 → 2.3.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/dist/cli.js +304 -55
- package/dist/cli.js.map +1 -1
- package/package.json +4 -2
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command9 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/lib/output.ts
|
|
7
7
|
var globalOutputOptions = {};
|
|
@@ -997,21 +997,21 @@ function createTaskCommand() {
|
|
|
997
997
|
command.description("Manage OmniFocus tasks");
|
|
998
998
|
command.command("list").alias("ls").description("List tasks").option("-f, --flagged", "Show only flagged tasks").option("-p, --project <name>", "Filter by project").option("-t, --tag <name>", "Filter by tag").option("-c, --completed", "Include completed tasks").action(
|
|
999
999
|
withErrorHandling(async (options) => {
|
|
1000
|
-
const
|
|
1000
|
+
const of2 = new OmniFocus();
|
|
1001
1001
|
const filters = {
|
|
1002
1002
|
includeCompleted: options.completed,
|
|
1003
1003
|
...options.flagged && { flagged: true },
|
|
1004
1004
|
...options.project && { project: options.project },
|
|
1005
1005
|
...options.tag && { tag: options.tag }
|
|
1006
1006
|
};
|
|
1007
|
-
const tasks = await
|
|
1007
|
+
const tasks = await of2.listTasks(filters);
|
|
1008
1008
|
outputJson(tasks);
|
|
1009
1009
|
})
|
|
1010
1010
|
);
|
|
1011
1011
|
command.command("create <name>").description("Create a new task").option("-p, --project <name>", "Assign to project").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1012
1012
|
withErrorHandling(async (name, options) => {
|
|
1013
|
-
const
|
|
1014
|
-
const task = await
|
|
1013
|
+
const of2 = new OmniFocus();
|
|
1014
|
+
const task = await of2.createTask({
|
|
1015
1015
|
name,
|
|
1016
1016
|
note: options.note,
|
|
1017
1017
|
project: options.project,
|
|
@@ -1026,7 +1026,7 @@ function createTaskCommand() {
|
|
|
1026
1026
|
);
|
|
1027
1027
|
command.command("update <idOrName>").description("Update an existing task").option("-n, --name <name>", "New name").option("--note <text>", "New note").option("-p, --project <name>", "Move to project").option("-t, --tag <tags...>", "Replace tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flag", "Flag the task").option("-F, --unflag", "Unflag the task").option("-c, --complete", "Mark as completed").option("-C, --incomplete", "Mark as incomplete").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1028
1028
|
withErrorHandling(async (idOrName, options) => {
|
|
1029
|
-
const
|
|
1029
|
+
const of2 = new OmniFocus();
|
|
1030
1030
|
const updates = {
|
|
1031
1031
|
...options.name && { name: options.name },
|
|
1032
1032
|
...options.note !== void 0 && { note: options.note },
|
|
@@ -1044,28 +1044,28 @@ function createTaskCommand() {
|
|
|
1044
1044
|
...options.incomplete && { completed: false },
|
|
1045
1045
|
...options.estimate !== void 0 && { estimatedMinutes: options.estimate }
|
|
1046
1046
|
};
|
|
1047
|
-
const task = await
|
|
1047
|
+
const task = await of2.updateTask(idOrName, updates);
|
|
1048
1048
|
outputJson(task);
|
|
1049
1049
|
})
|
|
1050
1050
|
);
|
|
1051
1051
|
command.command("delete <idOrName>").alias("rm").description("Delete a task").action(
|
|
1052
1052
|
withErrorHandling(async (idOrName) => {
|
|
1053
|
-
const
|
|
1054
|
-
await
|
|
1053
|
+
const of2 = new OmniFocus();
|
|
1054
|
+
await of2.deleteTask(idOrName);
|
|
1055
1055
|
outputJson({ message: "Task deleted successfully" });
|
|
1056
1056
|
})
|
|
1057
1057
|
);
|
|
1058
1058
|
command.command("view <idOrName>").description("View task details").action(
|
|
1059
1059
|
withErrorHandling(async (idOrName) => {
|
|
1060
|
-
const
|
|
1061
|
-
const task = await
|
|
1060
|
+
const of2 = new OmniFocus();
|
|
1061
|
+
const task = await of2.getTask(idOrName);
|
|
1062
1062
|
outputJson(task);
|
|
1063
1063
|
})
|
|
1064
1064
|
);
|
|
1065
1065
|
command.command("stats").description("Show task statistics").action(
|
|
1066
1066
|
withErrorHandling(async () => {
|
|
1067
|
-
const
|
|
1068
|
-
const stats = await
|
|
1067
|
+
const of2 = new OmniFocus();
|
|
1068
|
+
const stats = await of2.getTaskStats();
|
|
1069
1069
|
outputJson(stats);
|
|
1070
1070
|
})
|
|
1071
1071
|
);
|
|
@@ -1079,20 +1079,20 @@ function createProjectCommand() {
|
|
|
1079
1079
|
command.description("Manage OmniFocus projects");
|
|
1080
1080
|
command.command("list").alias("ls").description("List projects").option("-f, --folder <name>", "Filter by folder").option("-s, --status <status>", "Filter by status (active, on hold, dropped)").option("-d, --dropped", "Include dropped projects").action(
|
|
1081
1081
|
withErrorHandling(async (options) => {
|
|
1082
|
-
const
|
|
1082
|
+
const of2 = new OmniFocus();
|
|
1083
1083
|
const filters = {
|
|
1084
1084
|
includeDropped: options.dropped,
|
|
1085
1085
|
...options.folder && { folder: options.folder },
|
|
1086
1086
|
...options.status && { status: options.status }
|
|
1087
1087
|
};
|
|
1088
|
-
const projects = await
|
|
1088
|
+
const projects = await of2.listProjects(filters);
|
|
1089
1089
|
outputJson(projects);
|
|
1090
1090
|
})
|
|
1091
1091
|
);
|
|
1092
1092
|
command.command("create <name>").description("Create a new project").option("-f, --folder <name>", "Assign to folder").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-s, --sequential", "Make it a sequential project").option("--status <status>", "Set status (active, on hold, dropped)").action(
|
|
1093
1093
|
withErrorHandling(async (name, options) => {
|
|
1094
|
-
const
|
|
1095
|
-
const project = await
|
|
1094
|
+
const of2 = new OmniFocus();
|
|
1095
|
+
const project = await of2.createProject({
|
|
1096
1096
|
name,
|
|
1097
1097
|
note: options.note,
|
|
1098
1098
|
folder: options.folder,
|
|
@@ -1105,7 +1105,7 @@ function createProjectCommand() {
|
|
|
1105
1105
|
);
|
|
1106
1106
|
command.command("update <idOrName>").description("Update an existing project").option("-n, --name <name>", "Rename project").option("--note <text>", "New note").option("-f, --folder <name>", "Move to folder").option("-t, --tag <tags...>", "Replace tags").option("-s, --sequential", "Make it sequential").option("-p, --parallel", "Make it parallel").option("--status <status>", "Set status (active, on hold, dropped)").action(
|
|
1107
1107
|
withErrorHandling(async (idOrName, options) => {
|
|
1108
|
-
const
|
|
1108
|
+
const of2 = new OmniFocus();
|
|
1109
1109
|
const updates = {
|
|
1110
1110
|
...options.name && { name: options.name },
|
|
1111
1111
|
...options.note !== void 0 && { note: options.note },
|
|
@@ -1115,28 +1115,28 @@ function createProjectCommand() {
|
|
|
1115
1115
|
...options.parallel && { sequential: false },
|
|
1116
1116
|
...options.status && { status: options.status }
|
|
1117
1117
|
};
|
|
1118
|
-
const project = await
|
|
1118
|
+
const project = await of2.updateProject(idOrName, updates);
|
|
1119
1119
|
outputJson(project);
|
|
1120
1120
|
})
|
|
1121
1121
|
);
|
|
1122
1122
|
command.command("delete <idOrName>").alias("rm").description("Delete a project").action(
|
|
1123
1123
|
withErrorHandling(async (idOrName) => {
|
|
1124
|
-
const
|
|
1125
|
-
await
|
|
1124
|
+
const of2 = new OmniFocus();
|
|
1125
|
+
await of2.deleteProject(idOrName);
|
|
1126
1126
|
outputJson({ message: "Project deleted successfully" });
|
|
1127
1127
|
})
|
|
1128
1128
|
);
|
|
1129
1129
|
command.command("view <idOrName>").description("View project details").action(
|
|
1130
1130
|
withErrorHandling(async (idOrName) => {
|
|
1131
|
-
const
|
|
1132
|
-
const project = await
|
|
1131
|
+
const of2 = new OmniFocus();
|
|
1132
|
+
const project = await of2.getProject(idOrName);
|
|
1133
1133
|
outputJson(project);
|
|
1134
1134
|
})
|
|
1135
1135
|
);
|
|
1136
1136
|
command.command("stats").description("Show project statistics").action(
|
|
1137
1137
|
withErrorHandling(async () => {
|
|
1138
|
-
const
|
|
1139
|
-
const stats = await
|
|
1138
|
+
const of2 = new OmniFocus();
|
|
1139
|
+
const stats = await of2.getProjectStats();
|
|
1140
1140
|
outputJson(stats);
|
|
1141
1141
|
})
|
|
1142
1142
|
);
|
|
@@ -1150,22 +1150,22 @@ function createInboxCommand() {
|
|
|
1150
1150
|
command.description("Manage OmniFocus inbox");
|
|
1151
1151
|
command.command("list").alias("ls").description("List inbox tasks").action(
|
|
1152
1152
|
withErrorHandling(async () => {
|
|
1153
|
-
const
|
|
1154
|
-
const tasks = await
|
|
1153
|
+
const of2 = new OmniFocus();
|
|
1154
|
+
const tasks = await of2.listInboxTasks();
|
|
1155
1155
|
outputJson(tasks);
|
|
1156
1156
|
})
|
|
1157
1157
|
);
|
|
1158
1158
|
command.command("count").description("Get inbox count").action(
|
|
1159
1159
|
withErrorHandling(async () => {
|
|
1160
|
-
const
|
|
1161
|
-
const count = await
|
|
1160
|
+
const of2 = new OmniFocus();
|
|
1161
|
+
const count = await of2.getInboxCount();
|
|
1162
1162
|
outputJson({ count });
|
|
1163
1163
|
})
|
|
1164
1164
|
);
|
|
1165
1165
|
command.command("add <name>").description("Add a task to inbox").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1166
1166
|
withErrorHandling(async (name, options) => {
|
|
1167
|
-
const
|
|
1168
|
-
const task = await
|
|
1167
|
+
const of2 = new OmniFocus();
|
|
1168
|
+
const task = await of2.createTask({
|
|
1169
1169
|
name,
|
|
1170
1170
|
note: options.note,
|
|
1171
1171
|
tags: options.tag,
|
|
@@ -1188,8 +1188,8 @@ function createSearchCommand() {
|
|
|
1188
1188
|
command.argument("<query>", "Search query");
|
|
1189
1189
|
command.action(
|
|
1190
1190
|
withErrorHandling(async (query) => {
|
|
1191
|
-
const
|
|
1192
|
-
const tasks = await
|
|
1191
|
+
const of2 = new OmniFocus();
|
|
1192
|
+
const tasks = await of2.searchTasks(query);
|
|
1193
1193
|
outputJson(tasks);
|
|
1194
1194
|
})
|
|
1195
1195
|
);
|
|
@@ -1203,15 +1203,15 @@ function createPerspectiveCommand() {
|
|
|
1203
1203
|
command.description("Manage OmniFocus perspectives");
|
|
1204
1204
|
command.command("list").alias("ls").description("List all perspectives").action(
|
|
1205
1205
|
withErrorHandling(async () => {
|
|
1206
|
-
const
|
|
1207
|
-
const perspectives = await
|
|
1206
|
+
const of2 = new OmniFocus();
|
|
1207
|
+
const perspectives = await of2.listPerspectives();
|
|
1208
1208
|
outputJson(perspectives);
|
|
1209
1209
|
})
|
|
1210
1210
|
);
|
|
1211
1211
|
command.command("view <name>").description("View tasks in a perspective").action(
|
|
1212
1212
|
withErrorHandling(async (name) => {
|
|
1213
|
-
const
|
|
1214
|
-
const tasks = await
|
|
1213
|
+
const of2 = new OmniFocus();
|
|
1214
|
+
const tasks = await of2.getPerspectiveTasks(name);
|
|
1215
1215
|
outputJson(tasks);
|
|
1216
1216
|
})
|
|
1217
1217
|
);
|
|
@@ -1225,8 +1225,8 @@ function createTagCommand() {
|
|
|
1225
1225
|
command.description("Manage and analyze OmniFocus tags");
|
|
1226
1226
|
command.command("list").alias("ls").description("List tags with usage information").option("-u, --unused-days <days>", "Show tags unused for N days", parseInt).option("-s, --sort <field>", "Sort by: name, usage, activity (default: name)", "name").option("-a, --active-only", "Only count active (incomplete) tasks").action(
|
|
1227
1227
|
withErrorHandling(async (options) => {
|
|
1228
|
-
const
|
|
1229
|
-
const tags = await
|
|
1228
|
+
const of2 = new OmniFocus();
|
|
1229
|
+
const tags = await of2.listTags({
|
|
1230
1230
|
unusedDays: options.unusedDays,
|
|
1231
1231
|
sortBy: options.sort,
|
|
1232
1232
|
activeOnly: options.activeOnly
|
|
@@ -1236,8 +1236,8 @@ function createTagCommand() {
|
|
|
1236
1236
|
);
|
|
1237
1237
|
command.command("create <name>").description("Create a new tag").option("-p, --parent <name>", "Create as child of parent tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
|
|
1238
1238
|
withErrorHandling(async (name, options) => {
|
|
1239
|
-
const
|
|
1240
|
-
const tag = await
|
|
1239
|
+
const of2 = new OmniFocus();
|
|
1240
|
+
const tag = await of2.createTag({
|
|
1241
1241
|
name,
|
|
1242
1242
|
parent: options.parent,
|
|
1243
1243
|
status: options.status
|
|
@@ -1247,33 +1247,33 @@ function createTagCommand() {
|
|
|
1247
1247
|
);
|
|
1248
1248
|
command.command("view <idOrName>").description("View tag details").action(
|
|
1249
1249
|
withErrorHandling(async (idOrName) => {
|
|
1250
|
-
const
|
|
1251
|
-
const tag = await
|
|
1250
|
+
const of2 = new OmniFocus();
|
|
1251
|
+
const tag = await of2.getTag(idOrName);
|
|
1252
1252
|
outputJson(tag);
|
|
1253
1253
|
})
|
|
1254
1254
|
);
|
|
1255
1255
|
command.command("update <idOrName>").description("Update an existing tag").option("-n, --name <name>", "Rename tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
|
|
1256
1256
|
withErrorHandling(async (idOrName, options) => {
|
|
1257
|
-
const
|
|
1257
|
+
const of2 = new OmniFocus();
|
|
1258
1258
|
const updates = {
|
|
1259
1259
|
...options.name && { name: options.name },
|
|
1260
1260
|
...options.status && { status: options.status }
|
|
1261
1261
|
};
|
|
1262
|
-
const tag = await
|
|
1262
|
+
const tag = await of2.updateTag(idOrName, updates);
|
|
1263
1263
|
outputJson(tag);
|
|
1264
1264
|
})
|
|
1265
1265
|
);
|
|
1266
1266
|
command.command("delete <idOrName>").alias("rm").description("Delete a tag").action(
|
|
1267
1267
|
withErrorHandling(async (idOrName) => {
|
|
1268
|
-
const
|
|
1269
|
-
await
|
|
1268
|
+
const of2 = new OmniFocus();
|
|
1269
|
+
await of2.deleteTag(idOrName);
|
|
1270
1270
|
outputJson({ message: "Tag deleted successfully" });
|
|
1271
1271
|
})
|
|
1272
1272
|
);
|
|
1273
1273
|
command.command("stats").description("Show tag usage statistics").action(
|
|
1274
1274
|
withErrorHandling(async () => {
|
|
1275
|
-
const
|
|
1276
|
-
const stats = await
|
|
1275
|
+
const of2 = new OmniFocus();
|
|
1276
|
+
const stats = await of2.getTagStats();
|
|
1277
1277
|
outputJson(stats);
|
|
1278
1278
|
})
|
|
1279
1279
|
);
|
|
@@ -1287,25 +1287,273 @@ function createFolderCommand() {
|
|
|
1287
1287
|
command.description("View OmniFocus folder hierarchy");
|
|
1288
1288
|
command.command("list").alias("ls").description("List top-level folders with nested children").option("-d, --dropped", "Include dropped folders").action(
|
|
1289
1289
|
withErrorHandling(async (options) => {
|
|
1290
|
-
const
|
|
1291
|
-
const folders = await
|
|
1290
|
+
const of2 = new OmniFocus();
|
|
1291
|
+
const folders = await of2.listFolders({ includeDropped: options.dropped });
|
|
1292
1292
|
outputJson(folders);
|
|
1293
1293
|
})
|
|
1294
1294
|
);
|
|
1295
1295
|
command.command("view <idOrName>").description("View folder details and children").option("-d, --dropped", "Include dropped child folders").action(
|
|
1296
1296
|
withErrorHandling(async (idOrName, options) => {
|
|
1297
|
-
const
|
|
1297
|
+
const of2 = new OmniFocus();
|
|
1298
1298
|
const filters = { includeDropped: options.dropped };
|
|
1299
|
-
const folder = await
|
|
1299
|
+
const folder = await of2.getFolder(idOrName, filters);
|
|
1300
1300
|
outputJson(folder);
|
|
1301
1301
|
})
|
|
1302
1302
|
);
|
|
1303
1303
|
return command;
|
|
1304
1304
|
}
|
|
1305
1305
|
|
|
1306
|
+
// src/commands/mcp.ts
|
|
1307
|
+
import { Command as Command8 } from "commander";
|
|
1308
|
+
|
|
1309
|
+
// src/mcp/server.ts
|
|
1310
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1311
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1312
|
+
import { z } from "zod";
|
|
1313
|
+
var server = new McpServer({
|
|
1314
|
+
name: "omnifocus",
|
|
1315
|
+
version: "1.0.0"
|
|
1316
|
+
});
|
|
1317
|
+
var of = new OmniFocus();
|
|
1318
|
+
function jsonResponse(data) {
|
|
1319
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
1320
|
+
}
|
|
1321
|
+
server.tool(
|
|
1322
|
+
"list_tasks",
|
|
1323
|
+
"List tasks with optional filtering",
|
|
1324
|
+
{
|
|
1325
|
+
includeCompleted: z.boolean().optional().describe("Include completed tasks"),
|
|
1326
|
+
includeDropped: z.boolean().optional().describe("Include dropped tasks"),
|
|
1327
|
+
flagged: z.boolean().optional().describe("Only show flagged tasks"),
|
|
1328
|
+
project: z.string().optional().describe("Filter by project name"),
|
|
1329
|
+
tag: z.string().optional().describe("Filter by tag name")
|
|
1330
|
+
},
|
|
1331
|
+
async (filters) => jsonResponse(await of.listTasks(filters))
|
|
1332
|
+
);
|
|
1333
|
+
server.tool(
|
|
1334
|
+
"get_task",
|
|
1335
|
+
"Get a specific task by ID or name",
|
|
1336
|
+
{ idOrName: z.string().describe("Task ID or name") },
|
|
1337
|
+
async ({ idOrName }) => jsonResponse(await of.getTask(idOrName))
|
|
1338
|
+
);
|
|
1339
|
+
server.tool(
|
|
1340
|
+
"create_task",
|
|
1341
|
+
"Create a new task",
|
|
1342
|
+
{
|
|
1343
|
+
name: z.string().describe("Task name"),
|
|
1344
|
+
note: z.string().optional().describe("Task note"),
|
|
1345
|
+
project: z.string().optional().describe("Project to add task to"),
|
|
1346
|
+
tags: z.array(z.string()).optional().describe("Tags to assign"),
|
|
1347
|
+
defer: z.string().optional().describe("Defer date (ISO 8601)"),
|
|
1348
|
+
due: z.string().optional().describe("Due date (ISO 8601)"),
|
|
1349
|
+
flagged: z.boolean().optional().describe("Flag the task"),
|
|
1350
|
+
estimatedMinutes: z.number().optional().describe("Estimated duration in minutes")
|
|
1351
|
+
},
|
|
1352
|
+
async (options) => jsonResponse(await of.createTask(options))
|
|
1353
|
+
);
|
|
1354
|
+
server.tool(
|
|
1355
|
+
"update_task",
|
|
1356
|
+
"Update an existing task",
|
|
1357
|
+
{
|
|
1358
|
+
idOrName: z.string().describe("Task ID or name"),
|
|
1359
|
+
name: z.string().optional().describe("New task name"),
|
|
1360
|
+
note: z.string().optional().describe("New task note"),
|
|
1361
|
+
project: z.string().optional().describe("Move to project"),
|
|
1362
|
+
tags: z.array(z.string()).optional().describe("Replace tags"),
|
|
1363
|
+
defer: z.string().optional().describe("New defer date (ISO 8601)"),
|
|
1364
|
+
due: z.string().optional().describe("New due date (ISO 8601)"),
|
|
1365
|
+
flagged: z.boolean().optional().describe("Flag/unflag the task"),
|
|
1366
|
+
estimatedMinutes: z.number().optional().describe("New estimated duration"),
|
|
1367
|
+
completed: z.boolean().optional().describe("Mark complete/incomplete")
|
|
1368
|
+
},
|
|
1369
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateTask(idOrName, options))
|
|
1370
|
+
);
|
|
1371
|
+
server.tool(
|
|
1372
|
+
"delete_task",
|
|
1373
|
+
"Delete a task",
|
|
1374
|
+
{ idOrName: z.string().describe("Task ID or name") },
|
|
1375
|
+
async ({ idOrName }) => {
|
|
1376
|
+
await of.deleteTask(idOrName);
|
|
1377
|
+
return jsonResponse({ deleted: true });
|
|
1378
|
+
}
|
|
1379
|
+
);
|
|
1380
|
+
server.tool(
|
|
1381
|
+
"search_tasks",
|
|
1382
|
+
"Search tasks by name or note content",
|
|
1383
|
+
{ query: z.string().describe("Search query") },
|
|
1384
|
+
async ({ query }) => jsonResponse(await of.searchTasks(query))
|
|
1385
|
+
);
|
|
1386
|
+
server.tool(
|
|
1387
|
+
"get_task_stats",
|
|
1388
|
+
"Get task statistics",
|
|
1389
|
+
{},
|
|
1390
|
+
async () => jsonResponse(await of.getTaskStats())
|
|
1391
|
+
);
|
|
1392
|
+
server.tool(
|
|
1393
|
+
"list_inbox",
|
|
1394
|
+
"List all inbox tasks",
|
|
1395
|
+
{},
|
|
1396
|
+
async () => jsonResponse(await of.listInboxTasks())
|
|
1397
|
+
);
|
|
1398
|
+
server.tool(
|
|
1399
|
+
"get_inbox_count",
|
|
1400
|
+
"Get the number of inbox tasks",
|
|
1401
|
+
{},
|
|
1402
|
+
async () => jsonResponse({ count: await of.getInboxCount() })
|
|
1403
|
+
);
|
|
1404
|
+
server.tool(
|
|
1405
|
+
"list_projects",
|
|
1406
|
+
"List projects with optional filtering",
|
|
1407
|
+
{
|
|
1408
|
+
includeDropped: z.boolean().optional().describe("Include dropped projects"),
|
|
1409
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Filter by status"),
|
|
1410
|
+
folder: z.string().optional().describe("Filter by folder name")
|
|
1411
|
+
},
|
|
1412
|
+
async (filters) => jsonResponse(await of.listProjects(filters))
|
|
1413
|
+
);
|
|
1414
|
+
server.tool(
|
|
1415
|
+
"get_project",
|
|
1416
|
+
"Get a specific project by ID or name",
|
|
1417
|
+
{ idOrName: z.string().describe("Project ID or name") },
|
|
1418
|
+
async ({ idOrName }) => jsonResponse(await of.getProject(idOrName))
|
|
1419
|
+
);
|
|
1420
|
+
server.tool(
|
|
1421
|
+
"create_project",
|
|
1422
|
+
"Create a new project",
|
|
1423
|
+
{
|
|
1424
|
+
name: z.string().describe("Project name"),
|
|
1425
|
+
note: z.string().optional().describe("Project note"),
|
|
1426
|
+
folder: z.string().optional().describe("Folder to create project in"),
|
|
1427
|
+
sequential: z.boolean().optional().describe("Sequential project (tasks must be done in order)"),
|
|
1428
|
+
tags: z.array(z.string()).optional().describe("Tags to assign"),
|
|
1429
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Initial status")
|
|
1430
|
+
},
|
|
1431
|
+
async (options) => jsonResponse(await of.createProject(options))
|
|
1432
|
+
);
|
|
1433
|
+
server.tool(
|
|
1434
|
+
"update_project",
|
|
1435
|
+
"Update an existing project",
|
|
1436
|
+
{
|
|
1437
|
+
idOrName: z.string().describe("Project ID or name"),
|
|
1438
|
+
name: z.string().optional().describe("New project name"),
|
|
1439
|
+
note: z.string().optional().describe("New project note"),
|
|
1440
|
+
folder: z.string().optional().describe("Move to folder"),
|
|
1441
|
+
sequential: z.boolean().optional().describe("Set sequential/parallel"),
|
|
1442
|
+
tags: z.array(z.string()).optional().describe("Replace tags"),
|
|
1443
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("New status")
|
|
1444
|
+
},
|
|
1445
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateProject(idOrName, options))
|
|
1446
|
+
);
|
|
1447
|
+
server.tool(
|
|
1448
|
+
"delete_project",
|
|
1449
|
+
"Delete a project",
|
|
1450
|
+
{ idOrName: z.string().describe("Project ID or name") },
|
|
1451
|
+
async ({ idOrName }) => {
|
|
1452
|
+
await of.deleteProject(idOrName);
|
|
1453
|
+
return jsonResponse({ deleted: true });
|
|
1454
|
+
}
|
|
1455
|
+
);
|
|
1456
|
+
server.tool(
|
|
1457
|
+
"get_project_stats",
|
|
1458
|
+
"Get project statistics",
|
|
1459
|
+
{},
|
|
1460
|
+
async () => jsonResponse(await of.getProjectStats())
|
|
1461
|
+
);
|
|
1462
|
+
server.tool(
|
|
1463
|
+
"list_perspectives",
|
|
1464
|
+
"List all available perspectives",
|
|
1465
|
+
{},
|
|
1466
|
+
async () => jsonResponse(await of.listPerspectives())
|
|
1467
|
+
);
|
|
1468
|
+
server.tool(
|
|
1469
|
+
"get_perspective_tasks",
|
|
1470
|
+
"Get tasks from a specific perspective",
|
|
1471
|
+
{ name: z.string().describe("Perspective name (e.g., Inbox, Flagged, or custom perspective)") },
|
|
1472
|
+
async ({ name }) => jsonResponse(await of.getPerspectiveTasks(name))
|
|
1473
|
+
);
|
|
1474
|
+
server.tool(
|
|
1475
|
+
"list_tags",
|
|
1476
|
+
"List all tags with optional filtering and sorting",
|
|
1477
|
+
{
|
|
1478
|
+
unusedDays: z.number().optional().describe("Only show tags unused for this many days"),
|
|
1479
|
+
sortBy: z.enum(["name", "usage", "activity"]).optional().describe("Sort order"),
|
|
1480
|
+
activeOnly: z.boolean().optional().describe("Only count active tasks")
|
|
1481
|
+
},
|
|
1482
|
+
async (options) => jsonResponse(await of.listTags(options))
|
|
1483
|
+
);
|
|
1484
|
+
server.tool(
|
|
1485
|
+
"get_tag",
|
|
1486
|
+
"Get a specific tag by ID or name",
|
|
1487
|
+
{ idOrName: z.string().describe('Tag ID, name, or path (e.g., "Parent/Child")') },
|
|
1488
|
+
async ({ idOrName }) => jsonResponse(await of.getTag(idOrName))
|
|
1489
|
+
);
|
|
1490
|
+
server.tool(
|
|
1491
|
+
"create_tag",
|
|
1492
|
+
"Create a new tag",
|
|
1493
|
+
{
|
|
1494
|
+
name: z.string().describe("Tag name"),
|
|
1495
|
+
parent: z.string().optional().describe("Parent tag name or path"),
|
|
1496
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Initial status")
|
|
1497
|
+
},
|
|
1498
|
+
async (options) => jsonResponse(await of.createTag(options))
|
|
1499
|
+
);
|
|
1500
|
+
server.tool(
|
|
1501
|
+
"update_tag",
|
|
1502
|
+
"Update an existing tag",
|
|
1503
|
+
{
|
|
1504
|
+
idOrName: z.string().describe("Tag ID, name, or path"),
|
|
1505
|
+
name: z.string().optional().describe("New tag name"),
|
|
1506
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("New status")
|
|
1507
|
+
},
|
|
1508
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateTag(idOrName, options))
|
|
1509
|
+
);
|
|
1510
|
+
server.tool(
|
|
1511
|
+
"delete_tag",
|
|
1512
|
+
"Delete a tag",
|
|
1513
|
+
{ idOrName: z.string().describe("Tag ID, name, or path") },
|
|
1514
|
+
async ({ idOrName }) => {
|
|
1515
|
+
await of.deleteTag(idOrName);
|
|
1516
|
+
return jsonResponse({ deleted: true });
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
server.tool(
|
|
1520
|
+
"get_tag_stats",
|
|
1521
|
+
"Get tag statistics",
|
|
1522
|
+
{},
|
|
1523
|
+
async () => jsonResponse(await of.getTagStats())
|
|
1524
|
+
);
|
|
1525
|
+
server.tool(
|
|
1526
|
+
"list_folders",
|
|
1527
|
+
"List all folders",
|
|
1528
|
+
{ includeDropped: z.boolean().optional().describe("Include dropped folders") },
|
|
1529
|
+
async (filters) => jsonResponse(await of.listFolders(filters))
|
|
1530
|
+
);
|
|
1531
|
+
server.tool(
|
|
1532
|
+
"get_folder",
|
|
1533
|
+
"Get a specific folder by ID or name",
|
|
1534
|
+
{
|
|
1535
|
+
idOrName: z.string().describe("Folder ID or name"),
|
|
1536
|
+
includeDropped: z.boolean().optional().describe("Include dropped children")
|
|
1537
|
+
},
|
|
1538
|
+
async ({ idOrName, includeDropped }) => jsonResponse(await of.getFolder(idOrName, { includeDropped }))
|
|
1539
|
+
);
|
|
1540
|
+
async function runMcpServer() {
|
|
1541
|
+
const transport = new StdioServerTransport();
|
|
1542
|
+
await server.connect(transport);
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// src/commands/mcp.ts
|
|
1546
|
+
function createMcpCommand() {
|
|
1547
|
+
const cmd = new Command8("mcp").description("Run OmniFocus MCP server");
|
|
1548
|
+
cmd.action(async () => {
|
|
1549
|
+
await runMcpServer();
|
|
1550
|
+
});
|
|
1551
|
+
return cmd;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1306
1554
|
// src/cli.ts
|
|
1307
|
-
var program = new
|
|
1308
|
-
program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.
|
|
1555
|
+
var program = new Command9();
|
|
1556
|
+
program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.3.0").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
|
|
1309
1557
|
const options = thisCommand.opts();
|
|
1310
1558
|
setOutputOptions({
|
|
1311
1559
|
compact: options.compact
|
|
@@ -1318,6 +1566,7 @@ program.addCommand(createSearchCommand());
|
|
|
1318
1566
|
program.addCommand(createPerspectiveCommand());
|
|
1319
1567
|
program.addCommand(createTagCommand());
|
|
1320
1568
|
program.addCommand(createFolderCommand());
|
|
1569
|
+
program.addCommand(createMcpCommand());
|
|
1321
1570
|
program.parseAsync().catch(() => {
|
|
1322
1571
|
process.exit(1);
|
|
1323
1572
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/lib/output.ts","../src/commands/task.ts","../src/lib/errors.ts","../src/lib/command-utils.ts","../src/lib/omnifocus.ts","../src/lib/dates.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 { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.js';\nimport { parseDateTime } from '../lib/dates.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\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 const tasks = await of.listTasks(filters);\n outputJson(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')\n .option('-D, --defer <date>', 'Set defer date')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const task = await of.createTask({\n name,\n note: options.note,\n project: options.project,\n tags: options.tag,\n due: options.due ? parseDateTime(options.due) : undefined,\n defer: options.defer ? parseDateTime(options.defer) : undefined,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n });\n outputJson(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')\n .option('-D, --defer <date>', 'Set defer date')\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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\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 && {\n due: options.due ? parseDateTime(options.due) : null,\n }),\n ...(options.defer !== undefined && {\n defer: options.defer ? parseDateTime(options.defer) : null,\n }),\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 const task = await of.updateTask(idOrName, updates);\n outputJson(task);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a task')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteTask(idOrName);\n outputJson({ message: 'Task deleted successfully' });\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View task details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const task = await of.getTask(idOrName);\n outputJson(task);\n })\n );\n\n command\n .command('stats')\n .description('Show task statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getTaskStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { outputJson } from './output.js';\n\nexport class OmniFocusCliError extends Error {\n constructor(\n message: string,\n public statusCode: number = 500\n ) {\n super(message);\n this.name = 'OmniFocusCliError';\n }\n}\n\nexport function handleError(error: unknown): never {\n let name = 'unknown_error';\n let detail = 'An unknown error occurred';\n let statusCode = 500;\n\n if (error instanceof OmniFocusCliError) {\n name = 'cli_error';\n detail = error.message;\n statusCode = error.statusCode;\n } else if (error instanceof Error) {\n name = 'omnifocus_error';\n detail = error.message;\n\n if (detail.includes('not found')) {\n statusCode = 404;\n } else if (detail.includes('Multiple')) {\n statusCode = 400;\n }\n }\n\n outputJson({ error: { name, detail, statusCode } });\n process.exit(1);\n}\n","import { handleError } from './errors.js';\n\nexport function withErrorHandling<T extends unknown[], R>(\n fn: (...args: T) => Promise<R>\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args);\n } catch (error) {\n handleError(error);\n }\n };\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(options.completed ? 'task.markComplete();' : 'task.markIncomplete();');\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 dayjs from 'dayjs';\nimport { OmniFocusCliError } from './errors.js';\n\nexport function parseDateTime(input: string): string {\n const d = dayjs(input);\n if (!d.isValid()) {\n throw new OmniFocusCliError(`Invalid date: ${input}`, 400);\n }\n return d.toISOString();\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const filters: ProjectFilters = {\n includeDropped: options.dropped,\n ...(options.folder && { folder: options.folder }),\n ...(options.status && { status: options.status }),\n };\n const projects = await of.listProjects(filters);\n outputJson(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(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const project = await 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 outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\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 const project = await of.updateProject(idOrName, updates);\n outputJson(project);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a project')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteProject(idOrName);\n outputJson({ message: 'Project deleted successfully' });\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View project details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const project = await of.getProject(idOrName);\n outputJson(project);\n })\n );\n\n command\n .command('stats')\n .description('Show project statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getProjectStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.js';\nimport { parseDateTime } from '../lib/dates.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(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const tasks = await of.listInboxTasks();\n outputJson(tasks);\n })\n );\n\n command\n .command('count')\n .description('Get inbox count')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const count = await of.getInboxCount();\n outputJson({ count });\n })\n );\n\n command\n .command('add <name>')\n .description('Add a task to inbox')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-d, --due <date>', 'Set due date')\n .option('-D, --defer <date>', 'Set defer date')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const task = await of.createTask({\n name,\n note: options.note,\n tags: options.tag,\n due: options.due ? parseDateTime(options.due) : undefined,\n defer: options.defer ? parseDateTime(options.defer) : undefined,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n });\n outputJson(task);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (query) => {\n const of = new OmniFocus();\n const tasks = await of.searchTasks(query);\n outputJson(tasks);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const perspectives = await of.listPerspectives();\n outputJson(perspectives);\n })\n );\n\n command\n .command('view <name>')\n .description('View tasks in a perspective')\n .action(\n withErrorHandling(async (name) => {\n const of = new OmniFocus();\n const tasks = await of.getPerspectiveTasks(name);\n outputJson(tasks);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const tags = await of.listTags({\n unusedDays: options.unusedDays,\n sortBy: options.sort,\n activeOnly: options.activeOnly,\n });\n outputJson(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(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const tag = await of.createTag({\n name,\n parent: options.parent,\n status: options.status,\n });\n outputJson(tag);\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View tag details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const tag = await of.getTag(idOrName);\n outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\n const updates: UpdateTagOptions = {\n ...(options.name && { name: options.name }),\n ...(options.status && { status: options.status }),\n };\n const tag = await of.updateTag(idOrName, updates);\n outputJson(tag);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a tag')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteTag(idOrName);\n outputJson({ message: 'Tag deleted successfully' });\n })\n );\n\n command\n .command('stats')\n .description('Show tag usage statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getTagStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const folders = await of.listFolders({ includeDropped: options.dropped });\n outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\n const filters: FolderFilters = { includeDropped: options.dropped };\n const folder = await of.getFolder(idOrName, filters);\n outputJson(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/cli.ts","../src/lib/output.ts","../src/commands/task.ts","../src/lib/errors.ts","../src/lib/command-utils.ts","../src/lib/omnifocus.ts","../src/lib/dates.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","../src/commands/mcp.ts","../src/mcp/server.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';\nimport { createMcpCommand } from './commands/mcp.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());\nprogram.addCommand(createMcpCommand());\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 { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.js';\nimport { parseDateTime } from '../lib/dates.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\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 const tasks = await of.listTasks(filters);\n outputJson(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')\n .option('-D, --defer <date>', 'Set defer date')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const task = await of.createTask({\n name,\n note: options.note,\n project: options.project,\n tags: options.tag,\n due: options.due ? parseDateTime(options.due) : undefined,\n defer: options.defer ? parseDateTime(options.defer) : undefined,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n });\n outputJson(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')\n .option('-D, --defer <date>', 'Set defer date')\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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\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 && {\n due: options.due ? parseDateTime(options.due) : null,\n }),\n ...(options.defer !== undefined && {\n defer: options.defer ? parseDateTime(options.defer) : null,\n }),\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 const task = await of.updateTask(idOrName, updates);\n outputJson(task);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a task')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteTask(idOrName);\n outputJson({ message: 'Task deleted successfully' });\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View task details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const task = await of.getTask(idOrName);\n outputJson(task);\n })\n );\n\n command\n .command('stats')\n .description('Show task statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getTaskStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { outputJson } from './output.js';\n\nexport class OmniFocusCliError extends Error {\n constructor(\n message: string,\n public statusCode: number = 500\n ) {\n super(message);\n this.name = 'OmniFocusCliError';\n }\n}\n\nexport function handleError(error: unknown): never {\n let name = 'unknown_error';\n let detail = 'An unknown error occurred';\n let statusCode = 500;\n\n if (error instanceof OmniFocusCliError) {\n name = 'cli_error';\n detail = error.message;\n statusCode = error.statusCode;\n } else if (error instanceof Error) {\n name = 'omnifocus_error';\n detail = error.message;\n\n if (detail.includes('not found')) {\n statusCode = 404;\n } else if (detail.includes('Multiple')) {\n statusCode = 400;\n }\n }\n\n outputJson({ error: { name, detail, statusCode } });\n process.exit(1);\n}\n","import { handleError } from './errors.js';\n\nexport function withErrorHandling<T extends unknown[], R>(\n fn: (...args: T) => Promise<R>\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args);\n } catch (error) {\n handleError(error);\n }\n };\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(options.completed ? 'task.markComplete();' : 'task.markIncomplete();');\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 dayjs from 'dayjs';\nimport { OmniFocusCliError } from './errors.js';\n\nexport function parseDateTime(input: string): string {\n const d = dayjs(input);\n if (!d.isValid()) {\n throw new OmniFocusCliError(`Invalid date: ${input}`, 400);\n }\n return d.toISOString();\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const filters: ProjectFilters = {\n includeDropped: options.dropped,\n ...(options.folder && { folder: options.folder }),\n ...(options.status && { status: options.status }),\n };\n const projects = await of.listProjects(filters);\n outputJson(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(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const project = await 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 outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\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 const project = await of.updateProject(idOrName, updates);\n outputJson(project);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a project')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteProject(idOrName);\n outputJson({ message: 'Project deleted successfully' });\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View project details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const project = await of.getProject(idOrName);\n outputJson(project);\n })\n );\n\n command\n .command('stats')\n .description('Show project statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getProjectStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.js';\nimport { parseDateTime } from '../lib/dates.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(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const tasks = await of.listInboxTasks();\n outputJson(tasks);\n })\n );\n\n command\n .command('count')\n .description('Get inbox count')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const count = await of.getInboxCount();\n outputJson({ count });\n })\n );\n\n command\n .command('add <name>')\n .description('Add a task to inbox')\n .option('--note <text>', 'Add note')\n .option('-t, --tag <tags...>', 'Add tags')\n .option('-d, --due <date>', 'Set due date')\n .option('-D, --defer <date>', 'Set defer date')\n .option('-f, --flagged', 'Flag the task')\n .option('-e, --estimate <minutes>', 'Estimated time in minutes', parseInt)\n .action(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const task = await of.createTask({\n name,\n note: options.note,\n tags: options.tag,\n due: options.due ? parseDateTime(options.due) : undefined,\n defer: options.defer ? parseDateTime(options.defer) : undefined,\n flagged: options.flagged,\n estimatedMinutes: options.estimate,\n });\n outputJson(task);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (query) => {\n const of = new OmniFocus();\n const tasks = await of.searchTasks(query);\n outputJson(tasks);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const perspectives = await of.listPerspectives();\n outputJson(perspectives);\n })\n );\n\n command\n .command('view <name>')\n .description('View tasks in a perspective')\n .action(\n withErrorHandling(async (name) => {\n const of = new OmniFocus();\n const tasks = await of.getPerspectiveTasks(name);\n outputJson(tasks);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const tags = await of.listTags({\n unusedDays: options.unusedDays,\n sortBy: options.sort,\n activeOnly: options.activeOnly,\n });\n outputJson(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(\n withErrorHandling(async (name, options) => {\n const of = new OmniFocus();\n const tag = await of.createTag({\n name,\n parent: options.parent,\n status: options.status,\n });\n outputJson(tag);\n })\n );\n\n command\n .command('view <idOrName>')\n .description('View tag details')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n const tag = await of.getTag(idOrName);\n outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\n const updates: UpdateTagOptions = {\n ...(options.name && { name: options.name }),\n ...(options.status && { status: options.status }),\n };\n const tag = await of.updateTag(idOrName, updates);\n outputJson(tag);\n })\n );\n\n command\n .command('delete <idOrName>')\n .alias('rm')\n .description('Delete a tag')\n .action(\n withErrorHandling(async (idOrName) => {\n const of = new OmniFocus();\n await of.deleteTag(idOrName);\n outputJson({ message: 'Tag deleted successfully' });\n })\n );\n\n command\n .command('stats')\n .description('Show tag usage statistics')\n .action(\n withErrorHandling(async () => {\n const of = new OmniFocus();\n const stats = await of.getTagStats();\n outputJson(stats);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { OmniFocus } from '../lib/omnifocus.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(\n withErrorHandling(async (options) => {\n const of = new OmniFocus();\n const folders = await of.listFolders({ includeDropped: options.dropped });\n outputJson(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(\n withErrorHandling(async (idOrName, options) => {\n const of = new OmniFocus();\n const filters: FolderFilters = { includeDropped: options.dropped };\n const folder = await of.getFolder(idOrName, filters);\n outputJson(folder);\n })\n );\n\n return command;\n}\n","import { Command } from 'commander';\nimport { runMcpServer } from '../mcp/server.js';\n\nexport function createMcpCommand(): Command {\n const cmd = new Command('mcp').description('Run OmniFocus MCP server');\n\n cmd.action(async () => {\n await runMcpServer();\n });\n\n return cmd;\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { OmniFocus } from '../lib/omnifocus.js';\n\nconst server = new McpServer({\n name: 'omnifocus',\n version: '1.0.0',\n});\n\nconst of = new OmniFocus();\n\nfunction jsonResponse(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\nserver.tool(\n 'list_tasks',\n 'List tasks with optional filtering',\n {\n includeCompleted: z.boolean().optional().describe('Include completed tasks'),\n includeDropped: z.boolean().optional().describe('Include dropped tasks'),\n flagged: z.boolean().optional().describe('Only show flagged tasks'),\n project: z.string().optional().describe('Filter by project name'),\n tag: z.string().optional().describe('Filter by tag name'),\n },\n async (filters) => jsonResponse(await of.listTasks(filters))\n);\n\nserver.tool(\n 'get_task',\n 'Get a specific task by ID or name',\n { idOrName: z.string().describe('Task ID or name') },\n async ({ idOrName }) => jsonResponse(await of.getTask(idOrName))\n);\n\nserver.tool(\n 'create_task',\n 'Create a new task',\n {\n name: z.string().describe('Task name'),\n note: z.string().optional().describe('Task note'),\n project: z.string().optional().describe('Project to add task to'),\n tags: z.array(z.string()).optional().describe('Tags to assign'),\n defer: z.string().optional().describe('Defer date (ISO 8601)'),\n due: z.string().optional().describe('Due date (ISO 8601)'),\n flagged: z.boolean().optional().describe('Flag the task'),\n estimatedMinutes: z.number().optional().describe('Estimated duration in minutes'),\n },\n async (options) => jsonResponse(await of.createTask(options))\n);\n\nserver.tool(\n 'update_task',\n 'Update an existing task',\n {\n idOrName: z.string().describe('Task ID or name'),\n name: z.string().optional().describe('New task name'),\n note: z.string().optional().describe('New task note'),\n project: z.string().optional().describe('Move to project'),\n tags: z.array(z.string()).optional().describe('Replace tags'),\n defer: z.string().optional().describe('New defer date (ISO 8601)'),\n due: z.string().optional().describe('New due date (ISO 8601)'),\n flagged: z.boolean().optional().describe('Flag/unflag the task'),\n estimatedMinutes: z.number().optional().describe('New estimated duration'),\n completed: z.boolean().optional().describe('Mark complete/incomplete'),\n },\n async ({ idOrName, ...options }) => jsonResponse(await of.updateTask(idOrName, options))\n);\n\nserver.tool(\n 'delete_task',\n 'Delete a task',\n { idOrName: z.string().describe('Task ID or name') },\n async ({ idOrName }) => {\n await of.deleteTask(idOrName);\n return jsonResponse({ deleted: true });\n }\n);\n\nserver.tool(\n 'search_tasks',\n 'Search tasks by name or note content',\n { query: z.string().describe('Search query') },\n async ({ query }) => jsonResponse(await of.searchTasks(query))\n);\n\nserver.tool(\n 'get_task_stats',\n 'Get task statistics',\n {},\n async () => jsonResponse(await of.getTaskStats())\n);\n\nserver.tool(\n 'list_inbox',\n 'List all inbox tasks',\n {},\n async () => jsonResponse(await of.listInboxTasks())\n);\n\nserver.tool(\n 'get_inbox_count',\n 'Get the number of inbox tasks',\n {},\n async () => jsonResponse({ count: await of.getInboxCount() })\n);\n\nserver.tool(\n 'list_projects',\n 'List projects with optional filtering',\n {\n includeDropped: z.boolean().optional().describe('Include dropped projects'),\n status: z.enum(['active', 'on hold', 'dropped']).optional().describe('Filter by status'),\n folder: z.string().optional().describe('Filter by folder name'),\n },\n async (filters) => jsonResponse(await of.listProjects(filters))\n);\n\nserver.tool(\n 'get_project',\n 'Get a specific project by ID or name',\n { idOrName: z.string().describe('Project ID or name') },\n async ({ idOrName }) => jsonResponse(await of.getProject(idOrName))\n);\n\nserver.tool(\n 'create_project',\n 'Create a new project',\n {\n name: z.string().describe('Project name'),\n note: z.string().optional().describe('Project note'),\n folder: z.string().optional().describe('Folder to create project in'),\n sequential: z.boolean().optional().describe('Sequential project (tasks must be done in order)'),\n tags: z.array(z.string()).optional().describe('Tags to assign'),\n status: z.enum(['active', 'on hold', 'dropped']).optional().describe('Initial status'),\n },\n async (options) => jsonResponse(await of.createProject(options))\n);\n\nserver.tool(\n 'update_project',\n 'Update an existing project',\n {\n idOrName: z.string().describe('Project ID or name'),\n name: z.string().optional().describe('New project name'),\n note: z.string().optional().describe('New project note'),\n folder: z.string().optional().describe('Move to folder'),\n sequential: z.boolean().optional().describe('Set sequential/parallel'),\n tags: z.array(z.string()).optional().describe('Replace tags'),\n status: z.enum(['active', 'on hold', 'dropped']).optional().describe('New status'),\n },\n async ({ idOrName, ...options }) => jsonResponse(await of.updateProject(idOrName, options))\n);\n\nserver.tool(\n 'delete_project',\n 'Delete a project',\n { idOrName: z.string().describe('Project ID or name') },\n async ({ idOrName }) => {\n await of.deleteProject(idOrName);\n return jsonResponse({ deleted: true });\n }\n);\n\nserver.tool(\n 'get_project_stats',\n 'Get project statistics',\n {},\n async () => jsonResponse(await of.getProjectStats())\n);\n\nserver.tool(\n 'list_perspectives',\n 'List all available perspectives',\n {},\n async () => jsonResponse(await of.listPerspectives())\n);\n\nserver.tool(\n 'get_perspective_tasks',\n 'Get tasks from a specific perspective',\n { name: z.string().describe('Perspective name (e.g., Inbox, Flagged, or custom perspective)') },\n async ({ name }) => jsonResponse(await of.getPerspectiveTasks(name))\n);\n\nserver.tool(\n 'list_tags',\n 'List all tags with optional filtering and sorting',\n {\n unusedDays: z.number().optional().describe('Only show tags unused for this many days'),\n sortBy: z.enum(['name', 'usage', 'activity']).optional().describe('Sort order'),\n activeOnly: z.boolean().optional().describe('Only count active tasks'),\n },\n async (options) => jsonResponse(await of.listTags(options))\n);\n\nserver.tool(\n 'get_tag',\n 'Get a specific tag by ID or name',\n { idOrName: z.string().describe('Tag ID, name, or path (e.g., \"Parent/Child\")') },\n async ({ idOrName }) => jsonResponse(await of.getTag(idOrName))\n);\n\nserver.tool(\n 'create_tag',\n 'Create a new tag',\n {\n name: z.string().describe('Tag name'),\n parent: z.string().optional().describe('Parent tag name or path'),\n status: z.enum(['active', 'on hold', 'dropped']).optional().describe('Initial status'),\n },\n async (options) => jsonResponse(await of.createTag(options))\n);\n\nserver.tool(\n 'update_tag',\n 'Update an existing tag',\n {\n idOrName: z.string().describe('Tag ID, name, or path'),\n name: z.string().optional().describe('New tag name'),\n status: z.enum(['active', 'on hold', 'dropped']).optional().describe('New status'),\n },\n async ({ idOrName, ...options }) => jsonResponse(await of.updateTag(idOrName, options))\n);\n\nserver.tool(\n 'delete_tag',\n 'Delete a tag',\n { idOrName: z.string().describe('Tag ID, name, or path') },\n async ({ idOrName }) => {\n await of.deleteTag(idOrName);\n return jsonResponse({ deleted: true });\n }\n);\n\nserver.tool(\n 'get_tag_stats',\n 'Get tag statistics',\n {},\n async () => jsonResponse(await of.getTagStats())\n);\n\nserver.tool(\n 'list_folders',\n 'List all folders',\n { includeDropped: z.boolean().optional().describe('Include dropped folders') },\n async (filters) => jsonResponse(await of.listFolders(filters))\n);\n\nserver.tool(\n 'get_folder',\n 'Get a specific folder by ID or name',\n {\n idOrName: z.string().describe('Folder ID or name'),\n includeDropped: z.boolean().optional().describe('Include dropped children'),\n },\n async ({ idOrName, includeDropped }) => jsonResponse(await of.getFolder(idOrName, { includeDropped }))\n);\n\nexport async function runMcpServer() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":["Command","of","Command","Command","of","Command","Command","of","Command","Command","of","Command","Command","of","Command","Command","of","Command","Command","of","Command","Command","Command"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stephendolan/omnifocus-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "A command-line interface for OmniFocus on macOS",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -48,8 +48,10 @@
|
|
|
48
48
|
"bun": ">=1.0.0"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
51
52
|
"commander": "^12.1.0",
|
|
52
|
-
"dayjs": "^1.11.19"
|
|
53
|
+
"dayjs": "^1.11.19",
|
|
54
|
+
"zod": "^3.24.0"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"@biomejs/biome": "^1.9.4",
|