shipsheet 0.0.1 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # shipsheet
2
+
3
+ CLI for managing a local `tasks.json` ship sheet - exportable to Kanban or Google Sheets.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g shipsheet
9
+ # or
10
+ npx shipsheet
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Add tasks
17
+ ss add "Build authentication" -p high -t "feature,backend" --due 2026-02-01
18
+ ss add "Fix login bug" -d "Users can't login with SSO" -p critical
19
+
20
+ # List tasks
21
+ ss list # All tasks
22
+ ss ls -s in-progress # Filter by status
23
+ ss ls -p high # Filter by priority
24
+ ss ls -t feature # Filter by tag
25
+
26
+ # Manage tasks
27
+ ss show <id> # Show task details
28
+ ss update <id> -t "New title" -p medium
29
+ ss move <id> in-progress # Move to status
30
+ ss done <id> # Mark as done
31
+ ss rm <id> # Remove task
32
+
33
+ # Export
34
+ ss export # JSON (default)
35
+ ss export -f csv # CSV for spreadsheets
36
+ ss export -f kanban # Kanban board format
37
+ ss export -f sheets # Google Sheets array format
38
+ ss export -f markdown # Markdown format
39
+ ss export -f csv -o tasks.csv # Save to file
40
+ ```
41
+
42
+ ## Task Structure
43
+
44
+ ```json
45
+ {
46
+ "id": "mkwbbi25gbew2",
47
+ "title": "Build authentication",
48
+ "description": "Optional description",
49
+ "status": "todo",
50
+ "priority": "high",
51
+ "tags": ["feature", "backend"],
52
+ "dueDate": "2026-02-01",
53
+ "createdAt": "2026-01-27T08:00:00.000Z",
54
+ "updatedAt": "2026-01-27T08:00:00.000Z"
55
+ }
56
+ ```
57
+
58
+ ## Statuses
59
+
60
+ - `todo` - Not started
61
+ - `in-progress` - Currently working
62
+ - `done` - Completed
63
+ - `blocked` - Blocked by something
64
+
65
+ ## Priorities
66
+
67
+ - `critical` - 🔴 Drop everything
68
+ - `high` - 🟠 Important
69
+ - `medium` - 🟡 Normal (default)
70
+ - `low` - 🟢 When time permits
71
+
72
+ ## Export Formats
73
+
74
+ | Format | Use Case |
75
+ |--------|----------|
76
+ | `json` | Full data backup, API integration |
77
+ | `csv` | Google Sheets, Excel import |
78
+ | `kanban` | Kanban board tools (Trello, Notion) |
79
+ | `sheets` | Google Sheets API (2D array) |
80
+ | `markdown` | Documentation, GitHub issues |
81
+
82
+ ## AI Skills
83
+
84
+ Add shipsheet as a skill for AI coding agents:
85
+
86
+ ```bash
87
+ npx skills ahmadawais/shipsheet
88
+ ```
89
+
90
+ This teaches AI agents how to use shipsheet commands in your projects.
91
+
92
+ ## License
93
+
94
+ MIT
@@ -0,0 +1,6 @@
1
+ import type { Task } from './types.js';
2
+ export declare function toCSV(): string;
3
+ export declare function toKanban(): Record<string, Task[]>;
4
+ export declare function toGoogleSheetsFormat(): string[][];
5
+ export declare function toJSON(): string;
6
+ export declare function toMarkdown(): string;
package/dist/export.js ADDED
@@ -0,0 +1,69 @@
1
+ import { loadSheet } from './store.js';
2
+ export function toCSV() {
3
+ const sheet = loadSheet();
4
+ const headers = ['ID', 'Title', 'Description', 'Status', 'Priority', 'Tags', 'Due Date', 'Created', 'Updated'];
5
+ const rows = sheet.tasks.map((t) => [
6
+ t.id,
7
+ `"${t.title.replace(/"/g, '""')}"`,
8
+ `"${(t.description || '').replace(/"/g, '""')}"`,
9
+ t.status,
10
+ t.priority,
11
+ `"${(t.tags || []).join(', ')}"`,
12
+ t.dueDate || '',
13
+ t.createdAt,
14
+ t.updatedAt,
15
+ ]);
16
+ return [headers.join(','), ...rows.map((r) => r.join(','))].join('\n');
17
+ }
18
+ export function toKanban() {
19
+ const sheet = loadSheet();
20
+ return {
21
+ todo: sheet.tasks.filter((t) => t.status === 'todo'),
22
+ 'in-progress': sheet.tasks.filter((t) => t.status === 'in-progress'),
23
+ done: sheet.tasks.filter((t) => t.status === 'done'),
24
+ blocked: sheet.tasks.filter((t) => t.status === 'blocked'),
25
+ };
26
+ }
27
+ export function toGoogleSheetsFormat() {
28
+ const sheet = loadSheet();
29
+ const headers = ['ID', 'Title', 'Description', 'Status', 'Priority', 'Tags', 'Due Date', 'Created', 'Updated'];
30
+ const rows = sheet.tasks.map((t) => [
31
+ t.id,
32
+ t.title,
33
+ t.description || '',
34
+ t.status,
35
+ t.priority,
36
+ (t.tags || []).join(', '),
37
+ t.dueDate || '',
38
+ t.createdAt,
39
+ t.updatedAt,
40
+ ]);
41
+ return [headers, ...rows];
42
+ }
43
+ export function toJSON() {
44
+ const sheet = loadSheet();
45
+ return JSON.stringify(sheet, null, 2);
46
+ }
47
+ export function toMarkdown() {
48
+ const kanban = toKanban();
49
+ let md = '# Ship Sheet\n\n';
50
+ for (const [status, tasks] of Object.entries(kanban)) {
51
+ md += `## ${status.charAt(0).toUpperCase() + status.slice(1)}\n\n`;
52
+ if (tasks.length === 0) {
53
+ md += '_No tasks_\n\n';
54
+ }
55
+ else {
56
+ for (const task of tasks) {
57
+ const priority = task.priority === 'critical' ? '🔴' : task.priority === 'high' ? '🟠' : task.priority === 'medium' ? '🟡' : '🟢';
58
+ md += `- ${priority} **${task.title}**`;
59
+ if (task.description)
60
+ md += ` - ${task.description}`;
61
+ if (task.dueDate)
62
+ md += ` (Due: ${task.dueDate})`;
63
+ md += '\n';
64
+ }
65
+ md += '\n';
66
+ }
67
+ }
68
+ return md;
69
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { writeFileSync } from 'node:fs';
4
+ import { addTask, listTasks, updateTask, removeTask, moveTask, getTask } from './store.js';
5
+ import { toCSV, toKanban, toJSON, toMarkdown, toGoogleSheetsFormat } from './export.js';
6
+ const program = new Command();
7
+ program
8
+ .name('shipsheet')
9
+ .description('CLI for managing a local tasks.json ship sheet')
10
+ .version('1.0.0');
11
+ program
12
+ .command('add <title>')
13
+ .description('Add a new task')
14
+ .option('-d, --description <desc>', 'Task description')
15
+ .option('-s, --status <status>', 'Task status (todo, in-progress, done, blocked)', 'todo')
16
+ .option('-p, --priority <priority>', 'Task priority (low, medium, high, critical)', 'medium')
17
+ .option('-t, --tags <tags>', 'Comma-separated tags')
18
+ .option('--due <date>', 'Due date (YYYY-MM-DD)')
19
+ .action((title, opts) => {
20
+ const task = addTask(title, {
21
+ description: opts.description,
22
+ status: opts.status,
23
+ priority: opts.priority,
24
+ tags: opts.tags?.split(',').map((t) => t.trim()),
25
+ dueDate: opts.due,
26
+ });
27
+ console.log(`✓ Added task: ${task.title} [${task.id}]`);
28
+ });
29
+ program
30
+ .command('list')
31
+ .alias('ls')
32
+ .description('List all tasks')
33
+ .option('-s, --status <status>', 'Filter by status')
34
+ .option('-p, --priority <priority>', 'Filter by priority')
35
+ .option('-t, --tag <tag>', 'Filter by tag')
36
+ .action((opts) => {
37
+ const tasks = listTasks({
38
+ status: opts.status,
39
+ priority: opts.priority,
40
+ tag: opts.tag,
41
+ });
42
+ if (tasks.length === 0) {
43
+ console.log('No tasks found.');
44
+ return;
45
+ }
46
+ const statusIcon = {
47
+ todo: '○',
48
+ 'in-progress': '◐',
49
+ done: '●',
50
+ blocked: '✕',
51
+ };
52
+ const priorityColor = {
53
+ critical: '\x1b[31m',
54
+ high: '\x1b[33m',
55
+ medium: '\x1b[36m',
56
+ low: '\x1b[90m',
57
+ };
58
+ const reset = '\x1b[0m';
59
+ for (const task of tasks) {
60
+ const icon = statusIcon[task.status];
61
+ const color = priorityColor[task.priority];
62
+ const tags = task.tags?.length ? ` [${task.tags.join(', ')}]` : '';
63
+ const due = task.dueDate ? ` (due: ${task.dueDate})` : '';
64
+ console.log(`${icon} ${color}${task.id.slice(0, 7)}${reset} ${task.title}${tags}${due}`);
65
+ }
66
+ });
67
+ program
68
+ .command('show <id>')
69
+ .description('Show task details')
70
+ .action((id) => {
71
+ const task = getTask(id);
72
+ if (!task) {
73
+ console.error(`Task not found: ${id}`);
74
+ process.exit(1);
75
+ }
76
+ console.log(`ID: ${task.id}`);
77
+ console.log(`Title: ${task.title}`);
78
+ console.log(`Description: ${task.description || '-'}`);
79
+ console.log(`Status: ${task.status}`);
80
+ console.log(`Priority: ${task.priority}`);
81
+ console.log(`Tags: ${task.tags?.join(', ') || '-'}`);
82
+ console.log(`Due: ${task.dueDate || '-'}`);
83
+ console.log(`Created: ${task.createdAt}`);
84
+ console.log(`Updated: ${task.updatedAt}`);
85
+ });
86
+ program
87
+ .command('update <id>')
88
+ .description('Update a task')
89
+ .option('-t, --title <title>', 'New title')
90
+ .option('-d, --description <desc>', 'New description')
91
+ .option('-s, --status <status>', 'New status')
92
+ .option('-p, --priority <priority>', 'New priority')
93
+ .option('--tags <tags>', 'New tags (comma-separated)')
94
+ .option('--due <date>', 'New due date')
95
+ .action((id, opts) => {
96
+ const updates = {};
97
+ if (opts.title)
98
+ updates.title = opts.title;
99
+ if (opts.description)
100
+ updates.description = opts.description;
101
+ if (opts.status)
102
+ updates.status = opts.status;
103
+ if (opts.priority)
104
+ updates.priority = opts.priority;
105
+ if (opts.tags)
106
+ updates.tags = opts.tags.split(',').map((t) => t.trim());
107
+ if (opts.due)
108
+ updates.dueDate = opts.due;
109
+ const task = updateTask(id, updates);
110
+ if (!task) {
111
+ console.error(`Task not found: ${id}`);
112
+ process.exit(1);
113
+ }
114
+ console.log(`✓ Updated task: ${task.title}`);
115
+ });
116
+ program
117
+ .command('remove <id>')
118
+ .alias('rm')
119
+ .description('Remove a task')
120
+ .action((id) => {
121
+ const removed = removeTask(id);
122
+ if (!removed) {
123
+ console.error(`Task not found: ${id}`);
124
+ process.exit(1);
125
+ }
126
+ console.log(`✓ Removed task`);
127
+ });
128
+ program
129
+ .command('move <id> <status>')
130
+ .description('Move task to a status (todo, in-progress, done, blocked)')
131
+ .action((id, status) => {
132
+ const validStatuses = ['todo', 'in-progress', 'done', 'blocked'];
133
+ if (!validStatuses.includes(status)) {
134
+ console.error(`Invalid status. Use: ${validStatuses.join(', ')}`);
135
+ process.exit(1);
136
+ }
137
+ const task = moveTask(id, status);
138
+ if (!task) {
139
+ console.error(`Task not found: ${id}`);
140
+ process.exit(1);
141
+ }
142
+ console.log(`✓ Moved "${task.title}" to ${status}`);
143
+ });
144
+ program
145
+ .command('done <id>')
146
+ .description('Mark task as done')
147
+ .action((id) => {
148
+ const task = moveTask(id, 'done');
149
+ if (!task) {
150
+ console.error(`Task not found: ${id}`);
151
+ process.exit(1);
152
+ }
153
+ console.log(`✓ Completed: ${task.title}`);
154
+ });
155
+ program
156
+ .command('export')
157
+ .description('Export tasks to various formats')
158
+ .option('-f, --format <format>', 'Export format (csv, json, kanban, markdown, sheets)', 'json')
159
+ .option('-o, --output <file>', 'Output file (prints to stdout if not specified)')
160
+ .action((opts) => {
161
+ let output;
162
+ switch (opts.format) {
163
+ case 'csv':
164
+ output = toCSV();
165
+ break;
166
+ case 'kanban':
167
+ output = JSON.stringify(toKanban(), null, 2);
168
+ break;
169
+ case 'markdown':
170
+ case 'md':
171
+ output = toMarkdown();
172
+ break;
173
+ case 'sheets':
174
+ output = JSON.stringify(toGoogleSheetsFormat(), null, 2);
175
+ break;
176
+ case 'json':
177
+ default:
178
+ output = toJSON();
179
+ }
180
+ if (opts.output) {
181
+ writeFileSync(opts.output, output);
182
+ console.log(`✓ Exported to ${opts.output}`);
183
+ }
184
+ else {
185
+ console.log(output);
186
+ }
187
+ });
188
+ program.parse();
@@ -0,0 +1,20 @@
1
+ import type { ShipSheet, Task, TaskStatus, TaskPriority } from './types.js';
2
+ export declare function loadSheet(): ShipSheet;
3
+ export declare function saveSheet(sheet: ShipSheet): void;
4
+ export declare function generateId(): string;
5
+ export declare function addTask(title: string, options?: {
6
+ description?: string;
7
+ status?: TaskStatus;
8
+ priority?: TaskPriority;
9
+ tags?: string[];
10
+ dueDate?: string;
11
+ }): Task;
12
+ export declare function listTasks(filter?: {
13
+ status?: TaskStatus;
14
+ priority?: TaskPriority;
15
+ tag?: string;
16
+ }): Task[];
17
+ export declare function getTask(id: string): Task | undefined;
18
+ export declare function updateTask(id: string, updates: Partial<Omit<Task, 'id' | 'createdAt'>>): Task | null;
19
+ export declare function removeTask(id: string): boolean;
20
+ export declare function moveTask(id: string, status: TaskStatus): Task | null;
package/dist/store.js ADDED
@@ -0,0 +1,93 @@
1
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const TASKS_FILE = 'tasks.json';
4
+ function getTasksPath() {
5
+ return join(process.cwd(), TASKS_FILE);
6
+ }
7
+ function createDefaultSheet() {
8
+ return {
9
+ name: 'Ship Sheet',
10
+ version: '1.0.0',
11
+ tasks: [],
12
+ createdAt: new Date().toISOString(),
13
+ updatedAt: new Date().toISOString(),
14
+ };
15
+ }
16
+ export function loadSheet() {
17
+ const path = getTasksPath();
18
+ if (!existsSync(path)) {
19
+ const sheet = createDefaultSheet();
20
+ saveSheet(sheet);
21
+ return sheet;
22
+ }
23
+ const data = readFileSync(path, 'utf-8');
24
+ return JSON.parse(data);
25
+ }
26
+ export function saveSheet(sheet) {
27
+ sheet.updatedAt = new Date().toISOString();
28
+ writeFileSync(getTasksPath(), JSON.stringify(sheet, null, 2));
29
+ }
30
+ export function generateId() {
31
+ return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
32
+ }
33
+ export function addTask(title, options = {}) {
34
+ const sheet = loadSheet();
35
+ const now = new Date().toISOString();
36
+ const task = {
37
+ id: generateId(),
38
+ title,
39
+ description: options.description,
40
+ status: options.status || 'todo',
41
+ priority: options.priority || 'medium',
42
+ tags: options.tags,
43
+ createdAt: now,
44
+ updatedAt: now,
45
+ dueDate: options.dueDate,
46
+ };
47
+ sheet.tasks.push(task);
48
+ saveSheet(sheet);
49
+ return task;
50
+ }
51
+ export function listTasks(filter) {
52
+ const sheet = loadSheet();
53
+ let tasks = sheet.tasks;
54
+ if (filter?.status) {
55
+ tasks = tasks.filter((t) => t.status === filter.status);
56
+ }
57
+ if (filter?.priority) {
58
+ tasks = tasks.filter((t) => t.priority === filter.priority);
59
+ }
60
+ if (filter?.tag) {
61
+ tasks = tasks.filter((t) => t.tags?.includes(filter.tag));
62
+ }
63
+ return tasks;
64
+ }
65
+ export function getTask(id) {
66
+ const sheet = loadSheet();
67
+ return sheet.tasks.find((t) => t.id === id || t.id.startsWith(id));
68
+ }
69
+ export function updateTask(id, updates) {
70
+ const sheet = loadSheet();
71
+ const index = sheet.tasks.findIndex((t) => t.id === id || t.id.startsWith(id));
72
+ if (index === -1)
73
+ return null;
74
+ sheet.tasks[index] = {
75
+ ...sheet.tasks[index],
76
+ ...updates,
77
+ updatedAt: new Date().toISOString(),
78
+ };
79
+ saveSheet(sheet);
80
+ return sheet.tasks[index];
81
+ }
82
+ export function removeTask(id) {
83
+ const sheet = loadSheet();
84
+ const index = sheet.tasks.findIndex((t) => t.id === id || t.id.startsWith(id));
85
+ if (index === -1)
86
+ return false;
87
+ sheet.tasks.splice(index, 1);
88
+ saveSheet(sheet);
89
+ return true;
90
+ }
91
+ export function moveTask(id, status) {
92
+ return updateTask(id, { status });
93
+ }
@@ -0,0 +1,20 @@
1
+ export type TaskStatus = 'todo' | 'in-progress' | 'done' | 'blocked';
2
+ export type TaskPriority = 'low' | 'medium' | 'high' | 'critical';
3
+ export interface Task {
4
+ id: string;
5
+ title: string;
6
+ description?: string;
7
+ status: TaskStatus;
8
+ priority: TaskPriority;
9
+ tags?: string[];
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ dueDate?: string;
13
+ }
14
+ export interface ShipSheet {
15
+ name: string;
16
+ version: string;
17
+ tasks: Task[];
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipsheet",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "CLI for managing a local tasks.json ship sheet - exportable to Kanban or Google Sheets",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,19 +8,40 @@
8
8
  "shipsheet": "dist/index.js",
9
9
  "ss": "dist/index.js"
10
10
  },
11
- "scripts": {
12
- "build": "tsc",
13
- "dev": "tsc --watch",
14
- "start": "node dist/index.js",
15
- "typecheck": "tsc --noEmit"
16
- },
17
- "keywords": ["cli", "tasks", "todo", "kanban", "shipsheet"],
11
+ "keywords": [
12
+ "cli",
13
+ "tasks",
14
+ "todo",
15
+ "kanban",
16
+ "shipsheet",
17
+ "skills"
18
+ ],
18
19
  "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/ahmadawais/shipsheet.git"
23
+ },
24
+ "author": "Ahmad Awais",
25
+ "files": [
26
+ "dist",
27
+ "skill"
28
+ ],
19
29
  "devDependencies": {
30
+ "@changesets/changelog-github": "^0.5.2",
31
+ "@changesets/cli": "^2.29.8",
20
32
  "@types/node": "^20.10.0",
21
33
  "typescript": "^5.3.0"
22
34
  },
