@nickmeriano/task 0.1.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +68 -0
  3. package/dist/author.d.ts +17 -0
  4. package/dist/author.d.ts.map +1 -0
  5. package/dist/author.js +52 -0
  6. package/dist/author.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +415 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/index.d.ts +5 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +7 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/server.d.ts +14 -0
  16. package/dist/server.d.ts.map +1 -0
  17. package/dist/server.js +292 -0
  18. package/dist/server.js.map +1 -0
  19. package/dist/store.d.ts +63 -0
  20. package/dist/store.d.ts.map +1 -0
  21. package/dist/store.js +346 -0
  22. package/dist/store.js.map +1 -0
  23. package/dist/types.d.ts +61 -0
  24. package/dist/types.d.ts.map +1 -0
  25. package/dist/types.js +13 -0
  26. package/dist/types.js.map +1 -0
  27. package/package.json +81 -0
  28. package/skill/SKILL.md +109 -0
  29. package/src/author.ts +57 -0
  30. package/src/cli.ts +419 -0
  31. package/src/index.ts +6 -0
  32. package/src/server.ts +311 -0
  33. package/src/store.ts +418 -0
  34. package/src/types.ts +75 -0
  35. package/ui/dist/assets/index-BopXdeSy.js +229 -0
  36. package/ui/dist/assets/index-Cl_P2tLU.css +1 -0
  37. package/ui/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  38. package/ui/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  39. package/ui/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  40. package/ui/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  41. package/ui/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  42. package/ui/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  43. package/ui/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  44. package/ui/dist/icon.svg +4 -0
  45. package/ui/dist/index.html +21 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nick Meriano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @nickmeriano/task
