claude-yes 1.80.0 → 1.82.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.
@@ -1,6 +1,6 @@
1
- import { t as CLIS_CONFIG } from "./ts-DJTdHpX6.js";
1
+ import { t as CLIS_CONFIG } from "./ts-WV8trEPX.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./versionChecker-iWnXmXoS.js";
3
+ import "./versionChecker-BVt2a2mL.js";
4
4
  import "./pidStore-C1JXxoPi.js";
5
5
  import "./globalPidIndex-Cr-g75QF.js";
6
6
 
@@ -9,4 +9,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
9
9
 
10
10
  //#endregion
11
11
  export { SUPPORTED_CLIS };
12
- //# sourceMappingURL=SUPPORTED_CLIS-ujFlzMra.js.map
12
+ //# sourceMappingURL=SUPPORTED_CLIS-WKiG4dyQ.js.map
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  import { n as logger } from "./logger-B9h0djqx.js";
3
- import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-iWnXmXoS.js";
3
+ import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-BVt2a2mL.js";
4
4
  import { argv } from "process";
5
5
  import { execFileSync, spawn } from "child_process";
6
6
  import ms from "ms";
@@ -475,7 +475,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
475
475
  }
476
476
  }
477
477
  {
478
- const { isSubcommand, runSubcommand } = await import("./subcommands-BVcxPfly.js");
478
+ const { isSubcommand, runSubcommand } = await import("./subcommands-eMrWDGMq.js");
479
479
  if (isSubcommand(process.argv[2])) {
480
480
  const code = await runSubcommand(process.argv);
481
481
  process.exit(code ?? 0);
@@ -504,7 +504,7 @@ if (config.useRust) {
504
504
  }
505
505
  }
506
506
  if (rustBinary) {
507
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-ujFlzMra.js");
507
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-WKiG4dyQ.js");
508
508
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
509
509
  if (config.verbose) {
510
510
  console.log(`[rust] Using binary: ${rustBinary}`);
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-DJTdHpX6.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-WV8trEPX.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./versionChecker-iWnXmXoS.js";
3
+ import "./versionChecker-BVt2a2mL.js";
4
4
  import "./pidStore-C1JXxoPi.js";
5
5
  import "./globalPidIndex-Cr-g75QF.js";
6
6
 
@@ -1,6 +1,6 @@
1
1
  import "./logger-B9h0djqx.js";
2
2
  import { r as readGlobalPids } from "./globalPidIndex-Cr-g75QF.js";
3
- import { readFile, stat } from "fs/promises";
3
+ import { appendFile, mkdir, readFile, stat, writeFile } from "fs/promises";
4
4
  import { homedir } from "os";
5
5
  import path from "path";
6
6
 
@@ -17,6 +17,47 @@ import path from "path";
17
17
  * Returns null when argv[2] is not a known subcommand so cli.ts falls through
18
18
  * to the normal agent-spawning flow.
19
19
  */
20
+ function notesPath() {
21
+ const dir = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
22
+ return path.join(dir, "notes.jsonl");
23
+ }
24
+ async function readNotes() {
25
+ let raw;
26
+ try {
27
+ raw = await readFile(notesPath(), "utf-8");
28
+ } catch {
29
+ return /* @__PURE__ */ new Map();
30
+ }
31
+ const map = /* @__PURE__ */ new Map();
32
+ for (const line of raw.split("\n")) {
33
+ const t = line.trim();
34
+ if (!t) continue;
35
+ try {
36
+ const { pid, note } = JSON.parse(t);
37
+ if (typeof pid === "number") if (note) map.set(pid, note);
38
+ else map.delete(pid);
39
+ } catch {}
40
+ }
41
+ return map;
42
+ }
43
+ async function writeNote(pid, note) {
44
+ const p = notesPath();
45
+ await mkdir(path.dirname(p), { recursive: true });
46
+ await appendFile(p, JSON.stringify({
47
+ pid,
48
+ note,
49
+ updated_at: Date.now()
50
+ }) + "\n");
51
+ }
52
+ async function compactNotes() {
53
+ const map = await readNotes();
54
+ const lines = Array.from(map.entries()).map(([pid, note]) => JSON.stringify({
55
+ pid,
56
+ note,
57
+ updated_at: Date.now()
58
+ })).join("\n");
59
+ await writeFile(notesPath(), lines ? lines + "\n" : "");
60
+ }
20
61
  /**
21
62
  * Read the per-cwd TS PidStore JSONL and convert to the global record shape,
22
63
  * so pre-existing TS agents that were spawned before the global-index mirror
@@ -82,7 +123,8 @@ const SUBCOMMANDS = new Set([
82
123
  "tail",
83
124
  "head",
84
125
  "send",
85
- "restart"
126
+ "restart",
127
+ "note"
86
128
  ]);
87
129
  function isSubcommand(name) {
88
130
  return !!name && SUBCOMMANDS.has(name);
@@ -106,6 +148,7 @@ async function runSubcommand(argv) {
106
148
  case "head": return await cmdRead(rest, { mode: "head" });
107
149
  case "send": return await cmdSend(rest);
108
150
  case "restart": return await cmdRestart(rest);
151
+ case "note": return await cmdNote(rest);
109
152
  default: return null;
110
153
  }
111
154
  } catch (err) {
@@ -220,6 +263,7 @@ async function cmdLs(rest) {
220
263
  const fixedWidth = widths.pid + widths.cli + widths.status + widths.age + widths.cwd + 10;
221
264
  const promptBudget = Math.max(20, termWidth - fixedWidth - 1);
222
265
  const IDLE_THRESHOLD_MS = 60 * 1e3;
266
+ const notes = await readNotes();
223
267
  const rows = await Promise.all(records.map(async (r) => {
224
268
  let displayStatus;
225
269
  if (!isPidAlive(r.pid)) displayStatus = "stopped";
@@ -227,13 +271,16 @@ async function cmdLs(rest) {
227
271
  const mtime = await stat(r.log_file).then((s) => s.mtimeMs).catch(() => null);
228
272
  displayStatus = mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS ? "idle" : "active";
229
273
  } else displayStatus = "active";
274
+ const label = truncate(notes.get(r.pid) ?? r.prompt ?? "", promptBudget);
275
+ const hasNote = notes.has(r.pid);
230
276
  return {
231
277
  pid: String(r.pid),
232
278
  cli: r.cli,
233
279
  status: displayStatus,
234
280
  age: humanizeAge(Date.now() - r.started_at),
235
281
  cwd: shortenPath(r.cwd),
236
- prompt: truncate(r.prompt ?? "", promptBudget),
282
+ label,
283
+ hasNote,
237
284
  _alive: displayStatus !== "stopped"
238
285
  };
239
286
  }));
@@ -243,7 +290,7 @@ async function cmdLs(rest) {
243
290
  "STATUS".padEnd(widths.status),
244
291
  "AGE".padEnd(widths.age),
245
292
  "CWD".padEnd(widths.cwd),
246
- "PROMPT"
293
+ "NOTE/PROMPT"
247
294
  ].join(" ") + "\n";
248
295
  process.stdout.write(header);
249
296
  for (const r of rows) process.stdout.write([
@@ -252,7 +299,7 @@ async function cmdLs(rest) {
252
299
  r.status.padEnd(widths.status),
253
300
  r.age.padEnd(widths.age),
254
301
  r.cwd.padEnd(widths.cwd),
255
- r.prompt
302
+ r.hasNote ? `* ${r.label}` : r.label
256
303
  ].join(" ") + "\n");
257
304
  if (!opts.json && rows.length > 0) {
258
305
  const alive = rows.find((r) => r._alive);
@@ -263,6 +310,7 @@ async function cmdLs(rest) {
263
310
  hints.push(` cy tail -f ${alive.pid} # follow live output\n`);
264
311
  hints.push(` cy send ${alive.pid} "next: ..." # send a prompt\n`);
265
312
  hints.push(` cy send ${alive.pid} "" --code=ctrl-c # interrupt\n`);
313
+ hints.push(` cy note ${alive.pid} "what it's doing" # set a note\n`);
266
314
  }
267
315
  if (stopped) hints.push(` cy restart ${stopped.pid} # restart stopped agent\n`);
268
316
  if (!alive && !stopped) hints.push(` cy ls --all # show exited agents\n`);
@@ -310,7 +358,9 @@ async function cmdRead(rest, { mode }) {
310
358
  mode,
311
359
  n
312
360
  });
313
- process.stderr.write(`[pid ${record.pid} ${shortenPath(record.cwd)}]\n`);
361
+ const noteLabel = (await readNotes()).get(record.pid);
362
+ const header = noteLabel ? `[pid ${record.pid} ${shortenPath(record.cwd)} * ${noteLabel}]` : `[pid ${record.pid} ${shortenPath(record.cwd)}]`;
363
+ process.stderr.write(header + "\n");
314
364
  process.stdout.write(rendered);
315
365
  if (!rendered.endsWith("\n")) process.stdout.write("\n");
316
366
  if (follow) {
@@ -380,13 +430,18 @@ async function cmdSend(rest) {
380
430
  const { flags, positional } = parseArgs(rest);
381
431
  const opts = commonOpts(flags);
382
432
  const keyword = positional[0];
383
- const message = positional.slice(1).join(" ");
384
- if (!keyword) throw new Error("usage: cy send <keyword> <msg> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
433
+ const rawMessage = positional.slice(1).join(" ");
434
+ if (!keyword) throw new Error("usage: cy send <keyword> <msg|-> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
385
435
  const trailing = controlCodeFromName(typeof flags.code === "string" ? flags.code.toLowerCase() : "enter");
386
436
  const record = await resolveOne(keyword, opts);
387
437
  const fifoPath = record.fifo_file;
388
438
  if (!fifoPath) throw new Error(`pid ${record.pid}: no fifo_file recorded — agent was not started with --stdpush (or was spawned by Rust which doesn't yet support FIFO IPC; see ROADMAP item 10)`);
389
- const body = message ?? "";
439
+ let body;
440
+ if (rawMessage === "-") {
441
+ const chunks = [];
442
+ for await (const chunk of process.stdin) chunks.push(chunk);
443
+ body = Buffer.concat(chunks).toString("utf-8").trimEnd();
444
+ } else body = rawMessage;
390
445
  if (body && trailing) {
391
446
  await writeToIpc(fifoPath, body);
392
447
  await new Promise((r) => setTimeout(r, 200));
@@ -476,7 +531,28 @@ async function cmdRestart(rest) {
476
531
  process.stderr.write(`\n cy tail ${proc.pid} # watch output\n cy ls # list all agents\n`);
477
532
  return 0;
478
533
  }
534
+ async function cmdNote(rest) {
535
+ const { flags, positional } = parseArgs(rest);
536
+ const opts = commonOpts(flags);
537
+ const keyword = positional[0];
538
+ const note = positional.slice(1).join(" ");
539
+ if (!keyword) throw new Error("usage: cy note <keyword> [\"note text\"] (omit text to clear)");
540
+ const record = await resolveOne(keyword, {
541
+ ...opts,
542
+ all: true
543
+ });
544
+ if (!note) {
545
+ await writeNote(record.pid, "");
546
+ await compactNotes();
547
+ process.stdout.write(`cleared note for pid ${record.pid}\n`);
548
+ return 0;
549
+ }
550
+ await writeNote(record.pid, note);
551
+ process.stdout.write(`note set for pid ${record.pid}: ${note}\n`);
552
+ process.stderr.write(`\n cy ls # see updated note in list\n`);
553
+ return 0;
554
+ }
479
555
 
480
556
  //#endregion
481
557
  export { isSubcommand, runSubcommand };
482
- //# sourceMappingURL=subcommands-BVcxPfly.js.map
558
+ //# sourceMappingURL=subcommands-eMrWDGMq.js.map
@@ -1,5 +1,5 @@
1
1
  import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
2
- import { r as getInstalledPackage } from "./versionChecker-iWnXmXoS.js";
2
+ import { r as getInstalledPackage } from "./versionChecker-BVt2a2mL.js";
3
3
  import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-C22d9SRJ.js";
4
4
  import { t as PidStore } from "./pidStore-C1JXxoPi.js";
5
5
  import { arch, platform } from "process";
@@ -1679,4 +1679,4 @@ function sleep(ms) {
1679
1679
 
1680
1680
  //#endregion
1681
1681
  export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
1682
- //# sourceMappingURL=ts-DJTdHpX6.js.map
1682
+ //# sourceMappingURL=ts-WV8trEPX.js.map
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
7
7
 
8
8
  //#region package.json
9
9
  var name = "claude-yes";
10
- var version = "1.80.0";
10
+ var version = "1.82.0";
11
11
 
12
12
  //#endregion
13
13
  //#region ts/versionChecker.ts
@@ -221,4 +221,4 @@ async function displayVersion() {
221
221
 
222
222
  //#endregion
223
223
  export { versionString as i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
224
- //# sourceMappingURL=versionChecker-iWnXmXoS.js.map
224
+ //# sourceMappingURL=versionChecker-BVt2a2mL.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.80.0",
3
+ "version": "1.82.0",
4
4
  "description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "ai",
@@ -307,7 +307,7 @@ describe("subcommands.cmdLs human table", () => {
307
307
  } finally {
308
308
  cap.restore();
309
309
  }
310
- expect(cap.text).toMatch(/PID\s+CLI\s+STATUS\s+AGE\s+CWD\s+PROMPT/);
310
+ expect(cap.text).toMatch(/PID\s+CLI\s+STATUS\s+AGE\s+CWD\s+NOTE\/PROMPT/);
311
311
  expect(cap.text).toMatch(new RegExp(`${process.pid}\\s`));
312
312
  expect(cap.text).toMatch(/claude/);
313
313
  expect(cap.text).toMatch(/table format test/);
package/ts/subcommands.ts CHANGED
@@ -11,11 +11,58 @@
11
11
  * to the normal agent-spawning flow.
12
12
  */
13
13
 
14
- import { readFile, stat } from "fs/promises";
14
+ import { appendFile, mkdir, readFile, stat, writeFile } from "fs/promises";
15
15
  import { homedir } from "os";
16
16
  import path from "path";
17
17
  import { type GlobalPidRecord, readGlobalPids } from "./globalPidIndex.ts";
18
18
 
19
+ // ---------------------------------------------------------------------------
20
+ // notes store (~/.agent-yes/notes.jsonl)
21
+ // ---------------------------------------------------------------------------
22
+
23
+ function notesPath(): string {
24
+ const dir = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
25
+ return path.join(dir, "notes.jsonl");
26
+ }
27
+
28
+ async function readNotes(): Promise<Map<number, string>> {
29
+ let raw: string;
30
+ try {
31
+ raw = await readFile(notesPath(), "utf-8");
32
+ } catch {
33
+ return new Map();
34
+ }
35
+ const map = new Map<number, string>();
36
+ for (const line of raw.split("\n")) {
37
+ const t = line.trim();
38
+ if (!t) continue;
39
+ try {
40
+ const { pid, note } = JSON.parse(t);
41
+ if (typeof pid === "number") {
42
+ if (note) map.set(pid, note);
43
+ else map.delete(pid);
44
+ }
45
+ } catch {
46
+ /* skip */
47
+ }
48
+ }
49
+ return map;
50
+ }
51
+
52
+ async function writeNote(pid: number, note: string): Promise<void> {
53
+ const p = notesPath();
54
+ await mkdir(path.dirname(p), { recursive: true });
55
+ await appendFile(p, JSON.stringify({ pid, note, updated_at: Date.now() }) + "\n");
56
+ }
57
+
58
+ async function compactNotes(): Promise<void> {
59
+ const map = await readNotes();
60
+ const lines = Array.from(map.entries())
61
+ .map(([pid, note]) => JSON.stringify({ pid, note, updated_at: Date.now() }))
62
+ .join("\n");
63
+ await writeFile(notesPath(), lines ? lines + "\n" : "");
64
+ }
65
+
19
66
  /**
20
67
  * Read the per-cwd TS PidStore JSONL and convert to the global record shape,
21
68
  * so pre-existing TS agents that were spawned before the global-index mirror
@@ -76,7 +123,18 @@ function mergeRecords(...buckets: GlobalPidRecord[][]): GlobalPidRecord[] {
76
123
  return Array.from(out.values());
77
124
  }
78
125
 
79
- const SUBCOMMANDS = new Set(["ls", "list", "ps", "read", "cat", "tail", "head", "send", "restart"]);
126
+ const SUBCOMMANDS = new Set([
127
+ "ls",
128
+ "list",
129
+ "ps",
130
+ "read",
131
+ "cat",
132
+ "tail",
133
+ "head",
134
+ "send",
135
+ "restart",
136
+ "note",
137
+ ]);
80
138
 
81
139
  export function isSubcommand(name: string | undefined): boolean {
82
140
  return !!name && SUBCOMMANDS.has(name);
@@ -109,6 +167,8 @@ export async function runSubcommand(argv: string[]): Promise<number | null> {
109
167
  return await cmdSend(rest);
110
168
  case "restart":
111
169
  return await cmdRestart(rest);
170
+ case "note":
171
+ return await cmdNote(rest);
112
172
  default:
113
173
  return null;
114
174
  }
@@ -300,6 +360,7 @@ async function cmdLs(rest: string[]): Promise<number> {
300
360
  const promptBudget = Math.max(20, termWidth - fixedWidth - 1);
301
361
 
302
362
  const IDLE_THRESHOLD_MS = 60 * 1000;
363
+ const notes = await readNotes();
303
364
  const rows = await Promise.all(
304
365
  records.map(async (r) => {
305
366
  let displayStatus: string;
@@ -314,13 +375,16 @@ async function cmdLs(rest: string[]): Promise<number> {
314
375
  } else {
315
376
  displayStatus = "active";
316
377
  }
378
+ const label = truncate(notes.get(r.pid) ?? r.prompt ?? "", promptBudget);
379
+ const hasNote = notes.has(r.pid);
317
380
  return {
318
381
  pid: String(r.pid),
319
382
  cli: r.cli,
320
383
  status: displayStatus,
321
384
  age: humanizeAge(Date.now() - r.started_at),
322
385
  cwd: shortenPath(r.cwd),
323
- prompt: truncate(r.prompt ?? "", promptBudget),
386
+ label,
387
+ hasNote,
324
388
  _alive: displayStatus !== "stopped",
325
389
  };
326
390
  }),
@@ -333,7 +397,7 @@ async function cmdLs(rest: string[]): Promise<number> {
333
397
  "STATUS".padEnd(widths.status),
334
398
  "AGE".padEnd(widths.age),
335
399
  "CWD".padEnd(widths.cwd),
336
- "PROMPT",
400
+ "NOTE/PROMPT",
337
401
  ].join(" ") + "\n";
338
402
  process.stdout.write(header);
339
403
 
@@ -345,7 +409,7 @@ async function cmdLs(rest: string[]): Promise<number> {
345
409
  r.status.padEnd(widths.status),
346
410
  r.age.padEnd(widths.age),
347
411
  r.cwd.padEnd(widths.cwd),
348
- r.prompt,
412
+ r.hasNote ? `* ${r.label}` : r.label,
349
413
  ].join(" ") + "\n",
350
414
  );
351
415
  }
@@ -359,6 +423,7 @@ async function cmdLs(rest: string[]): Promise<number> {
359
423
  hints.push(` cy tail -f ${alive.pid} # follow live output\n`);
360
424
  hints.push(` cy send ${alive.pid} "next: ..." # send a prompt\n`);
361
425
  hints.push(` cy send ${alive.pid} "" --code=ctrl-c # interrupt\n`);
426
+ hints.push(` cy note ${alive.pid} "what it's doing" # set a note\n`);
362
427
  }
363
428
  if (stopped) {
364
429
  hints.push(` cy restart ${stopped.pid} # restart stopped agent\n`);
@@ -433,7 +498,12 @@ async function cmdRead(rest: string[], { mode }: ReadOpts): Promise<number> {
433
498
 
434
499
  const buf = await readFile(logPath);
435
500
  const rendered = await renderRawLog(buf, { mode, n });
436
- process.stderr.write(`[pid ${record.pid} ${shortenPath(record.cwd)}]\n`);
501
+ const notes = await readNotes();
502
+ const noteLabel = notes.get(record.pid);
503
+ const header = noteLabel
504
+ ? `[pid ${record.pid} ${shortenPath(record.cwd)} * ${noteLabel}]`
505
+ : `[pid ${record.pid} ${shortenPath(record.cwd)}]`;
506
+ process.stderr.write(header + "\n");
437
507
  process.stdout.write(rendered);
438
508
  if (!rendered.endsWith("\n")) process.stdout.write("\n");
439
509
 
@@ -526,10 +596,10 @@ async function cmdSend(rest: string[]): Promise<number> {
526
596
  const { flags, positional } = parseArgs(rest);
527
597
  const opts = commonOpts(flags);
528
598
  const keyword = positional[0];
529
- const message = positional.slice(1).join(" ");
599
+ const rawMessage = positional.slice(1).join(" ");
530
600
 
531
601
  if (!keyword)
532
- throw new Error("usage: cy send <keyword> <msg> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
602
+ throw new Error("usage: cy send <keyword> <msg|-> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
533
603
 
534
604
  const codeName = typeof flags.code === "string" ? flags.code.toLowerCase() : "enter";
535
605
  const trailing = controlCodeFromName(codeName);
@@ -542,7 +612,15 @@ async function cmdSend(rest: string[]): Promise<number> {
542
612
  );
543
613
  }
544
614
 
545
- const body = message ?? "";
615
+ let body: string;
616
+ if (rawMessage === "-") {
617
+ const chunks: Buffer[] = [];
618
+ for await (const chunk of process.stdin) chunks.push(chunk as Buffer);
619
+ body = Buffer.concat(chunks).toString("utf-8").trimEnd();
620
+ } else {
621
+ body = rawMessage;
622
+ }
623
+
546
624
  if (body && trailing) {
547
625
  await writeToIpc(fifoPath, body);
548
626
  await new Promise((r) => setTimeout(r, 200));
@@ -657,3 +735,31 @@ async function cmdRestart(rest: string[]): Promise<number> {
657
735
  );
658
736
  return 0;
659
737
  }
738
+
739
+ // ---------------------------------------------------------------------------
740
+ // cy note
741
+ // ---------------------------------------------------------------------------
742
+
743
+ async function cmdNote(rest: string[]): Promise<number> {
744
+ const { flags, positional } = parseArgs(rest);
745
+ const opts = commonOpts(flags);
746
+ const keyword = positional[0];
747
+ const note = positional.slice(1).join(" ");
748
+
749
+ if (!keyword) throw new Error('usage: cy note <keyword> ["note text"] (omit text to clear)');
750
+
751
+ const record = await resolveOne(keyword, { ...opts, all: true });
752
+
753
+ if (!note) {
754
+ // clear
755
+ await writeNote(record.pid, "");
756
+ await compactNotes();
757
+ process.stdout.write(`cleared note for pid ${record.pid}\n`);
758
+ return 0;
759
+ }
760
+
761
+ await writeNote(record.pid, note);
762
+ process.stdout.write(`note set for pid ${record.pid}: ${note}\n`);
763
+ process.stderr.write(`\n cy ls # see updated note in list\n`);
764
+ return 0;
765
+ }