smashspace 0.1.6 → 0.1.7
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/smash.mjs +58 -23
- package/package.json +1 -1
package/dist/smash.mjs
CHANGED
|
@@ -3599,7 +3599,11 @@ the target board for you.
|
|
|
3599
3599
|
shim that fails with "Volta error: Could not execute command".
|
|
3600
3600
|
- MCP server: \`smashspace-mcp\` (exposes \`smash_*\` tools, same token as the CLI)
|
|
3601
3601
|
- Sign in once per machine: \`smash login\` (browser approval; token saved to
|
|
3602
|
-
\`~/.config/smash/credentials.json\` and reused by MCP)
|
|
3602
|
+
\`~/.config/smash/credentials.json\` and reused by MCP). It is idempotent \u2014 if a
|
|
3603
|
+
valid token is already saved it does nothing, so don't re-run it in a loop.
|
|
3604
|
+
- If \`smash\` is on PATH, **call it directly** \u2014 do not prefix
|
|
3605
|
+
\`PATH=\u2026/node/\u2026/bin\`. A "Volta error: Could not execute command" means a stale
|
|
3606
|
+
install; fix it with \`volta install smashspace\` rather than PATH-hacking.
|
|
3603
3607
|
|
|
3604
3608
|
### Which board am I on?
|
|
3605
3609
|
|
|
@@ -3671,7 +3675,20 @@ Keep the card's agent state current while you work:
|
|
|
3671
3675
|
}
|
|
3672
3676
|
\`\`\`
|
|
3673
3677
|
|
|
3674
|
-
Set \`status: "done"\` only after verification passes.
|
|
3678
|
+
Set \`status: "done"\` only after verification passes. Keep it current on
|
|
3679
|
+
meaningful moves/edits too (not just during todo-dev) so a human can see whose
|
|
3680
|
+
turn it is at a glance.
|
|
3681
|
+
|
|
3682
|
+
## Batching (stay inside the CLI)
|
|
3683
|
+
|
|
3684
|
+
Prefer the CLI's own batch flags over dropping to a shell/node loop:
|
|
3685
|
+
|
|
3686
|
+
\`\`\`bash
|
|
3687
|
+
smash create "Title" --desc-file spec.md # multi-line description, no quoting pain
|
|
3688
|
+
smash card update <cardId> --desc-file - # description from stdin
|
|
3689
|
+
smash checklist add <cardId> --file steps.txt # one item per line (or many args)
|
|
3690
|
+
smash checklist add <cardId> "Step 1" "Step 2" "Step 3"
|
|
3691
|
+
\`\`\`
|
|
3675
3692
|
|
|
3676
3693
|
## Command: /smash list
|
|
3677
3694
|
|
|
@@ -3829,6 +3846,15 @@ function show(data, headerLines = []) {
|
|
|
3829
3846
|
if (data !== void 0)
|
|
3830
3847
|
console.log(JSON.stringify(data, null, 2));
|
|
3831
3848
|
}
|
|
3849
|
+
async function readTextArg(pathOrDash) {
|
|
3850
|
+
if (pathOrDash === "-") {
|
|
3851
|
+
const chunks = [];
|
|
3852
|
+
for await (const chunk of stdin)
|
|
3853
|
+
chunks.push(chunk);
|
|
3854
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
3855
|
+
}
|
|
3856
|
+
return readFile2(pathOrDash, "utf8");
|
|
3857
|
+
}
|
|
3832
3858
|
function resolveBaseUrl(loaded = loadProjectConfig()) {
|
|
3833
3859
|
if (program2.getOptionValueSource("baseUrl") === "cli")
|
|
3834
3860
|
return getOpts().baseUrl;
|
|
@@ -4058,12 +4084,14 @@ ${detail.card.description}`);
|
|
|
4058
4084
|
}
|
|
4059
4085
|
}
|
|
4060
4086
|
});
|
|
4061
|
-
cardCmd.command("update <cardId>").description("Update card fields (title, description, due date, cover, checklist title)").option("--title <title>", "New title").option("--description <description>", "New description (markdown)").option("--due <iso>", "Due date as ISO string, or empty string to clear").option("--cover <attachmentId>", "Cover attachment ID, or empty string to clear").option("--checklist-title <title>", "Custom checklist section title, or empty string to clear").action(
|
|
4087
|
+
cardCmd.command("update <cardId>").description("Update card fields (title, description, due date, cover, checklist title)").option("--title <title>", "New title").option("--description <description>", "New description (markdown)").option("--desc-file <path>", "read description from a file (or - for stdin)").option("--due <iso>", "Due date as ISO string, or empty string to clear").option("--cover <attachmentId>", "Cover attachment ID, or empty string to clear").option("--checklist-title <title>", "Custom checklist section title, or empty string to clear").action(
|
|
4062
4088
|
async (cardId, opts) => {
|
|
4063
4089
|
const patch = {};
|
|
4064
4090
|
if (opts.title !== void 0)
|
|
4065
4091
|
patch.title = opts.title;
|
|
4066
|
-
if (opts.
|
|
4092
|
+
if (opts.descFile !== void 0)
|
|
4093
|
+
patch.description = await readTextArg(opts.descFile);
|
|
4094
|
+
else if (opts.description !== void 0)
|
|
4067
4095
|
patch.description = opts.description;
|
|
4068
4096
|
if (opts.due !== void 0)
|
|
4069
4097
|
patch.dueAt = opts.due === "" ? null : opts.due;
|
|
@@ -4072,7 +4100,7 @@ cardCmd.command("update <cardId>").description("Update card fields (title, descr
|
|
|
4072
4100
|
if (opts.checklistTitle !== void 0)
|
|
4073
4101
|
patch.checklistTitle = opts.checklistTitle === "" ? null : opts.checklistTitle;
|
|
4074
4102
|
if (Object.keys(patch).length === 0) {
|
|
4075
|
-
console.error("Provide at least one of: --title, --description, --due, --cover, --checklist-title");
|
|
4103
|
+
console.error("Provide at least one of: --title, --description, --desc-file, --due, --cover, --checklist-title");
|
|
4076
4104
|
process.exit(1);
|
|
4077
4105
|
}
|
|
4078
4106
|
const card = await api(`/api/cards/${cardId}`, {
|
|
@@ -4198,15 +4226,28 @@ archiveCmd.command("purge <cardId>").description("Permanently delete an archived
|
|
|
4198
4226
|
console.log(`\u2713 card ${cardId} permanently deleted`);
|
|
4199
4227
|
});
|
|
4200
4228
|
var checklistCmd = program2.command("checklist").description("Card checklist items");
|
|
4201
|
-
checklistCmd.command("add <cardId>
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4229
|
+
checklistCmd.command("add <cardId> [titles...]").description("Add one or more checklist items (repeat titles, or --file with one per line)").option("--file <path>", "read items from a file, one per line (or - for stdin)").action(async (cardId, titles, opts) => {
|
|
4230
|
+
let items = titles ?? [];
|
|
4231
|
+
if (opts.file) {
|
|
4232
|
+
const text = await readTextArg(opts.file);
|
|
4233
|
+
items = items.concat(
|
|
4234
|
+
text.split(/\r?\n/).map((s) => s.trim()).filter(Boolean)
|
|
4235
|
+
);
|
|
4236
|
+
}
|
|
4237
|
+
if (items.length === 0) {
|
|
4238
|
+
console.error("Provide at least one item title, or --file <path>");
|
|
4239
|
+
process.exit(1);
|
|
4240
|
+
}
|
|
4241
|
+
const created = [];
|
|
4242
|
+
for (const title of items) {
|
|
4243
|
+
created.push(
|
|
4244
|
+
await api(`/api/cards/${cardId}/checklist-items`, {
|
|
4245
|
+
method: "POST",
|
|
4246
|
+
body: JSON.stringify({ title })
|
|
4247
|
+
})
|
|
4248
|
+
);
|
|
4249
|
+
}
|
|
4250
|
+
show(created, [`\u2713 ${created.length} checklist item(s) added`]);
|
|
4210
4251
|
});
|
|
4211
4252
|
checklistCmd.command("toggle <itemId>").description("Toggle a checklist item to checked/unchecked").option("--check", "Mark as checked", false).option("--uncheck", "Mark as unchecked", false).action(
|
|
4212
4253
|
async (itemId, opts) => {
|
|
@@ -4804,24 +4845,18 @@ program2.command("init").description(
|
|
|
4804
4845
|
show(void 0, [...actions, ...next]);
|
|
4805
4846
|
}
|
|
4806
4847
|
);
|
|
4807
|
-
program2.command("create <title>").description(`Create a card on the resolved board (${CONFIG_FILENAME}, default "main")`).option("-b, --board <label>", "board label from config").option("--board-id <id>", "explicit board id (bypass config)").option("-l, --list <name>", "target list name (default: first list)").option("-d, --desc <text>", "card description (Markdown)").action(async (title, opts) => {
|
|
4848
|
+
program2.command("create <title>").description(`Create a card on the resolved board (${CONFIG_FILENAME}, default "main")`).option("-b, --board <label>", "board label from config").option("--board-id <id>", "explicit board id (bypass config)").option("-l, --list <name>", "target list name (default: first list)").option("-d, --desc <text>", "card description (Markdown)").option("--desc-file <path>", "read description from a file (or - for stdin)").action(async (title, opts) => {
|
|
4808
4849
|
const ctx = resolveContext(opts);
|
|
4809
4850
|
const detail = await fetchBoard(ctx.boardId, ctx.baseUrl);
|
|
4810
4851
|
const list = opts.list ? findListByName(detail, opts.list) : detail.lists[0];
|
|
4811
4852
|
if (!list)
|
|
4812
4853
|
throw new Error(`Board ${ctx.boardId} has no lists`);
|
|
4854
|
+
const description = opts.descFile ? await readTextArg(opts.descFile) : opts.desc;
|
|
4813
4855
|
const card = await api(
|
|
4814
4856
|
`/api/lists/${list.id}/cards`,
|
|
4815
|
-
{ method: "POST", body: JSON.stringify({ title }) },
|
|
4857
|
+
{ method: "POST", body: JSON.stringify(description ? { title, description } : { title }) },
|
|
4816
4858
|
ctx.baseUrl
|
|
4817
4859
|
);
|
|
4818
|
-
if (opts.desc) {
|
|
4819
|
-
await api(
|
|
4820
|
-
`/api/cards/${card.id}`,
|
|
4821
|
-
{ method: "PATCH", body: JSON.stringify({ description: opts.desc }) },
|
|
4822
|
-
ctx.baseUrl
|
|
4823
|
-
);
|
|
4824
|
-
}
|
|
4825
4860
|
show(card, [`\u2713 created ${card.id} "${title}" in ${list.title} (board ${ctx.entry.label})`]);
|
|
4826
4861
|
});
|
|
4827
4862
|
program2.command("read").description(`Show the resolved board \u2014 lists + cards (${CONFIG_FILENAME}, default "main")`).option("-b, --board <label>", "board label from config").option("--board-id <id>", "explicit board id (bypass config)").action(async (opts) => {
|