23
35
  "dependencies": {
24
36
  "commander": "^12.0.0"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc",
40
+ "dev": "tsc --watch",
41
+ "start": "node dist/index.js",
42
+ "typecheck": "tsc --noEmit",
43
+ "changeset": "changeset",
44
+ "version": "changeset version",
45
+ "release": "pnpm build && changeset publish && git push --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes"
25
46
  }
26
- }
47
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,74 @@
1
+ # ShipSheet Skill
2
+
3
+ Manage local task lists with shipsheet CLI. Use when asked to track tasks, create todo lists, or manage a ship sheet.
4
+
5
+ ## When to Use
6
+
7
+ - User wants to track tasks or todos locally
8
+ - User needs a ship sheet for project management
9
+ - User wants to export tasks to Kanban or Google Sheets
10
+ - User asks to "add a task", "list tasks", "mark done", etc.
11
+
12
+ ## Commands
13
+
14
+ ### Add Task
15
+ ```bash
16
+ npx shipsheet add "Task title" -p <priority> -t "tag1,tag2" -d "description" --due YYYY-MM-DD
17
+ ```
18
+
19
+ Options:
20
+ - `-p, --priority`: low, medium, high, critical
21
+ - `-t, --tags`: Comma-separated tags
22
+ - `-d, --description`: Task description
23
+ - `--due`: Due date
24
+
25
+ ### List Tasks
26
+ ```bash
27
+ npx shipsheet list
28
+ npx shipsheet ls -s <status> -p <priority> -t <tag>
29
+ ```
30
+
31
+ ### Update Task
32
+ ```bash
33
+ npx shipsheet update <id> -t "New title" -s <status> -p <priority>
34
+ ```
35
+
36
+ ### Move Task Status
37
+ ```bash
38
+ npx shipsheet move <id> <status>
39
+ npx shipsheet done <id>
40
+ ```
41
+
42
+ Statuses: `todo`, `in-progress`, `done`, `blocked`
43
+
44
+ ### Remove Task
45
+ ```bash
46
+ npx shipsheet rm <id>
47
+ ```
48
+
49
+ ### Export Tasks
50
+ ```bash
51
+ npx shipsheet export -f <format> -o <output-file>
52
+ ```
53
+
54
+ Formats: `json`, `csv`, `kanban`, `markdown`, `sheets`
55
+
56
+ ## Examples
57
+
58
+ ```bash
59
+ # Add high priority task with tags
60
+ npx shipsheet add "Fix auth bug" -p critical -t "bug,auth"
61
+
62
+ # List only in-progress tasks
63
+ npx shipsheet ls -s in-progress
64
+
65
+ # Mark task done (use first few chars of ID)
66
+ npx shipsheet done mkwbb
67
+
68
+ # Export to CSV for Google Sheets
69
+ npx shipsheet export -f csv -o tasks.csv
70
+ ```
71
+
72
+ ## File Location
73
+
74
+ Tasks are stored in `tasks.json` in the current directory.
package/skill/spec.md ADDED
@@ -0,0 +1,90 @@
1
+ # ShipSheet Specification
2
+
3
+ ## Overview
4
+
5
+ ShipSheet is a CLI tool for managing local task lists stored in `tasks.json`. It provides a simple interface for task management with export capabilities for Kanban boards and Google Sheets.
6
+
7
+ ## Data Model
8
+
9
+ ### ShipSheet (Root)
10
+ ```typescript
11
+ interface ShipSheet {
12
+ name: string; // Sheet name
13
+ version: string; // Schema version
14
+ tasks: Task[]; // Array of tasks
15
+ createdAt: string; // ISO timestamp
16
+ updatedAt: string; // ISO timestamp
17
+ }
18
+ ```
19
+
20
+ ### Task
21
+ ```typescript
22
+ interface Task {
23
+ id: string; // Unique identifier (base36 timestamp + random)
24
+ title: string; // Task title (required)
25
+ description?: string; // Optional description
26
+ status: TaskStatus; // Current status
27
+ priority: TaskPriority; // Priority level
28
+ tags?: string[]; // Optional tags array
29
+ dueDate?: string; // Optional due date (YYYY-MM-DD)
30
+ createdAt: string; // ISO timestamp
31
+ updatedAt: string; // ISO timestamp
32
+ }
33
+
34
+ type TaskStatus = 'todo' | 'in-progress' | 'done' | 'blocked';
35
+ type TaskPriority = 'low' | 'medium' | 'high' | 'critical';
36
+ ```
37
+
38
+ ## CLI Commands
39
+
40
+ | Command | Alias | Description |
41
+ |---------|-------|-------------|
42
+ | `add <title>` | - | Add new task |
43
+ | `list` | `ls` | List all tasks |
44
+ | `show <id>` | - | Show task details |
45
+ | `update <id>` | - | Update task properties |
46
+ | `move <id> <status>` | - | Change task status |
47
+ | `done <id>` | - | Mark task as done |
48
+ | `remove <id>` | `rm` | Delete task |
49
+ | `export` | - | Export to various formats |
50
+
51
+ ## Export Formats
52
+
53
+ ### JSON
54
+ Full `tasks.json` content with all metadata.
55
+
56
+ ### CSV
57
+ ```
58
+ ID,Title,Description,Status,Priority,Tags,Due Date,Created,Updated
59
+ ```
60
+
61
+ ### Kanban
62
+ ```json
63
+ {
64
+ "todo": [...],
65
+ "in-progress": [...],
66
+ "done": [...],
67
+ "blocked": [...]
68
+ }
69
+ ```
70
+
71
+ ### Google Sheets (2D Array)
72
+ ```json
73
+ [
74
+ ["ID", "Title", "Description", "Status", "Priority", "Tags", "Due Date", "Created", "Updated"],
75
+ ["id1", "Task 1", "", "todo", "high", "tag1, tag2", "", "2026-01-27", "2026-01-27"]
76
+ ]
77
+ ```
78
+
79
+ ### Markdown
80
+ Kanban-style markdown with priority indicators and grouped by status.
81
+
82
+ ## ID Matching
83
+
84
+ Task IDs support partial matching - you can use the first few characters of an ID to reference a task (e.g., `mkwbb` instead of `mkwbbi25gbew2`).
85
+
86
+ ## File Storage
87
+
88
+ - Location: `./tasks.json` in current working directory
89
+ - Format: Pretty-printed JSON (2-space indent)
90
+ - Auto-created on first task add
@@ -1,22 +0,0 @@
1
- # Cli
2
- - Use pnpm as the package manager for CLI projects. Confidence: 1.00
3
- - Use TypeScript for CLI projects. Confidence: 0.95
4
- - Use tsup as the build tool for CLI projects. Confidence: 0.95
5
- - Use vitest for testing CLI projects. Confidence: 0.95
6
- - Use Commander.js for CLI command handling. Confidence: 0.95
7
- - Use clack for interactive user input in CLI projects. Confidence: 0.95
8
- - Check for existing CLI name conflicts before running npm link. Confidence: 0.95
9
- - Organize CLI commands in a dedicated commands folder with each module separated. Confidence: 0.95
10
- - Include a small 150px ASCII art welcome banner displaying the CLI name. Confidence: 0.95
11
- - Use lowercase flags for version and help commands (-v, --version, -h, --help). Confidence: 0.85
12
- - Start projects with version 0.0.1 instead of 1.0.0. Confidence: 0.85
13
- - Version command should output only the version number with no ASCII art, banner, or additional information. Confidence: 0.90
14
- - Read CLI version from package.json instead of hardcoding it in the source code. Confidence: 0.75
15
- - Always use ora for loading spinners in CLI projects. Confidence: 0.95
16
- - Use picocolors for terminal string coloring in CLI projects. Confidence: 0.90
17
- - Use Ink for building interactive CLI UIs in CommandCode projects. Confidence: 0.80
18
- - Use ink-spinner for loading animations in Ink-based CLIs. Confidence: 0.70
19
- - Hide internal flags from help: .addOption(new Option('--local').hideHelp()). Confidence: 0.90
20
- - Use pnpm.onlyBuiltDependencies in package.json to pre-approve native binary builds. Confidence: 0.60
21
- - Use ANSI Shadow font for ASCII art at large terminal widths and ANSI Compact for small widths. Confidence: 0.85
22
- - Use minimal white, gray, and black colors for ASCII art banners. Confidence: 0.85
@@ -1,4 +0,0 @@
1
- # Taste (Continuously Learned by CommandCode.ai)
2
-
3
- # cli
4
- See [cli/taste.md](cli/taste.md)
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "outDir": "dist",
7
- "rootDir": "src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "declaration": true
12
- },
13
- "include": ["src/**/*"],
14
- "exclude": ["node_modules", "dist"]
15
- }