@lumoai/cli 1.3.0 → 1.4.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/assets/skill.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lumo
3
- description: 'Use the Lumo CLI to load task context, manage session bindings, inspect projects and milestones, and create/update/list/show/comment on tasks from the terminal. Activate when: user mentions a Lumo task identifier (LUM-42, LUM-12, etc.), asks to load task background or context, wants to bind, check, or detach a Claude Code session''s task binding, is about to start development work on a specific task, wants to create a new task, list their tasks, view a task, comment on a task, list projects, list milestones, attach a task to a milestone, or update a task''s status/title/description/priority/assignee/milestone. Triggers on: "LUM-", "task context", "load context", "session start", "session attach", "session status", "session detach", "bind session", "unbind session", "which task", "what task am I on", "work on LUM", "create task", "new task", "add task", "file a task", "log a task", "list tasks", "my tasks", "show task", "view task", "comment on task", "leave a comment", "list projects", "what projects", "update task", "change task status", "rename task", "reassign task", "mark task as done", "milestone", "里程碑", "list milestones", "set milestone", "挂到 milestone", "attach milestone", "unbind milestone", "create milestone", "new milestone", "update milestone", "change milestone status", "delete milestone", "show milestone", "view milestone", "tasks in milestone", "milestone tasks", "新建里程碑", "更新里程碑", "删除里程碑", "查看里程碑", "auth login", "log in", "login", "auth logout", "log out", "logout", "sign out", "switch account", "switch identity", "whoami", "who am I", "current identity", "current user", "current workspace", "登录", "登出", "切换账号", "当前身份", "create doc", "new doc", "new document", "write doc", "写文档", "新建文档", "update doc", "edit doc", "修改文档", "更新文档", "list docs", "my docs", "我的文档", "show doc", "view doc", "查看文档", "delete doc", "删除文档", "bind doc", "attach doc to task", "把文档关联到任务", "文档绑定到任务", "unbind doc", "解绑文档", "personal doc", "workspace doc", "个人文档", "workspace 文档", "doc scope", "tag", "add tag", "remove tag", "标签", "添加标签", "移除标签", "doc tag", "task tag", "share doc", "doc share", "share document", "分享文档", "文档分享", "unshare doc", "remove share", "取消分享", "share list", "list doc shares", "who has access", "viewer", "editor", "manager", "shared with", "doc tree", "doc move", "move doc", "reparent doc", "文档树", "移动文档", "sprint", "start sprint", "close sprint", "add to sprint", "active sprints", "冲刺", "迭代", "开始冲刺", "关闭冲刺", "create sprint", "new sprint", "list sprints", "show sprint", "update sprint", "delete sprint", "sprint summary", "sprint retro", "把任务挂到冲刺", "冲刺里有什么", "lumo update", "update cli", "upgrade lumo", "update lumo", "upgrade cli", "升级 lumo", "更新 cli", "new lumo version", "是否有新版本", "lumo setup", "install lumo skill", "install lumo hooks", "wire up lumo", "set up lumo", "onboard lumo", "npx @lumoai/cli", "安装 lumo", "配置 lumo", "lumo 初始化", "task artifact", "artifact add", "artifact list", "artifact show", "artifact rm", "artifact delete", "remove artifact", "delete artifact", "spec artifact", "record spec", "attach spec", "attach plan", "记录 spec", "挂 spec", "查看 artifact", "删除 artifact", figma, attach figma, figma link, 关联 figma, 设计稿, figma design.'
3
+ description: 'Use the Lumo CLI to load task context, manage session bindings, inspect projects and milestones, and create/update/list/show/comment on tasks from the terminal. Activate when: user mentions a Lumo task identifier (LUM-42, LUM-12, etc.), asks to load task background or context, wants to bind, check, or detach a Claude Code session''s task binding, is about to start development work on a specific task, wants to create a new task, list their tasks, view a task, comment on a task, list projects, list milestones, attach a task to a milestone, or update a task''s status/title/description/priority/assignee/milestone. Triggers on: "LUM-", "task context", "load context", "session start", "session attach", "session status", "session detach", "bind session", "unbind session", "which task", "what task am I on", "work on LUM", "create task", "new task", "add task", "file a task", "log a task", "list tasks", "my tasks", "show task", "view task", "comment on task", "leave a comment", "list projects", "what projects", "update task", "change task status", "rename task", "reassign task", "mark task as done", "milestone", "里程碑", "list milestones", "set milestone", "挂到 milestone", "attach milestone", "unbind milestone", "create milestone", "new milestone", "update milestone", "change milestone status", "delete milestone", "show milestone", "view milestone", "tasks in milestone", "milestone tasks", "新建里程碑", "更新里程碑", "删除里程碑", "查看里程碑", "auth login", "log in", "login", "auth logout", "log out", "logout", "sign out", "switch account", "switch identity", "whoami", "who am I", "current identity", "current user", "current workspace", "登录", "登出", "切换账号", "当前身份", "create doc", "new doc", "new document", "write doc", "写文档", "新建文档", "update doc", "edit doc", "修改文档", "更新文档", "list docs", "my docs", "我的文档", "show doc", "view doc", "查看文档", "delete doc", "删除文档", "bind doc", "attach doc to task", "把文档关联到任务", "文档绑定到任务", "unbind doc", "解绑文档", "personal doc", "workspace doc", "个人文档", "workspace 文档", "doc scope", "tag", "add tag", "remove tag", "标签", "添加标签", "移除标签", "doc tag", "task tag", "share doc", "doc share", "share document", "分享文档", "文档分享", "unshare doc", "remove share", "取消分享", "share list", "list doc shares", "who has access", "viewer", "editor", "manager", "shared with", "doc tree", "doc move", "move doc", "reparent doc", "文档树", "移动文档", "sprint", "start sprint", "close sprint", "add to sprint", "active sprints", "冲刺", "迭代", "开始冲刺", "关闭冲刺", "create sprint", "new sprint", "list sprints", "show sprint", "update sprint", "delete sprint", "sprint summary", "sprint retro", "把任务挂到冲刺", "冲刺里有什么", "lumo update", "update cli", "upgrade lumo", "update lumo", "upgrade cli", "升级 lumo", "更新 cli", "new lumo version", "是否有新版本", "lumo setup", "install lumo skill", "install lumo hooks", "wire up lumo", "set up lumo", "onboard lumo", "npx @lumoai/cli", "安装 lumo", "配置 lumo", "lumo 初始化", "task artifact", "artifact add", "artifact list", "artifact show", "artifact rm", "artifact delete", "artifact update", "update artifact", "edit artifact", "change artifact kind", "change artifact source", "remove artifact", "delete artifact", "spec artifact", "record spec", "attach spec", "attach plan", "记录 spec", "挂 spec", "查看 artifact", "编辑 artifact", "修改 artifact", "删除 artifact", figma, attach figma, figma link, 关联 figma, 设计稿, figma design.'
4
4
  ---
