@task-mcp/cli 1.0.21 → 1.0.22

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/src/index.ts DELETED
@@ -1,277 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * Task MCP CLI - Zero-dependency terminal visualization
4
- *
5
- * Usage:
6
- * task # Show dashboard (default)
7
- * task dashboard [ws] # Show workspace dashboard
8
- * task d [ws] # Alias for dashboard
9
- * task list # List tasks
10
- * task ls # Alias for list
11
- * task workspaces # List workspaces
12
- * task ws # Alias for workspaces
13
- * task help # Show help
14
- */
15
-
16
- import { c, banner } from "./ansi.js";
17
- import { dashboard } from "./commands/dashboard.js";
18
- import { listTasksCmd, listWorkspacesCmd } from "./commands/list.js";
19
- import { startInteractive } from "./interactive.js";
20
- import {
21
- inboxAddCmd,
22
- inboxListCmd,
23
- inboxGetCmd,
24
- inboxPromoteCmd,
25
- inboxDiscardCmd,
26
- inboxDeleteCmd,
27
- inboxCountCmd,
28
- } from "./commands/inbox.js";
29
-
30
- import pkg from "../package.json" with { type: "json" };
31
- export const VERSION = pkg.version;
32
-
33
- export interface ParsedArgs {
34
- command: string;
35
- args: string[];
36
- flags: Record<string, string | boolean>;
37
- }
38
-
39
- export function parseArgs(argv: string[]): ParsedArgs {
40
- const args = argv.slice(2); // Skip bun and script path
41
- const flags: Record<string, string | boolean> = {};
42
- const positional: string[] = [];
43
-
44
- for (let i = 0; i < args.length; i++) {
45
- const arg = args[i]!;
46
- if (arg.startsWith("--")) {
47
- const [key, value] = arg.slice(2).split("=");
48
- if (value !== undefined) {
49
- flags[key!] = value;
50
- } else if (args[i + 1] && !args[i + 1]!.startsWith("-")) {
51
- flags[key!] = args[++i]!;
52
- } else {
53
- flags[key!] = true;
54
- }
55
- } else if (arg.startsWith("-") && arg.length === 2) {
56
- const key = arg.slice(1);
57
- if (args[i + 1] && !args[i + 1]!.startsWith("-")) {
58
- flags[key] = args[++i]!;
59
- } else {
60
- flags[key] = true;
61
- }
62
- } else {
63
- positional.push(arg);
64
- }
65
- }
66
-
67
- return {
68
- command: positional[0] ?? "dashboard",
69
- args: positional.slice(1),
70
- flags,
71
- };
72
- }
73
-
74
- function showHelp(): void {
75
- console.log(`
76
- ${c.cyan(c.bold("Task MCP CLI"))} ${c.gray(`v${VERSION}`)}
77
- ${c.dim("Zero-dependency terminal visualization for task-mcp")}
78
-
79
- ${c.yellow("USAGE")}
80
- ${c.bold("task")} [command] [options]
81
-
82
- ${c.yellow("COMMANDS")}
83
- ${c.cyan("dashboard")} [workspace] Show workspace dashboard (default)
84
- ${c.cyan("d")} [workspace] Alias for dashboard
85
- ${c.cyan("list")} List all tasks
86
- ${c.cyan("ls")} Alias for list
87
- ${c.cyan("workspaces")} List all workspaces
88
- ${c.cyan("ws")} Alias for workspaces
89
- ${c.cyan("inbox")} <subcommand> Manage inbox (add/list/get/promote/discard)
90
- ${c.cyan("interactive")} Start interactive mode
91
- ${c.cyan("i")} Alias for interactive
92
- ${c.cyan("help")} Show this help message
93
- ${c.cyan("version")} Show version
94
-
95
- ${c.yellow("INBOX SUBCOMMANDS")}
96
- ${c.cyan("inbox")} "content" Quick capture to inbox
97
- ${c.cyan("inbox add")} "content" Add item with natural language
98
- ${c.cyan("inbox list")} List pending items
99
- ${c.cyan("inbox get")} <id> Show item details
100
- ${c.cyan("inbox promote")} <id> Promote to task
101
- ${c.cyan("inbox discard")} <id> Discard item
102
- ${c.cyan("inbox count")} Show pending count
103
-
104
- ${c.yellow("OPTIONS")}
105
- ${c.cyan("-i, --interactive")} Start interactive mode
106
- ${c.cyan("--status")} <status> Filter tasks by status (pending,in_progress,blocked,completed,cancelled)
107
- ${c.cyan("--priority")} <priority> Filter tasks by priority (critical,high,medium,low)
108
- ${c.cyan("--all")} Include completed/cancelled tasks
109
-
110
- ${c.yellow("EXAMPLES")}
111
- ${c.dim("# Show dashboard for all projects")}
112
- task
113
-
114
- ${c.dim("# Show dashboard for a specific project")}
115
- task dashboard proj_abc123
116
-
117
- ${c.dim("# List pending high-priority tasks")}
118
- task list --status pending --priority high
119
-
120
- ${c.dim("# List all workspaces")}
121
- task workspaces --all
122
- `);
123
- }
124
-
125
- function showVersion(): void {
126
- console.log(`task-mcp-cli v${VERSION}`);
127
- }
128
-
129
- async function handleInboxCommand(
130
- args: string[],
131
- flags: Record<string, string | boolean>
132
- ): Promise<void> {
133
- const subcommand = args[0];
134
-
135
- // If first arg is not a subcommand, treat it as content for quick capture
136
- const subcommands = ["add", "list", "ls", "get", "promote", "discard", "delete", "count"];
137
- if (subcommand && !subcommands.includes(subcommand)) {
138
- // Quick capture: task inbox "content here"
139
- await inboxAddCmd({ content: args.join(" ") });
140
- return;
141
- }
142
-
143
- switch (subcommand) {
144
- case "add":
145
- if (!args[1]) {
146
- console.log(c.error("Usage: task inbox add \"content\""));
147
- return;
148
- }
149
- await inboxAddCmd({ content: args.slice(1).join(" ") });
150
- break;
151
-
152
- case "list":
153
- case "ls":
154
- await inboxListCmd({
155
- all: flags.all === true,
156
- status: flags.status as "pending" | "promoted" | "discarded" | undefined,
157
- });
158
- break;
159
-
160
- case "get":
161
- if (!args[1]) {
162
- console.log(c.error("Usage: task inbox get <item-id>"));
163
- return;
164
- }
165
- await inboxGetCmd(args[1]);
166
- break;
167
-
168
- case "promote":
169
- if (!args[1]) {
170
- console.log(c.error("Usage: task inbox promote <item-id> [--priority <p>]"));
171
- return;
172
- }
173
- await inboxPromoteCmd({
174
- itemId: args[1],
175
- title: flags.title as string | undefined,
176
- priority: flags.priority as "critical" | "high" | "medium" | "low" | undefined,
177
- });
178
- break;
179
-
180
- case "discard":
181
- if (!args[1]) {
182
- console.log(c.error("Usage: task inbox discard <item-id>"));
183
- return;
184
- }
185
- await inboxDiscardCmd(args[1]);
186
- break;
187
-
188
- case "delete":
189
- if (!args[1]) {
190
- console.log(c.error("Usage: task inbox delete <item-id>"));
191
- return;
192
- }
193
- await inboxDeleteCmd(args[1]);
194
- break;
195
-
196
- case "count":
197
- await inboxCountCmd();
198
- break;
199
-
200
- default:
201
- // No subcommand = list pending
202
- await inboxListCmd({ all: false });
203
- break;
204
- }
205
- }
206
-
207
- async function main(): Promise<void> {
208
- const { command, args, flags } = parseArgs(process.argv);
209
-
210
- // Handle -i flag for interactive mode
211
- if (flags.i === true || flags.interactive === true) {
212
- await startInteractive();
213
- return;
214
- }
215
-
216
- try {
217
- switch (command) {
218
- case "dashboard":
219
- case "d":
220
- await dashboard(args[0]);
221
- break;
222
-
223
- case "list":
224
- case "ls":
225
- await listTasksCmd({
226
- workspace: args[0],
227
- status: flags.status as string | undefined,
228
- priority: flags.priority as string | undefined,
229
- all: flags.all === true,
230
- });
231
- break;
232
-
233
- case "workspaces":
234
- case "ws":
235
- await listWorkspacesCmd();
236
- break;
237
-
238
- case "interactive":
239
- case "i":
240
- await startInteractive();
241
- break;
242
-
243
- case "inbox":
244
- await handleInboxCommand(args, flags);
245
- break;
246
-
247
- case "help":
248
- case "-h":
249
- case "--help":
250
- showHelp();
251
- break;
252
-
253
- case "version":
254
- case "-v":
255
- case "--version":
256
- showVersion();
257
- break;
258
-
259
- default:
260
- console.log(c.error(`Unknown command: ${command}`));
261
- console.log(c.dim("Run 'task help' for usage information."));
262
- process.exit(1);
263
- }
264
- } catch (error) {
265
- if (error instanceof Error) {
266
- console.error(c.error(`Error: ${error.message}`));
267
- } else {
268
- console.error(c.error("An unexpected error occurred"));
269
- }
270
- process.exit(1);
271
- }
272
- }
273
-
274
- // Only run main when directly executed, not when imported
275
- if (import.meta.main) {
276
- main();
277
- }
@@ -1,254 +0,0 @@
1
- /**
2
- * Interactive Mode for Task MCP CLI
3
- * Zero-dependency implementation using Bun native capabilities
4
- */
5
-
6
- import { c, banner } from "./ansi.js";
7
- import { dashboard } from "./commands/dashboard.js";
8
- import { listTasksCmd, listWorkspacesCmd } from "./commands/list.js";
9
- import * as readline from "node:readline";
10
- import {
11
- MENU_SEPARATOR_WIDTH,
12
- ERROR_MESSAGE_DELAY_MS,
13
- WELCOME_SCREEN_DELAY_MS,
14
- } from "./constants.js";
15
-
16
- interface MenuOption {
17
- key: string;
18
- label: string;
19
- description?: string;
20
- action: () => Promise<void> | void;
21
- }
22
-
23
- /**
24
- * Simple prompt for user input
25
- */
26
- async function prompt(question: string): Promise<string> {
27
- const rl = readline.createInterface({
28
- input: process.stdin,
29
- output: process.stdout,
30
- });
31
-
32
- return new Promise((resolve) => {
33
- rl.question(question, (answer) => {
34
- rl.close();
35
- resolve(answer.trim());
36
- });
37
- });
38
- }
39
-
40
- /**
41
- * Display menu and get user selection
42
- */
43
- async function showMenu(title: string, options: MenuOption[]): Promise<void> {
44
- console.clear();
45
- console.log(banner("TASK MCP"));
46
- console.log();
47
- console.log(c.bold(c.cyan(title)));
48
- console.log(c.dim("─".repeat(MENU_SEPARATOR_WIDTH)));
49
- console.log();
50
-
51
- for (const opt of options) {
52
- const desc = opt.description ? c.dim(` - ${opt.description}`) : "";
53
- console.log(` ${c.yellow(opt.key)} ${opt.label}${desc}`);
54
- }
55
-
56
- console.log();
57
- const choice = await prompt(c.cyan("Select option: "));
58
-
59
- const selected = options.find((o) => o.key.toLowerCase() === choice.toLowerCase());
60
- if (selected) {
61
- await selected.action();
62
- } else if (choice !== "") {
63
- console.log(c.error(`Invalid option: ${choice}`));
64
- await sleep(ERROR_MESSAGE_DELAY_MS);
65
- }
66
- }
67
-
68
- /**
69
- * Sleep utility
70
- */
71
- function sleep(ms: number): Promise<void> {
72
- return new Promise((resolve) => setTimeout(resolve, ms));
73
- }
74
-
75
- /**
76
- * Wait for any key press
77
- */
78
- async function waitForKey(message: string = "Press Enter to continue..."): Promise<void> {
79
- await prompt(c.dim(message));
80
- }
81
-
82
- /**
83
- * Main Menu
84
- */
85
- async function mainMenu(): Promise<boolean> {
86
- const options: MenuOption[] = [
87
- {
88
- key: "d",
89
- label: "Dashboard",
90
- description: "View workspace dashboard",
91
- action: async () => {
92
- await dashboardMenu();
93
- },
94
- },
95
- {
96
- key: "w",
97
- label: "Workspaces",
98
- description: "List workspaces",
99
- action: async () => {
100
- await workspacesMenu();
101
- },
102
- },
103
- {
104
- key: "t",
105
- label: "Tasks",
106
- description: "List and filter tasks",
107
- action: async () => {
108
- await tasksMenu();
109
- },
110
- },
111
- {
112
- key: "x",
113
- label: "Exit",
114
- description: "Exit interactive mode",
115
- action: () => {
116
- console.log(c.dim("Goodbye!"));
117
- process.exit(0);
118
- },
119
- },
120
- ];
121
-
122
- await showMenu("Main Menu", options);
123
- return true;
124
- }
125
-
126
- /**
127
- * Dashboard Menu
128
- */
129
- async function dashboardMenu(): Promise<void> {
130
- console.clear();
131
- console.log(c.bold(c.cyan("Dashboard")));
132
- console.log(c.dim("─".repeat(MENU_SEPARATOR_WIDTH)));
133
- console.log();
134
-
135
- const workspace = await prompt(c.cyan("Workspace name (Enter for current): "));
136
-
137
- console.log();
138
- await dashboard(workspace || undefined);
139
- console.log();
140
- await waitForKey();
141
- }
142
-
143
- /**
144
- * Workspaces Menu
145
- */
146
- async function workspacesMenu(): Promise<void> {
147
- const options: MenuOption[] = [
148
- {
149
- key: "l",
150
- label: "List Workspaces",
151
- action: async () => {
152
- console.clear();
153
- await listWorkspacesCmd();
154
- console.log();
155
- await waitForKey();
156
- },
157
- },
158
- {
159
- key: "b",
160
- label: "Back to Main Menu",
161
- action: () => {},
162
- },
163
- ];
164
-
165
- await showMenu("Workspaces", options);
166
- }
167
-
168
- /**
169
- * Tasks Menu
170
- */
171
- async function tasksMenu(): Promise<void> {
172
- const options: MenuOption[] = [
173
- {
174
- key: "l",
175
- label: "List All Tasks",
176
- action: async () => {
177
- console.clear();
178
- await listTasksCmd({ all: false });
179
- console.log();
180
- await waitForKey();
181
- },
182
- },
183
- {
184
- key: "p",
185
- label: "Filter by Priority",
186
- action: async () => {
187
- console.clear();
188
- const priority = await prompt(c.cyan("Priority (critical/high/medium/low): "));
189
- if (priority) {
190
- await listTasksCmd({ priority });
191
- }
192
- console.log();
193
- await waitForKey();
194
- },
195
- },
196
- {
197
- key: "s",
198
- label: "Filter by Status",
199
- action: async () => {
200
- console.clear();
201
- const status = await prompt(c.cyan("Status (pending/in_progress/blocked/completed): "));
202
- if (status) {
203
- await listTasksCmd({ status });
204
- }
205
- console.log();
206
- await waitForKey();
207
- },
208
- },
209
- {
210
- key: "a",
211
- label: "All (include completed)",
212
- action: async () => {
213
- console.clear();
214
- await listTasksCmd({ all: true });
215
- console.log();
216
- await waitForKey();
217
- },
218
- },
219
- {
220
- key: "b",
221
- label: "Back to Main Menu",
222
- action: () => {},
223
- },
224
- ];
225
-
226
- await showMenu("Tasks", options);
227
- }
228
-
229
- /**
230
- * Start interactive mode
231
- */
232
- export async function startInteractive(): Promise<void> {
233
- console.clear();
234
- console.log(banner("TASK MCP"));
235
- console.log();
236
- console.log(c.bold("Welcome to Task MCP Interactive Mode"));
237
- console.log(c.dim("Navigate using keyboard shortcuts"));
238
- console.log();
239
- await sleep(WELCOME_SCREEN_DELAY_MS);
240
-
241
- while (true) {
242
- try {
243
- await mainMenu();
244
- } catch (error) {
245
- if (error instanceof Error && error.message.includes("readline was closed")) {
246
- // User pressed Ctrl+C or Ctrl+D
247
- console.log();
248
- console.log(c.dim("Goodbye!"));
249
- process.exit(0);
250
- }
251
- throw error;
252
- }
253
- }
254
- }