2
+
3
+ A task manager that lives in your repo.
4
+
5
+ Tasks and their status are coupled to the code — so keep them next to it.
6
+ State is a SQLite database in `.task/` at your project root: no accounts, no
7
+ connectors, no drift between the board and the branch. Built for the way
8
+ projects work now — you *and* your AI agents share one backlog, and the board
9
+ updates live while agents move tickets from another terminal.
10
+
11
+ ```bash
12
+ npx @nickmeriano/task init
13
+ ```
14
+
15
+ `init` creates `.task/` — commit it, that's the point.
16
+
17
+ ## Teach your agent
18
+
19
+ The package ships an agent skill at `skill/SKILL.md` with the conventions that
20
+ make a shared board work: check it before starting, move tasks as work actually
21
+ progresses, comment at milestones, file what you discover instead of letting it
22
+ evaporate. Install it with whatever manages your agent's skills — e.g.
23
+ [`npx skills add`](https://skills.sh) pointed at that directory.
24
+
25
+ It deliberately isn't installed for you. Where skills live differs by agent and
26
+ by repo layout, and a task manager guessing at that puts a copy somewhere
27
+ nothing reads — which is exactly what happened the first time this tried.
28
+
29
+ ## Use
30
+
31
+ ```bash
32
+ task add "Wire up webhook retries" --tags api --milestone launch
33
+ task list # open tasks, board order
34
+ task list --needs-human # what's blocked on a person
35
+ task start 1 # → in_progress
36
+ task done 1 # → done
37
+ task comment 1 "shipped in #42" --author claude
38
+ task serve # kanban + table UI at localhost:4400, live
39
+ ```
40
+
41
+ - Ids are `PREFIX-12` or just `12`; the prefix comes from `task init --prefix`.
42
+ - Statuses: `backlog` `todo` `in_progress` `done` `canceled`.
43
+ - A task carries tags, at most one milestone, and a `--needs-human` flag for
44
+ work an agent can't finish alone. `--tag a,b` matches either tag.
45
+ - Comments are attributed from `git config user.name` with no setup —
46
+ override with `--author` or `$TASK_AUTHOR`, and check with `task whoami`.
47
+ - Every command takes `--json` — that's the agent interface.
48
+ - Commands work from any subdirectory; the CLI walks up to find `.task/` the
49
+ way git finds `.git`.
50
+ - `task serve` is the one command that also looks *down*: run it at a monorepo
51
+ root and it serves every nested board from one server, with a board switcher
52
+ in the header. Run it inside a package and you get just that board. Every
53
+ other command stays scoped to the nearest `.task/`.
54
+ - The database self-migrates when it's opened, so pulling a colleague's
55
+ `.task/` and running any command brings it up to date in place.
56
+
57
+ ## How it's built
58
+
59
+ - **Zero dependencies.** Storage is Node's built-in `node:sqlite` (Node ≥
60
+ 22.13) — nothing to compile, so `npx` starts in about a second.
61
+ - **Realtime is a file watch.** `task serve` is one `node:http` process: the
62
+ prebuilt UI, a JSON API, and a server-sent-events stream that pings whenever
63
+ anything writes to `.task/` — this UI, another terminal, an agent mid-run.
64
+ - **The UI is deliberately simple.** Five fixed statuses, a kanban board with
65
+ drag and drop, a table, a detail panel. Built on the
66
+ [mojo](https://ui.nickmeriano.com) design system.
67
+
68
+ Docs: [task.nickmeriano.com](https://task.nickmeriano.com)
@@ -0,0 +1,17 @@
1
+ export type AuthorSource = "flag" | "env" | "git" | "fallback";
2
+ export interface Author {
3
+ name: string;
4
+ source: AuthorSource;
5
+ }
6
+ export declare const ANONYMOUS = "anonymous";
7
+ /**
8
+ * Who is writing this comment. No config file: git already knows your name and
9
+ * it's the same one your commits carry, so attribution costs zero setup.
10
+ *
11
+ * --author <who> → $TASK_AUTHOR → git config user.name → "anonymous"
12
+ *
13
+ * Agents keep passing `--author claude` explicitly, which is what the first
14
+ * step is for.
15
+ */
16
+ export declare function resolveAuthor(flag?: string, cwd?: string): Author;
17
+ //# sourceMappingURL=author.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"author.d.ts","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,CAAA;AAE9D,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;CACrB;AAED,eAAO,MAAM,SAAS,cAAc,CAAA;AA6BpC;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAQhF"}
package/dist/author.js ADDED
@@ -0,0 +1,52 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import process from "node:process";
3
+ export const ANONYMOUS = "anonymous";
4
+ /** Resolved at most once per process — git config doesn't change mid-command. */
5
+ const gitNameCache = new Map();
6
+ /**
7
+ * Ask git who you are. Every way this can fail — git not installed, not a
8
+ * repository, `user.name` never set — is the same non-answer, so they all
9
+ * collapse to null rather than being told apart.
10
+ */
11
+ function gitName(cwd) {
12
+ const cached = gitNameCache.get(cwd);
13
+ if (cached !== undefined)
14
+ return cached;
15
+ let name = null;
16
+ try {
17
+ const out = execFileSync("git", ["config", "--get", "user.name"], {
18
+ cwd,
19
+ encoding: "utf8",
20
+ timeout: 1000,
21
+ stdio: ["ignore", "pipe", "ignore"],
22
+ });
23
+ name = out.trim() || null;
24
+ }
25
+ catch {
26
+ name = null;
27
+ }
28
+ gitNameCache.set(cwd, name);
29
+ return name;
30
+ }
31
+ /**
32
+ * Who is writing this comment. No config file: git already knows your name and
33
+ * it's the same one your commits carry, so attribution costs zero setup.
34
+ *
35
+ * --author <who> → $TASK_AUTHOR → git config user.name → "anonymous"
36
+ *
37
+ * Agents keep passing `--author claude` explicitly, which is what the first
38
+ * step is for.
39
+ */
40
+ export function resolveAuthor(flag, cwd = process.cwd()) {
41
+ const flagged = flag?.trim();
42
+ if (flagged)
43
+ return { name: flagged, source: "flag" };
44
+ const env = process.env.TASK_AUTHOR?.trim();
45
+ if (env)
46
+ return { name: env, source: "env" };
47
+ const git = gitName(cwd);
48
+ if (git)
49
+ return { name: git, source: "git" };
50
+ return { name: ANONYMOUS, source: "fallback" };
51
+ }
52
+ //# sourceMappingURL=author.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"author.js","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,OAAO,MAAM,cAAc,CAAA;AASlC,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAA;AAEpC,iFAAiF;AACjF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAA;AAErD;;;;GAIG;AACH,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACvC,IAAI,IAAI,GAAkB,IAAI,CAAA;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE;YAChE,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAA;QACF,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,IAAI,CAAA;IACb,CAAC;IACD,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC3B,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACtE,MAAM,OAAO,GAAG,IAAI,EAAE,IAAI,EAAE,CAAA;IAC5B,IAAI,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IACrD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,CAAA;IAC3C,IAAI,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACxB,IAAI,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAC5C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;AAChD,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,415 @@
1
+ #!/usr/bin/env node
2
+ // The `task` CLI — tasks that live in your repo. Zero dependencies: hand-rolled
3
+ // flag parsing, node:sqlite for storage, plain text out (--json for agents).
4
+ //
5
+ // task init
6
+ // task add "Wire up webhooks" --tags api,infra --milestone launch
7
+ // task list --status todo,in_progress
8
+ // task start TASK-3 && task done TASK-3
9
+ // task serve
10
+ import { readFileSync } from "node:fs";
11
+ import { basename, join } from "node:path";
12
+ import process from "node:process";
13
+ import { resolveAuthor } from "./author.js";
14
+ import { createTaskServer } from "./server.js";
15
+ import { CONFIG_FILE, TASK_DIR, TaskStore, findBoards, findRoot, initProject } from "./store.js";
16
+ import { STATUSES, isStatus } from "./types.js";
17
+ // node:sqlite still emits an ExperimentalWarning on Node 22 — noise in a CLI
18
+ // that runs it on every invocation. Filter that one warning, keep the rest.
19
+ process.removeAllListeners("warning");
20
+ process.on("warning", (warning) => {
21
+ if (warning.name !== "ExperimentalWarning")
22
+ console.error(warning);
23
+ });
24
+ const VERSION = "0.1.0";
25
+ const DEFAULT_PORT = 4400;
26
+ // Every valueless flag has to be listed here: an unregistered one swallows the
27
+ // next argv token, so `task list --needs-human todo` would silently eat `todo`.
28
+ const BOOLEAN_FLAGS = new Set([
29
+ "json",
30
+ "all",
31
+ "help",
32
+ "version",
33
+ "yes",
34
+ "needs-human",
35
+ "no-needs-human",
36
+ ]);
37
+ function parseArgs(argv) {
38
+ const positional = [];
39
+ const flags = {};
40
+ for (let i = 0; i < argv.length; i++) {
41
+ const arg = argv[i];
42
+ if (arg.startsWith("--")) {
43
+ const name = arg.slice(2);
44
+ const eq = name.indexOf("=");
45
+ if (eq >= 0) {
46
+ flags[name.slice(0, eq)] = name.slice(eq + 1);
47
+ }
48
+ else if (BOOLEAN_FLAGS.has(name) || i + 1 >= argv.length || argv[i + 1].startsWith("--")) {
49
+ flags[name] = true;
50
+ }
51
+ else {
52
+ flags[name] = argv[++i];
53
+ }
54
+ }
55
+ else {
56
+ positional.push(arg);
57
+ }
58
+ }
59
+ return { positional, flags };
60
+ }
61
+ function str(flags, name) {
62
+ const v = flags[name];
63
+ return typeof v === "string" ? v : undefined;
64
+ }
65
+ function fail(message) {
66
+ console.error(`error: ${message}`);
67
+ process.exit(1);
68
+ }
69
+ function openStore() {
70
+ const root = findRoot(process.cwd());
71
+ if (!root)
72
+ fail("no .task directory found in this directory or any parent — run `task init` first");
73
+ return new TaskStore(root);
74
+ }
75
+ // ── Input normalization ──────────────────────────────────────────────────────
76
+ function parseStatus(value) {
77
+ const normalized = value.toLowerCase().replace(/-/g, "_");
78
+ if (!isStatus(normalized))
79
+ fail(`invalid status "${value}" — one of: ${STATUSES.join(", ")}`);
80
+ return normalized;
81
+ }
82
+ function parseTags(value) {
83
+ return value.split(",").map((t) => t.trim()).filter(Boolean);
84
+ }
85
+ function patchFromFlags(flags) {
86
+ const patch = {};
87
+ const title = str(flags, "title");
88
+ if (title !== undefined)
89
+ patch.title = title;
90
+ const description = str(flags, "description") ?? str(flags, "desc");
91
+ if (description !== undefined)
92
+ patch.description = description;
93
+ const status = str(flags, "status");
94
+ if (status !== undefined)
95
+ patch.status = parseStatus(status);
96
+ const tags = str(flags, "tags") ?? str(flags, "tag");
97
+ if (tags !== undefined)
98
+ patch.tags = parseTags(tags);
99
+ const milestone = str(flags, "milestone");
100
+ if (milestone !== undefined)
101
+ patch.milestone = milestone.trim() || null;
102
+ if (flags["needs-human"])
103
+ patch.needsHuman = true;
104
+ if (flags["no-needs-human"])
105
+ patch.needsHuman = false;
106
+ return patch;
107
+ }
108
+ // ── Output helpers ───────────────────────────────────────────────────────────
109
+ const STATUS_GLYPH = {
110
+ backlog: "◌",
111
+ todo: "○",
112
+ in_progress: "◐",
113
+ done: "●",
114
+ canceled: "⊘",
115
+ };
116
+ function table(rows) {
117
+ if (rows.length === 0)
118
+ return;
119
+ const widths = rows[0].map((_, col) => Math.max(...rows.map((r) => (r[col] ?? "").length)));
120
+ for (const row of rows) {
121
+ console.log(row.map((cell, col) => (cell ?? "").padEnd(widths[col])).join(" ").trimEnd());
122
+ }
123
+ }
124
+ function taskRow(t) {
125
+ // Exactly six cells, always — table() lines columns up by index.
126
+ return [
127
+ t.id,
128
+ `${STATUS_GLYPH[t.status]} ${t.status}`,
129
+ t.needsHuman ? "⚑" : "",
130
+ t.title,
131
+ t.tags.join(","),
132
+ t.milestone ?? "",
133
+ ];
134
+ }
135
+ function printTask(t) {
136
+ console.log(`${t.id} ${STATUS_GLYPH[t.status]} ${t.status} ${t.title}`);
137
+ }
138
+ // ── Commands ─────────────────────────────────────────────────────────────────
139
+ function cmdInit(args) {
140
+ const cwd = process.cwd();
141
+ if (findRoot(cwd) === cwd)
142
+ fail("already initialized — .task/ exists here");
143
+ const name = str(args.flags, "name") ?? basename(cwd);
144
+ const store = initProject(cwd, { name, prefix: str(args.flags, "prefix")?.toUpperCase() });
145
+ console.log(`Initialized ${store.config.name} (${store.config.prefix}-…) in .task/`);
146
+ console.log(`\nNext:`);
147
+ console.log(` task add "My first task" create a task`);
148
+ console.log(` task list see what's open`);
149
+ console.log(` task serve open the board UI`);
150
+ console.log(`\nCommit .task/ — tasks belong in the repo, next to the code they describe.`);
151
+ // Deliberately not installed for you: where an agent's skills live differs
152
+ // per agent and per repo layout, and a task manager guessing at that is how
153
+ // you end up with a copy somewhere nothing reads. `skill/` ships in this
154
+ // package — point your agent's skill installer at it.
155
+ console.log(`Teach your agent the conventions: skill/SKILL.md in this package.`);
156
+ }
157
+ function cmdAdd(args) {
158
+ const title = args.positional.join(" ").trim();
159
+ if (!title)
160
+ fail(`usage: task add <title> [--description …] [--status …] [--tags a,b] [--milestone …] [--needs-human]`);
161
+ const store = openStore();
162
+ const task = store.create({ title, ...patchFromFlags(args.flags) });
163
+ if (args.flags.json) {
164
+ console.log(JSON.stringify({ task }, null, 2));
165
+ }
166
+ else {
167
+ printTask(task);
168
+ }
169
+ }
170
+ function cmdList(args) {
171
+ const store = openStore();
172
+ const statusFlag = str(args.flags, "status");
173
+ const statuses = statusFlag
174
+ ? statusFlag.split(",").map(parseStatus)
175
+ : args.flags.all
176
+ ? undefined
177
+ : ["backlog", "todo", "in_progress"];
178
+ const tagFlag = str(args.flags, "tags") ?? str(args.flags, "tag");
179
+ const tasks = store.list({
180
+ statuses,
181
+ tags: tagFlag ? parseTags(tagFlag) : undefined,
182
+ milestone: str(args.flags, "milestone"),
183
+ needsHuman: args.flags["needs-human"] ? true : undefined,
184
+ });
185
+ // Present in board order: grouped by status column, then position.
186
+ const order = new Map(STATUSES.map((s, i) => [s, i]));
187
+ tasks.sort((a, b) => order.get(a.status) - order.get(b.status) || a.position - b.position);
188
+ if (args.flags.json) {
189
+ console.log(JSON.stringify({ tasks }, null, 2));
190
+ }
191
+ else if (tasks.length === 0) {
192
+ console.log(args.flags.all ? "no tasks" : "no open tasks (--all includes done/canceled)");
193
+ }
194
+ else {
195
+ table(tasks.map(taskRow));
196
+ }
197
+ }
198
+ function cmdShow(args) {
199
+ const ref = args.positional[0];
200
+ if (!ref)
201
+ fail("usage: task show <id>");
202
+ const store = openStore();
203
+ const number = store.parseId(ref);
204
+ const task = store.get(number);
205
+ if (!task)
206
+ fail(`no such task: ${store.displayId(number)}`);
207
+ const comments = store.comments(number);
208
+ if (args.flags.json) {
209
+ console.log(JSON.stringify({ task, comments }, null, 2));
210
+ return;
211
+ }
212
+ console.log(`${task.id} ${task.title}`);
213
+ console.log(`status ${task.status}`);
214
+ if (task.needsHuman)
215
+ console.log(`needs a human`);
216
+ if (task.tags.length)
217
+ console.log(`tags ${task.tags.join(", ")}`);
218
+ if (task.milestone)
219
+ console.log(`milestone ${task.milestone}`);
220
+ console.log(`created ${task.createdAt}`);
221
+ console.log(`updated ${task.updatedAt}`);
222
+ if (task.description)
223
+ console.log(`\n${task.description}`);
224
+ if (comments.length) {
225
+ console.log(``);
226
+ for (const c of comments) {
227
+ console.log(`— ${c.author || "anonymous"} · ${c.createdAt}`);
228
+ console.log(` ${c.body.split("\n").join("\n ")}`);
229
+ }
230
+ }
231
+ }
232
+ function cmdUpdate(args, forcedStatus) {
233
+ const ref = args.positional[0];
234
+ if (!ref)
235
+ fail("usage: task update <id> [--status …] [--title …] …");
236
+ const store = openStore();
237
+ const patch = patchFromFlags(args.flags);
238
+ if (forcedStatus)
239
+ patch.status = forcedStatus;
240
+ if (Object.keys(patch).length === 0)
241
+ fail("nothing to update — pass at least one flag");
242
+ const task = store.update(store.parseId(ref), patch);
243
+ if (args.flags.json) {
244
+ console.log(JSON.stringify({ task }, null, 2));
245
+ }
246
+ else {
247
+ printTask(task);
248
+ }
249
+ }
250
+ function cmdMove(args) {
251
+ const [ref, status] = args.positional;
252
+ if (!ref || !status)
253
+ fail("usage: task move <id> <status>");
254
+ cmdUpdate({ positional: [ref], flags: { ...args.flags, status } });
255
+ }
256
+ function cmdComment(args) {
257
+ const [ref, ...rest] = args.positional;
258
+ const body = rest.join(" ").trim();
259
+ if (!ref || !body)
260
+ fail(`usage: task comment <id> <text> [--author <who>]`);
261
+ const store = openStore();
262
+ const author = resolveAuthor(str(args.flags, "author")).name;
263
+ const comment = store.addComment(store.parseId(ref), body, author);
264
+ if (args.flags.json) {
265
+ console.log(JSON.stringify({ comment }, null, 2));
266
+ }
267
+ else {
268
+ console.log(`commented on ${comment.taskId}`);
269
+ }
270
+ }
271
+ const AUTHOR_SOURCE = {
272
+ flag: "--author",
273
+ env: "$TASK_AUTHOR",
274
+ git: "git config user.name",
275
+ fallback: "no name found — set git config user.name or $TASK_AUTHOR",
276
+ };
277
+ /** Deliberately never opens the store, so it answers outside a .task/ repo. */
278
+ function cmdWhoami(args) {
279
+ const author = resolveAuthor(str(args.flags, "author"));
280
+ if (args.flags.json) {
281
+ console.log(JSON.stringify(author, null, 2));
282
+ }
283
+ else {
284
+ console.log(`${author.name} (${AUTHOR_SOURCE[author.source]})`);
285
+ }
286
+ }
287
+ function cmdDelete(args) {
288
+ const ref = args.positional[0];
289
+ if (!ref)
290
+ fail("usage: task delete <id>");
291
+ const store = openStore();
292
+ const number = store.parseId(ref);
293
+ store.delete(number);
294
+ console.log(`deleted ${store.displayId(number)}`);
295
+ }
296
+ function cmdServe(args) {
297
+ // Serve is the one command that's monorepo-aware: anchor at the nearest
298
+ // board like every other command, but if there is none, serve whatever
299
+ // boards live *below* here instead of failing.
300
+ const serveRoot = findRoot(process.cwd()) ?? process.cwd();
301
+ const boards = findBoards(serveRoot);
302
+ if (boards.length === 0) {
303
+ fail("no .task directory found in this directory, any parent, or below — run `task init` first");
304
+ }
305
+ const port = Number(str(args.flags, "port") ?? DEFAULT_PORT);
306
+ if (!Number.isInteger(port) || port <= 0)
307
+ fail(`invalid port: ${str(args.flags, "port")}`);
308
+ const server = createTaskServer(serveRoot);
309
+ server.on("error", (error) => {
310
+ if (error.code === "EADDRINUSE")
311
+ fail(`port ${port} is in use — try --port <n>`);
312
+ fail(error.message);
313
+ });
314
+ server.listen(port, () => {
315
+ const boardName = (root) => JSON.parse(readFileSync(join(root, TASK_DIR, CONFIG_FILE), "utf8"))
316
+ .name;
317
+ if (boards.length === 1) {
318
+ console.log(`${boardName(boards[0].root)} · task board`);
319
+ }
320
+ else {
321
+ console.log(`${boards.length} boards · task board`);
322
+ for (const board of boards)
323
+ console.log(` ${board.id} ${boardName(board.root)}`);
324
+ }
325
+ console.log(` http://localhost:${port}`);
326
+ console.log(`Live: edits from any terminal or agent show up as they happen. Ctrl-C to stop.`);
327
+ });
328
+ }
329
+ // ── Help + dispatch ──────────────────────────────────────────────────────────
330
+ const HELP = `task — a task manager that lives in your repo
331
+
332
+ State is a SQLite database in .task/ at the project root. Commit it: tasks and
333
+ their status travel with the code they describe. Any command works from any
334
+ subdirectory (it walks up to find .task/, like git).
335
+
336
+ Usage
337
+ task init [--name <name>] [--prefix <PREFIX>]
338
+ task add <title> [--description <text>] [--status <s>] [--tags <a,b>]
339
+ [--milestone <m>] [--needs-human]
340
+ task list [--status <s1,s2>] [--tag <a,b>] [--milestone <m>]
341
+ [--needs-human] [--all]
342
+ task show <id>
343
+ task update <id> [--title <t>] [--description <text>] [--status <s>]
344
+ [--tags <a,b>] [--milestone <m>]
345
+ [--needs-human | --no-needs-human]
346
+ task move <id> <status> shorthand for update --status
347
+ task start <id> → in_progress
348
+ task done <id> → done
349
+ task comment <id> <text> [--author <who>]
350
+ task delete <id>
351
+ task whoami who your comments are attributed to
352
+ task serve [--port <n>] board + table UI with live updates (default port ${DEFAULT_PORT});
353
+ serves every board at or below here — in a
354
+ monorepo the header becomes a board switcher
355
+
356
+ Values
357
+ <id> TASK-12, or just 12
358
+ status ${STATUSES.join(" ")}
359
+ --tag a,b matches a task carrying *either* tag
360
+ --needs-human this can't be finished by an agent alone
361
+ clearing --tags "" drops all tags, --milestone "" clears it
362
+
363
+ Comment authors resolve --author → $TASK_AUTHOR → git config user.name →
364
+ anonymous, so there is nothing to set up. \`task whoami\` shows which one won.
365
+
366
+ Every read/write command accepts --json for machine-readable output — that's
367
+ the interface AI agents should use.
368
+ `;
369
+ function main() {
370
+ const [command, ...rest] = process.argv.slice(2);
371
+ const args = parseArgs(rest);
372
+ if (!command || command === "help" || args.flags.help) {
373
+ console.log(HELP);
374
+ return;
375
+ }
376
+ if (command === "--version" || args.flags.version) {
377
+ console.log(VERSION);
378
+ return;
379
+ }
380
+ switch (command) {
381
+ case "init":
382
+ return cmdInit(args);
383
+ case "add":
384
+ return cmdAdd(args);
385
+ case "list":
386
+ return cmdList(args);
387
+ case "show":
388
+ return cmdShow(args);
389
+ case "update":
390
+ return cmdUpdate(args);
391
+ case "move":
392
+ return cmdMove(args);
393
+ case "start":
394
+ return cmdUpdate(args, "in_progress");
395
+ case "done":
396
+ return cmdUpdate(args, "done");
397
+ case "comment":
398
+ return cmdComment(args);
399
+ case "whoami":
400
+ return cmdWhoami(args);
401
+ case "delete":
402
+ return cmdDelete(args);
403
+ case "serve":
404
+ return cmdServe(args);
405
+ default:
406
+ fail(`unknown command "${command}" — run \`task help\``);
407
+ }
408
+ }
409
+ try {
410
+ main();
411
+ }
412
+ catch (error) {
413
+ fail(error instanceof Error ? error.message : String(error));
414
+ }
415
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { TaskStore, findRoot, findBoards, initProject, derivePrefix, type BoardRef } from "./store.js";
2
+ export { createTaskServer } from "./server.js";
3
+ export { resolveAuthor, ANONYMOUS, type Author, type AuthorSource } from "./author.js";
4
+ export * from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AACtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AACtF,cAAc,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // Programmatic access to the same store the CLI and `task serve` use — for
2
+ // scripts that want to read or write .task/ without shelling out.
3
+ export { TaskStore, findRoot, findBoards, initProject, derivePrefix } from "./store.js";
4
+ export { createTaskServer } from "./server.js";
5
+ export { resolveAuthor, ANONYMOUS } from "./author.js";
6
+ export * from "./types.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,kEAAkE;AAClE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAiB,MAAM,YAAY,CAAA;AACtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAkC,MAAM,aAAa,CAAA;AACtF,cAAc,YAAY,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { type Server } from "node:http";
2
+ /**
3
+ * `task serve` — one plain node:http server for the static UI, the JSON API,
4
+ * and an SSE stream that pings whenever anything writes to a `.task/` (the UI
5
+ * itself, another terminal, or an agent running the CLI). The UI refetches on
6
+ * every ping, so "realtime" is just fs.watch + a debounce — no sockets, no
7
+ * state to reconcile.
8
+ *
9
+ * Serves every board found at or below `serveRoot` (see `findBoards`): API
10
+ * requests pick one with `?board=<id>`, defaulting to the first. One board is
11
+ * the common case and behaves exactly as before.
12
+ */
13
+ export declare function createTaskServer(serveRoot: string): Server;
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAA;AAsDhG;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAqP1D"}