5
5
 
6
6
  ## Prerequisites
@@ -299,17 +299,29 @@ The CLI does not support @-mention chip syntax. If the user wants to ping someon
299
299
 
300
300
  Record Claude Code spec-engineering products (spec / plan / design …) on a task. The artifacts show up in the task detail "规格" (definition) layer and are injected into `lumo task context`.
301
301
 
302
- #### `lumo task artifact add <task> --kind <kind> --title <title> --file <path> [--source <source>]`
302
+ #### `lumo task artifact add <task> --kind <kind> --title <title> --file <path> --source <source>`
303
303
 
304
- Attaches an artifact to a task. `--kind`, `--title`, `--source` are stored verbatim — **`kind` is opaque** (no enumeration; `spec` / `plan` / `requirements` / anything is accepted). `--file` supplies the body (file contents). `--source` defaults to `claude-code`. Each call appends to the end of the task's artifact list — call once per artifact (e.g. Superpowers: one `spec`, one `plan`). The `<task>` (e.g. `LUM-42`) is resolved server-side.
304
+ Attaches an artifact to a task. `--kind`, `--title`, `--source` are stored verbatim — **`kind` is opaque** (no enumeration; `spec` / `plan` / `requirements` / anything is accepted). `--source` is **required** and names the spec-generation framework that produced the artifact, written as its **formal name** (`Superpowers` / `Spec Kit` / `BMad` / `OpenSpec` / `GSD` / …) — it is also opaque (no enumeration), but there is **no default**, so you must pass it. Quote names that contain spaces (`--source "Spec Kit"`). `--file` supplies the body (file contents). Each call appends to the end of the task's artifact list — call once per artifact (e.g. Superpowers: one `spec`, one `plan`). The `<task>` (e.g. `LUM-42`) is resolved server-side.
305
305
 
306
306
  ```bash
307
- lumo task artifact add LUM-42 --kind spec --title "Spec" --file docs/spec.md --source superpowers
308
- lumo task artifact add LUM-42 --kind plan --title "Implementation plan" --file docs/plan.md --source superpowers
307
+ lumo task artifact add LUM-42 --kind spec --title "Spec" --file docs/spec.md --source Superpowers
308
+ lumo task artifact add LUM-42 --kind plan --title "Implementation plan" --file docs/plan.md --source "Spec Kit"
309
309
  ```
310
310
 
311
311
  Output: `Added [spec] "Spec" to LUM-42`
312
312
 
313
+ #### `lumo task artifact update <task> <artifact-id> [--kind <kind>] [--title <title>] [--source <source>]`
314
+
315
+ Patches an existing artifact's metadata in place. Editable fields are **`kind`, `title`, and `source`** only — **content is immutable** (to change the body, `rm` the artifact and `add` it again). At least one flag is required; passing none errors before any network call. Empty values (`--kind ""`) are rejected. The `<artifact-id>` is the cuid in column 1 of `artifact list`.
316
+
317
+ ```bash
318
+ lumo task artifact update LUM-42 cma_xxx --kind plan # re-classify spec → plan
319
+ lumo task artifact update LUM-42 cma_xxx --source "Spec Kit" # fix the framework label
320
+ lumo task artifact update LUM-42 cma_xxx --title "Final spec" --source OpenSpec
321
+ ```
322
+
323
+ Output: `Updated [plan] "Final spec" (OpenSpec) on LUM-42`. A 404 (task or artifact missing in this workspace) prints the server message and exits 1.
324
+
313
325
  #### `lumo task artifact list <task>`
314
326
 
315
327
  Lists artifacts on the task in order: `<id> <kind> <source> <title>`. Prints `No artifacts on <task>` when there are none.
@@ -334,7 +346,7 @@ Deletes an artifact from a task. Irreversible — `--yes` is required and there
334
346
  lumo task artifact rm LUM-42 cma_xxx --yes
335
347
  ```
336
348
 
337
- When to suggest: after running a spec/plan workflow in Claude Code, offer to record the product(s) with `task artifact add` (one call per artifact). Use `task artifact list` to see what's already recorded, `task artifact show` to inspect a single artifact's content, and `task artifact rm` to drop one that's wrong or stale.
349
+ When to suggest: after running a spec/plan workflow in Claude Code, offer to record the product(s) with `task artifact add` (one call per artifact) — always pass `--source` with the framework you used. Use `task artifact list` to see what's already recorded, `task artifact show` to inspect a single artifact's content, `task artifact update` to fix a wrong kind/title/source without re-uploading, and `task artifact rm` to drop one that's wrong or stale.
338
350
 
339
351
  ### Task ↔ Figma Designs
340
352
 
@@ -6,11 +6,12 @@ const api_1 = require("../lib/api");
6
6
  const doc_input_1 = require("../lib/doc-input");
7
7
  async function taskArtifactAdd(identifier, options) {
8
8
  if (!identifier) {
9
- console.error('Error: missing <task>. Usage: lumo task artifact add <LUM-42> --kind spec --title "Spec" --file spec.md');
9
+ console.error('Error: missing <task>. Usage: lumo task artifact add <LUM-42> --kind spec --title "Spec" --file spec.md --source Superpowers');
10
10
  return 1;
11
11
  }
12
12
  const kind = options.kind?.trim();
13
13
  const title = options.title?.trim();
14
+ const source = options.source?.trim();
14
15
  if (!kind) {
15
16
  console.error('Error: --kind is required and cannot be empty.');
16
17
  return 1;
@@ -19,6 +20,10 @@ async function taskArtifactAdd(identifier, options) {
19
20
  console.error('Error: --title is required and cannot be empty.');
20
21
  return 1;
21
22
  }
23
+ if (!source) {
24
+ console.error('Error: --source is required (the spec-gen framework, formal name e.g. Superpowers, "Spec Kit", BMad, OpenSpec, GSD).');
25
+ return 1;
26
+ }
22
27
  if (!options.file) {
23
28
  console.error('Error: --file <path> is required.');
24
29
  return 1;
@@ -43,9 +48,7 @@ async function taskArtifactAdd(identifier, options) {
43
48
  const envUrl = process.env.LUMO_API_URL?.trim();
44
49
  const apiUrl = envUrl && envUrl.length > 0 ? envUrl : creds.apiUrl;
45
50
  const base = (0, api_1.trimTrailingSlash)(apiUrl);
46
- const payload = { kind, title, content };
47
- if (options.source?.trim())
48
- payload.source = options.source.trim();
51
+ const payload = { kind, title, content, source };
49
52
  let res;
50
53
  try {
51
54
  res = await fetch(`${base}/api/tasks/${encodeURIComponent(identifier)}/artifacts`, {
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.taskArtifactUpdate = taskArtifactUpdate;
4
+ const config_1 = require("../lib/config");
5
+ const api_1 = require("../lib/api");
6
+ async function taskArtifactUpdate(identifier, artifactId, options) {
7
+ if (!identifier) {
8
+ console.error('Error: missing <task>. Usage: lumo task artifact update <LUM-42> <artifact-id> --kind plan');
9
+ return 1;
10
+ }
11
+ if (!artifactId) {
12
+ console.error('Error: missing <artifact-id>. Usage: lumo task artifact update <LUM-42> <artifact-id> --kind plan');
13
+ return 1;
14
+ }
15
+ const payload = {};
16
+ const kind = options.kind?.trim();
17
+ const title = options.title?.trim();
18
+ const source = options.source?.trim();
19
+ if (options.kind !== undefined) {
20
+ if (!kind) {
21
+ console.error('Error: --kind cannot be empty.');
22
+ return 1;
23
+ }
24
+ payload.kind = kind;
25
+ }
26
+ if (options.title !== undefined) {
27
+ if (!title) {
28
+ console.error('Error: --title cannot be empty.');
29
+ return 1;
30
+ }
31
+ payload.title = title;
32
+ }
33
+ if (options.source !== undefined) {
34
+ if (!source) {
35
+ console.error('Error: --source cannot be empty.');
36
+ return 1;
37
+ }
38
+ payload.source = source;
39
+ }
40
+ if (Object.keys(payload).length === 0) {
41
+ console.error('Error: provide at least one of --kind, --title, or --source to update.');
42
+ return 1;
43
+ }
44
+ const creds = (0, config_1.readCredentials)();
45
+ if (!creds) {
46
+ console.error('Error: not logged in. Run `lumo auth login` first.');
47
+ return 1;
48
+ }
49
+ const envUrl = process.env.LUMO_API_URL?.trim();
50
+ const apiUrl = envUrl && envUrl.length > 0 ? envUrl : creds.apiUrl;
51
+ const base = (0, api_1.trimTrailingSlash)(apiUrl);
52
+ let res;
53
+ try {
54
+ res = await fetch(`${base}/api/tasks/${encodeURIComponent(identifier)}/artifacts/${encodeURIComponent(artifactId)}`, {
55
+ method: 'PATCH',
56
+ headers: {
57
+ Authorization: `Bearer ${creds.token}`,
58
+ 'Content-Type': 'application/json',
59
+ },
60
+ body: JSON.stringify(payload),
61
+ });
62
+ }
63
+ catch (err) {
64
+ const msg = err instanceof Error ? err.message : String(err);
65
+ console.error(`Error: could not reach Lumo API at ${apiUrl} (${msg})`);
66
+ return 1;
67
+ }
68
+ if (res.status === 401) {
69
+ console.error('Error: API key invalid or revoked. Run `lumo auth login`.');
70
+ return 1;
71
+ }
72
+ if (res.status === 404) {
73
+ let serverMsg = `task ${identifier} or artifact ${artifactId} not found in workspace ${creds.workspaceSlug}`;
74
+ try {
75
+ const errBody = (await res.json());
76
+ if (typeof errBody.error === 'string')
77
+ serverMsg = errBody.error;
78
+ }
79
+ catch {
80
+ /* not JSON */
81
+ }
82
+ console.error(`Error: ${serverMsg}`);
83
+ return 1;
84
+ }
85
+ if (res.status !== 200) {
86
+ let serverMsg = null;
87
+ try {
88
+ const errBody = (await res.json());
89
+ if (typeof errBody.error === 'string')
90
+ serverMsg = errBody.error;
91
+ }
92
+ catch {
93
+ /* not JSON */
94
+ }
95
+ console.error(serverMsg
96
+ ? `Error: ${serverMsg}`
97
+ : `Error: artifact update failed (HTTP ${res.status})`);
98
+ return 1;
99
+ }
100
+ const data = (await res.json());
101
+ process.stdout.write(`Updated [${data.artifact.kind}] "${data.artifact.title}" (${data.artifact.source}) on ${identifier}\n`);
102
+ }
@@ -59,6 +59,7 @@ const task_artifact_add_1 = require("./commands/task-artifact-add");
59
59
  const task_artifact_list_1 = require("./commands/task-artifact-list");
60
60
  const task_artifact_show_1 = require("./commands/task-artifact-show");
61
61
  const task_artifact_rm_1 = require("./commands/task-artifact-rm");
62
+ const task_artifact_update_1 = require("./commands/task-artifact-update");
62
63
  const project_list_1 = require("./commands/project-list");
63
64
  const milestone_list_1 = require("./commands/milestone-list");
64
65
  const milestone_create_1 = require("./commands/milestone-create");
@@ -245,8 +246,15 @@ taskArtifact
245
246
  .requiredOption('--kind <kind>', 'Artifact kind, e.g. spec | plan | design (opaque)')
246
247
  .requiredOption('--title <title>', 'Artifact title')
247
248
  .requiredOption('--file <path>', 'File whose contents become the artifact body')
248
- .option('--source <source>', 'Producer label (default: claude-code)')
249
+ .requiredOption('--source <source>', 'Spec-gen framework, formal name e.g. Superpowers | "Spec Kit" | BMad | OpenSpec | GSD (opaque; quote names with spaces)')
249
250
  .action(wrap((taskId, options) => (0, task_artifact_add_1.taskArtifactAdd)(taskId, options)));
251
+ taskArtifact
252
+ .command('update <task> <artifact-id>')
253
+ .description('Update an artifact’s kind / title / source (not content). Provide at least one flag.')
254
+ .option('--kind <kind>', 'New artifact kind (opaque)')
255
+ .option('--title <title>', 'New artifact title')
256
+ .option('--source <source>', 'New spec-gen framework, formal name e.g. Superpowers | "Spec Kit" | BMad | OpenSpec | GSD (quote names with spaces)')
257
+ .action(wrap((taskId, artifactId, options) => (0, task_artifact_update_1.taskArtifactUpdate)(taskId, artifactId, options)));
250
258
  taskArtifact
251
259
  .command('list <task>')
252
260
  .description('List artifacts attached to a task, in order')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumoai/cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Lumo CLI — manage tasks and sessions from the terminal",
5
5
  "license": "MIT",
6
6
  "author": "cli@uselumo.ai",