@paneui/cli 0.0.6 → 0.0.8

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,9 +1,9 @@
1
- // `pane session participant <new|revoke>` — mint or invalidate one
2
- // participant URL on an existing session. Recovery + leak-containment
3
- // primitives that together replace the destructive `pane session delete +
4
- // pane session create` workaround for the lost-URL case.
1
+ // `pane surface participant <new|revoke>` — mint or invalidate one
2
+ // participant URL on an existing surface. Recovery + leak-containment
3
+ // primitives that together replace the destructive `pane surface delete +
4
+ // pane surface create` workaround for the lost-URL case.
5
5
  //
6
- // This file is a sub-noun dispatcher under `pane session`. The session
6
+ // This file is a sub-noun dispatcher under `pane surface`. The surface
7
7
  // dispatcher hands us a ParsedArgs whose positionals[0] is "participant"
8
8
  // (our sub-noun marker), so we read the verb from positionals[1] and the
9
9
  // args from positionals[2..]. This mirrors the way every other sub-verb
@@ -14,32 +14,32 @@ import { makeClient } from "../config.js";
14
14
  import { printJson, fail, failFromError } from "../output.js";
15
15
  const NO_FLAGS = [];
16
16
  const NO_BOOLS = [];
17
- export const participantHelp = `pane session participant — manage one session's participant URLs
17
+ export const participantHelp = `pane surface participant — manage one surface's participant URLs
18
18
 
19
19
  Participant tokens are stored hashed on the relay and CANNOT be recovered.
20
20
  If you lost the create-response (and the URL with it), use 'new' to mint a
21
- fresh URL — the session keeps its event log, artifact pin, and created_at.
22
- Use 'revoke' to invalidate a single URL while keeping the session alive.
21
+ fresh URL — the surface keeps its event log, template pin, and created_at.
22
+ Use 'revoke' to invalidate a single URL while keeping the surface alive.
23
23
 
24
24
  Usage:
25
- pane session participant <verb> <args>
25
+ pane surface participant <verb> <args>
26
26
 
27
27
  Verbs:
28
- list <session-id> List the participants on one session, including
28
+ list <surface-id> List the participants on one surface, including
29
29
  revoked rows (for audit). Returns
30
- { session_id, items: [...] } where each item
30
+ { surface_id, items: [...] } where each item
31
31
  carries { participant_id, kind, token_prefix,
32
32
  joined_at, revoked_at }. Use this to find the
33
33
  participant_id you need to pass to 'revoke'.
34
34
 
35
- new <session-id> Mint a fresh human URL on an existing session.
35
+ new <surface-id> Mint a fresh human URL on an existing surface.
36
36
  Returns { participant_id, kind, token, url,
37
37
  created_at } — ONCE. The plaintext token is
38
38
  never recoverable; save the response (pipe to
39
39
  a JSONL log) before delivering the URL.
40
40
 
41
- revoke <session-id> <participant-id>
42
- Invalidate one participant URL. The session's
41
+ revoke <surface-id> <participant-id>
42
+ Invalidate one participant URL. The surface's
43
43
  other participants (and the agent's own
44
44
  websocket) are untouched. Idempotent: running
45
45
  revoke twice still returns success.
@@ -54,24 +54,24 @@ Options:
54
54
  -h, --help Show this help.
55
55
 
56
56
  Recovery recipe:
57
- pane session list # find session_id
58
- pane session participant list <session-id> # find participant
57
+ pane surface list # find surface_id
58
+ pane surface participant list <surface-id> # find participant
59
59
  # ids on that
60
- # session
61
- pane session participant new <session-id> # mint a new URL
62
- pane session participant revoke <session-id> <p-id> # invalidate the
60
+ # surface
61
+ pane surface participant new <surface-id> # mint a new URL
62
+ pane surface participant revoke <surface-id> <p-id> # invalidate the
63
63
  # old URL
64
64
 
65
65
  Output: stdout is machine-readable JSON.`;
66
66
  async function runParticipantList(args) {
67
- assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane session participant list");
68
- const sessionId = args.positionals[1];
69
- if (!sessionId) {
70
- fail("missing <session-id> — usage: pane session participant list <session-id>", "invalid_args");
67
+ assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane surface participant list");
68
+ const surfaceId = args.positionals[1];
69
+ if (!surfaceId) {
70
+ fail("missing <surface-id> — usage: pane surface participant list <surface-id>", "invalid_args");
71
71
  }
72
72
  const client = makeClient(args);
73
73
  try {
74
- const res = await client.listParticipants(sessionId);
74
+ const res = await client.listParticipants(surfaceId);
75
75
  printJson(res);
76
76
  }
77
77
  catch (e) {
@@ -79,14 +79,14 @@ async function runParticipantList(args) {
79
79
  }
80
80
  }
81
81
  async function runParticipantNew(args) {
82
- assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane session participant new");
83
- const sessionId = args.positionals[1];
84
- if (!sessionId) {
85
- fail("missing <session-id> — usage: pane session participant new <session-id>", "invalid_args");
82
+ assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane surface participant new");
83
+ const surfaceId = args.positionals[1];
84
+ if (!surfaceId) {
85
+ fail("missing <surface-id> — usage: pane surface participant new <surface-id>", "invalid_args");
86
86
  }
87
87
  const client = makeClient(args);
88
88
  try {
89
- const res = await client.mintParticipant(sessionId);
89
+ const res = await client.mintParticipant(surfaceId);
90
90
  printJson(res);
91
91
  }
92
92
  catch (e) {
@@ -94,17 +94,17 @@ async function runParticipantNew(args) {
94
94
  }
95
95
  }
96
96
  async function runParticipantRevoke(args) {
97
- assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane session participant revoke");
98
- const sessionId = args.positionals[1];
97
+ assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane surface participant revoke");
98
+ const surfaceId = args.positionals[1];
99
99
  const participantId = args.positionals[2];
100
- if (!sessionId || !participantId) {
101
- fail("missing arguments — usage: pane session participant revoke <session-id> <participant-id>", "invalid_args");
100
+ if (!surfaceId || !participantId) {
101
+ fail("missing arguments — usage: pane surface participant revoke <surface-id> <participant-id>", "invalid_args");
102
102
  }
103
103
  const client = makeClient(args);
104
104
  try {
105
- await client.revokeParticipant(sessionId, participantId);
105
+ await client.revokeParticipant(surfaceId, participantId);
106
106
  printJson({
107
- session_id: sessionId,
107
+ surface_id: surfaceId,
108
108
  participant_id: participantId,
109
109
  revoked: true,
110
110
  });
@@ -115,7 +115,7 @@ async function runParticipantRevoke(args) {
115
115
  }
116
116
  export async function runParticipant(args) {
117
117
  // positionals[0] is the verb (list | new | revoke), positionals[1..] are
118
- // the verb's args. (The session.ts dispatcher already shifted off the
118
+ // the verb's args. (The surface.ts dispatcher already shifted off the
119
119
  // "participant" marker before calling us.)
120
120
  const verb = args.positionals[0];
121
121
  switch (verb) {
@@ -129,9 +129,9 @@ export async function runParticipant(args) {
129
129
  await runParticipantRevoke(args);
130
130
  break;
131
131
  case undefined:
132
- fail("missing verb — usage: pane session participant <list|new|revoke> (run 'pane session participant --help')", "invalid_args");
132
+ fail("missing verb — usage: pane surface participant <list|new|revoke> (run 'pane surface participant --help')", "invalid_args");
133
133
  break;
134
134
  default:
135
- fail(`unknown participant verb '${verb}' — expected list|new|revoke (run 'pane session participant --help')`, "invalid_args");
135
+ fail(`unknown participant verb '${verb}' — expected list|new|revoke (run 'pane surface participant --help')`, "invalid_args");
136
136
  }
137
137
  }
@@ -1,32 +1,38 @@
1
- // `pane session send <id>` — append an agent event to a session.
1
+ // `pane surface send <id>` — append an agent event to a surface.
2
2
  import { readFileSync } from "node:fs";
3
3
  import { basename } from "node:path";
4
4
  import { assertKnownFlags } from "../argv.js";
5
5
  import { makeClient } from "../config.js";
6
6
  import { resolveJson } from "../input.js";
7
7
  import { printJson, fail, failFromError } from "../output.js";
8
- const KNOWN_FLAGS = ["type", "data", "blob", "causation-id", "idempotency-key"];
8
+ const KNOWN_FLAGS = [
9
+ "type",
10
+ "data",
11
+ "attachment",
12
+ "causation-id",
13
+ "idempotency-key",
14
+ ];
9
15
  const KNOWN_BOOLS = [];
10
- export const sendHelp = `pane session send — emit an agent event into a session
16
+ export const sendHelp = `pane surface send — emit an agent event into a surface
11
17
 
12
18
  Usage:
13
- pane session send <session-id> --type <event-type> --data <path|json> [options]
14
- pane session send <session-id> --type <event-type> --blob <file-path> [options]
19
+ pane surface send <surface-id> --type <event-type> --data <path|json> [options]
20
+ pane surface send <surface-id> --type <event-type> --attachment <file-path> [options]
15
21
 
16
- POSTs an event to /v1/sessions/:id/events. The event is stamped as authored by
22
+ POSTs an event to /v1/surfaces/:id/events. The event is stamped as authored by
17
23
  the agent (the relay derives identity from the API key — it cannot be spoofed).
18
24
 
19
25
  Required:
20
- --type <t> Event type. Must exist in the session's event schema
26
+ --type <t> Event type. Must exist in the surface's event schema
21
27
  with the agent in its emittedBy list.
22
28
  --data <v> Event payload: a file path to a .json file, or inline
23
29
  JSON. Use --data 'null' or --data '{}' for no payload.
24
30
 
25
31
  ALTERNATIVE to --data:
26
- --blob <path> One-shot: upload <path> as a session-scope blob, then
27
- send an event whose payload is the BlobRef. The event
28
- data is { blob: <BlobRef> }; declare it in your event
29
- schema with \`format: pane-blob-id\` on \`blob.blob_id\`.
32
+ --attachment <path> One-shot: upload <path> as a surface-scope attachment, then
33
+ send an event whose payload is the AttachmentRef. The event
34
+ data is { attachment: <AttachmentRef> }; declare it in your event
35
+ schema with \`format: pane-attachment-id\` on \`attachment.attachment_id\`.
30
36
 
31
37
  Options:
32
38
  --causation-id <id> Opaque causation id stored verbatim on the event.
@@ -38,42 +44,42 @@ Options:
38
44
  Output (stdout, JSON):
39
45
  { event, deduped }`;
40
46
  export async function runSend(args) {
41
- assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane session send");
42
- const sessionId = args.positionals[0];
43
- if (!sessionId)
44
- fail("missing <session-id>", "invalid_args");
47
+ assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane surface send");
48
+ const surfaceId = args.positionals[0];
49
+ if (!surfaceId)
50
+ fail("missing <surface-id>", "invalid_args");
45
51
  const type = args.flags.get("type");
46
52
  if (!type)
47
53
  fail("missing --type", "invalid_args");
48
54
  const dataRaw = args.flags.get("data");
49
- const blobPath = args.flags.get("blob");
55
+ const blobPath = args.flags.get("attachment");
50
56
  if (dataRaw !== undefined && blobPath !== undefined) {
51
- fail("--data and --blob are mutually exclusive", "invalid_args");
57
+ fail("--data and --attachment are mutually exclusive", "invalid_args");
52
58
  }
53
59
  if (dataRaw === undefined && blobPath === undefined) {
54
- fail("missing --data or --blob", "invalid_args");
60
+ fail("missing --data or --attachment", "invalid_args");
55
61
  }
56
62
  const client = makeClient(args);
57
- // --blob path: upload the file as a session-scope blob, then send an
58
- // event whose data is { blob: <BlobRef> }. The session's event schema
59
- // is expected to declare a blob field with format: pane-blob-id.
63
+ // --attachment path: upload the file as a surface-scope attachment, then send an
64
+ // event whose data is { attachment: <AttachmentRef> }. The surface's event schema
65
+ // is expected to declare a attachment field with format: pane-attachment-id.
60
66
  if (blobPath !== undefined) {
61
67
  let bytes;
62
68
  try {
63
69
  bytes = readFileSync(blobPath);
64
70
  }
65
71
  catch (e) {
66
- fail(`failed to read --blob '${blobPath}': ${e instanceof Error ? e.message : String(e)}`, "invalid_args");
72
+ fail(`failed to read --attachment '${blobPath}': ${e instanceof Error ? e.message : String(e)}`, "invalid_args");
67
73
  }
68
74
  try {
69
75
  const ref = await client.uploadBlob(bytes, {
70
- scope: "session",
71
- sessionId: sessionId,
76
+ scope: "surface",
77
+ surfaceId: surfaceId,
72
78
  filename: basename(blobPath),
73
79
  });
74
- const res = await client.sendEvent(sessionId, {
80
+ const res = await client.sendEvent(surfaceId, {
75
81
  type: type,
76
- data: { blob: ref },
82
+ data: { attachment: ref },
77
83
  causationId: args.flags.get("causation-id"),
78
84
  idempotencyKey: args.flags.get("idempotency-key"),
79
85
  });
@@ -92,7 +98,7 @@ export async function runSend(args) {
92
98
  fail(e instanceof Error ? e.message : String(e), "invalid_args");
93
99
  }
94
100
  try {
95
- const res = await client.sendEvent(sessionId, {
101
+ const res = await client.sendEvent(surfaceId, {
96
102
  type: type,
97
103
  data,
98
104
  causationId: args.flags.get("causation-id"),
@@ -1,22 +1,22 @@
1
- // `pane session show <id>` — snapshot of a session, optionally long-polled.
1
+ // `pane surface show <id>` — snapshot of a surface, optionally long-polled.
2
2
  import { assertKnownFlags } from "../argv.js";
3
3
  import { makeClient } from "../config.js";
4
4
  import { printJson, fail, failFromError } from "../output.js";
5
5
  const KNOWN_FLAGS = ["since", "wait"];
6
6
  const KNOWN_BOOLS = [];
7
- export const stateHelp = `pane session show — show a session's metadata and event log
7
+ export const stateHelp = `pane surface show — show a surface's metadata and event log
8
8
 
9
9
  Usage:
10
- pane session show <session-id> [options]
10
+ pane surface show <surface-id> [options]
11
11
 
12
- By default non-blocking: fetches session metadata (GET /v1/sessions/:id) plus
13
- the event log (GET /v1/sessions/:id/events) and prints them together.
12
+ By default non-blocking: fetches surface metadata (GET /v1/surfaces/:id) plus
13
+ the event log (GET /v1/surfaces/:id/events) and prints them together.
14
14
 
15
15
  With --wait, blocks at the relay for up to <secs> if no new events are
16
16
  available since the cursor — returns as soon as something lands. Use this
17
17
  for headless polling agents that can't keep a WebSocket open (cron,
18
18
  FaaS, slow links): poll, then re-poll using next_cursor as --since on the
19
- next call. Compared to 'pane session watch', it's higher latency per
19
+ next call. Compared to 'pane surface watch', it's higher latency per
20
20
  round-trip but no long-lived connection.
21
21
 
22
22
  Options:
@@ -34,10 +34,10 @@ Options:
34
34
  Output (stdout, JSON):
35
35
  { meta, events, next_cursor }`;
36
36
  export async function runState(args) {
37
- assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane session show");
38
- const sessionId = args.positionals[0];
39
- if (!sessionId)
40
- fail("missing <session-id>", "invalid_args");
37
+ assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane surface show");
38
+ const surfaceId = args.positionals[0];
39
+ if (!surfaceId)
40
+ fail("missing <surface-id>", "invalid_args");
41
41
  const since = args.flags.get("since") ?? null;
42
42
  // --wait <secs>: hand the server the long-poll window. The relay caps
43
43
  // this at 30s; we pass the raw value and let the relay clamp (sending
@@ -54,8 +54,8 @@ export async function runState(args) {
54
54
  }
55
55
  const client = makeClient(args);
56
56
  try {
57
- const meta = await client.getSession(sessionId);
58
- const page = await client.getEvents(sessionId, {
57
+ const meta = await client.getSession(surfaceId);
58
+ const page = await client.getEvents(surfaceId, {
59
59
  since,
60
60
  ...(waitSeconds !== undefined ? { waitSeconds } : {}),
61
61
  });
@@ -1,14 +1,14 @@
1
- // `pane session` — the central noun of pane: open, observe, send to, and
2
- // close a session.
1
+ // `pane surface` — the central noun of pane: open, observe, send to, and
2
+ // close a surface.
3
3
  //
4
- // A session is one *use* of an artifact: an open URL the human(s) interact
4
+ // A surface is one *use* of an template: an open URL the human(s) interact
5
5
  // with, plus an event log the agent reads and appends to. Every other noun
6
- // (artifact, blob, key, taste, feedback) exists in service of sessions.
6
+ // (template, attachment, key, taste, feedback) exists in service of surfaces.
7
7
  //
8
8
  // This file is a thin dispatcher — each verb's actual logic lives in its own
9
9
  // file (create.ts, state.ts, send.ts, watch.ts, delete.ts). The verb runners
10
- // expect the session id at positionals[0]; we slice off our own verb before
11
- // delegating so they don't need to know they're being called via `session`.
10
+ // expect the surface id at positionals[0]; we slice off our own verb before
11
+ // delegating so they don't need to know they're being called via `surface`.
12
12
  import { runCreate } from "./create.js";
13
13
  import { runState } from "./state.js";
14
14
  import { runSend } from "./send.js";
@@ -17,39 +17,39 @@ import { runDelete } from "./delete.js";
17
17
  import { runList, listHelp } from "./list.js";
18
18
  import { runParticipant, participantHelp } from "./participant.js";
19
19
  import { fail } from "../output.js";
20
- export const sessionHelp = `pane session — open, observe, send to, and close sessions
20
+ export const sessionHelp = `pane surface — open, observe, send to, and close surfaces
21
21
 
22
- A session is one use of an artifact: an open URL the human(s) interact with,
22
+ A surface is one use of an template: an open URL the human(s) interact with,
23
23
  plus an event log the agent reads and appends to.
24
24
 
25
25
  Usage:
26
- pane session <verb> [options]
26
+ pane surface <verb> [options]
27
27
 
28
28
  Verbs:
29
- create Create a session (POST /v1/sessions). Prints session_id,
29
+ create Create a surface (POST /v1/surfaces). Prints surface_id,
30
30
  urls, tokens, expires_at.
31
- list Enumerate YOUR agent's sessions. The recovery primitive
32
- for "I dropped the create response" — sessions are
31
+ list Enumerate YOUR agent's surfaces. The recovery primitive
32
+ for "I dropped the create response" — surfaces are
33
33
  listable, but participant tokens are stored hashed and
34
34
  CANNOT be recovered. Use 'participant new' to mint a
35
35
  fresh URL.
36
- show <id> Non-blocking snapshot: session metadata + event log.
36
+ show <id> Non-blocking snapshot: surface metadata + event log.
37
37
  Supports --wait <secs> for relay-side long-polling.
38
- send <id> Emit an agent event into a session.
39
- watch <id> Stream a session's events as JSON-lines on stdout
38
+ send <id> Emit an agent event into a surface.
39
+ watch <id> Stream a surface's events as JSON-lines on stdout
40
40
  (long-lived; the building block for pipe-readers).
41
- delete <id> Close/delete a session (DELETE /v1/sessions/:id).
41
+ delete <id> Close/delete a surface (DELETE /v1/surfaces/:id).
42
42
  participant List / mint / revoke participant URLs on an existing
43
- <list|new|revoke> session. 'list' returns the participant ids you need
43
+ <list|new|revoke> surface. 'list' returns the participant ids you need
44
44
  for 'revoke'; 'new' replaces the destructive 'delete
45
45
  + recreate' workaround for a lost URL; 'revoke'
46
- invalidates one URL without touching the session.
46
+ invalidates one URL without touching the surface.
47
47
 
48
- Run \`pane session <verb> --help\` for verb-specific options.`;
48
+ Run \`pane surface <verb> --help\` for verb-specific options.`;
49
49
  /**
50
50
  * Build a new ParsedArgs with the leading positional (the verb) stripped.
51
51
  * The downstream verb runners (runState / runSend / runWatch / runDelete)
52
- * read the session id at positionals[0], so we hand them an args object that
52
+ * read the surface id at positionals[0], so we hand them an args object that
53
53
  * looks exactly like the pre-restructure invocation.
54
54
  */
55
55
  function shiftPositionals(args) {
@@ -68,7 +68,7 @@ function shiftPositionals(args) {
68
68
  }
69
69
  export async function runSession(args) {
70
70
  const verb = args.positionals[0];
71
- // `pane session participant --help` (verb-level help on the participant
71
+ // `pane surface participant --help` (verb-level help on the participant
72
72
  // sub-noun, with no further sub-verb). The general --help pre-empt in
73
73
  // index.ts only fires when no positional follows the noun; here a
74
74
  // positional ("participant") is present, so the sub-noun must own its own
@@ -79,7 +79,7 @@ export async function runSession(args) {
79
79
  process.stdout.write(participantHelp + "\n");
80
80
  return;
81
81
  }
82
- // `pane session list --help` — same pattern.
82
+ // `pane surface list --help` — same pattern.
83
83
  if (verb === "list" &&
84
84
  args.bools.has("help") &&
85
85
  args.positionals.length === 1) {
@@ -110,9 +110,9 @@ export async function runSession(args) {
110
110
  await runParticipant(inner);
111
111
  break;
112
112
  case undefined:
113
- fail("missing verb — usage: pane session <create|list|show|send|watch|delete|participant> (run 'pane session --help')", "invalid_args");
113
+ fail("missing verb — usage: pane surface <create|list|show|send|watch|delete|participant> (run 'pane surface --help')", "invalid_args");
114
114
  break;
115
115
  default:
116
- fail(`unknown session verb '${verb}' — expected create|list|show|send|watch|delete|participant (run 'pane session --help')`, "invalid_args");
116
+ fail(`unknown surface verb '${verb}' — expected create|list|show|send|watch|delete|participant (run 'pane surface --help')`, "invalid_args");
117
117
  }
118
118
  }
@@ -1,21 +1,21 @@
1
1
  // `pane taste` — read / write / clear the calling agent's freeform "taste
2
- // notes" markdown blob.
2
+ // notes" markdown attachment.
3
3
  //
4
4
  // Taste notes are presentation preferences the agent has learned from human
5
5
  // feedback ("denser layout", "no rounded corners", "use a dark header") — the
6
- // kind of guidance that should outlive a single session. The intended loop:
6
+ // kind of guidance that should outlive a single surface. The intended loop:
7
7
  //
8
- // 1. Before generating a pane artifact, run `pane taste get` and feed the
8
+ // 1. Before generating a pane template, run `pane taste get` and feed the
9
9
  // `taste` field into the prompt so prior preferences shape the output.
10
10
  // 2. When the human gives new presentation feedback, run `pane taste get`,
11
11
  // merge the feedback into the existing notes IN THE PROMPT, then call
12
- // `pane taste set` with the WHOLE new blob (the relay does whole-blob
12
+ // `pane taste set` with the WHOLE new attachment (the relay does whole-attachment
13
13
  // replace, not append — that's deliberate, so the notes can't grow
14
14
  // unbounded into noise).
15
15
  //
16
16
  // Keep taste notes about *presentation/UI taste only* — colours, density,
17
- // component preferences. Project context, todos, and per-session state belong
18
- // somewhere else. Today the blob is keyed by the agent's API key (per-agent);
17
+ // component preferences. Project context, todos, and per-surface state belong
18
+ // somewhere else. Today the attachment is keyed by the agent's API key (per-agent);
19
19
  // when pane gains first-class humans, this may move to per-human.
20
20
  import { readFileSync } from "node:fs";
21
21
  import { assertKnownFlags } from "../argv.js";
@@ -27,25 +27,25 @@ const SET_FLAGS = ["file"];
27
27
  const CLEAR_BOOLS = ["yes"];
28
28
  export const tasteHelp = `pane taste — read / write / clear YOUR agent's UI taste notes
29
29
 
30
- Taste notes are a small markdown blob storing presentation preferences your
30
+ Taste notes are a small markdown attachment storing presentation preferences your
31
31
  agent has picked up from human feedback ("denser table", "no rounded corners",
32
- "use a dark header"). Read them before generating a pane artifact so prior
32
+ "use a dark header"). Read them before generating a pane template so prior
33
33
  feedback shapes the output; rewrite them whenever the human gives new
34
34
  presentation feedback. Keep entries about UI/presentation taste only — not
35
- project context, todos, or session state.
35
+ project context, todos, or surface state.
36
36
 
37
37
  Usage:
38
38
  pane taste <subcommand> [options]
39
39
 
40
40
  Subcommands:
41
- get Print the current notes blob:
41
+ get Print the current notes attachment:
42
42
  { taste: string|null, updated_at: string|null, bytes: number }.
43
43
  taste is null and bytes is 0 when notes have never been written.
44
44
 
45
- set Whole-blob replace. Source the markdown via --file <path>,
45
+ set Whole-attachment replace. Source the markdown via --file <path>,
46
46
  --file - (read stdin), or by piping into 'pane taste set' with
47
47
  no flag. The relay rejects empty/whitespace-only payloads and
48
- caps the blob at MAX_TASTE_BYTES (utf8). To clear the notes,
48
+ caps the attachment at MAX_TASTE_BYTES (utf8). To clear the notes,
49
49
  use 'pane taste clear', not 'set' with an empty body.
50
50
 
51
51
  clear Delete the notes. Requires --yes (it is destructive). Prints
@@ -92,7 +92,7 @@ async function runTasteGet(args) {
92
92
  async function runTasteSet(args) {
93
93
  assertKnownFlags(args, SET_FLAGS, NO_BOOLS, "pane taste set");
94
94
  const filePath = args.flags.get("file");
95
- // Source the blob deterministically — no isTTY-flag fusing, because
95
+ // Source the attachment deterministically — no isTTY-flag fusing, because
96
96
  // `!process.stdin.isTTY` is true under every non-interactive caller
97
97
  // (pipes, redirects, closed fd, CI, agent harnesses) and would wrongly
98
98
  // reject `--file` for the entire target audience. See issue #148.
@@ -119,7 +119,7 @@ async function runTasteSet(args) {
119
119
  fail("'pane taste set' needs input — pass --file <path>, pipe markdown on stdin, or use --file -", "invalid_args");
120
120
  }
121
121
  if (taste.trim().length === 0) {
122
- fail("'pane taste set' refuses an empty or whitespace-only blob — use 'pane taste clear --yes' to delete the notes", "invalid_args");
122
+ fail("'pane taste set' refuses an empty or whitespace-only attachment — use 'pane taste clear --yes' to delete the notes", "invalid_args");
123
123
  }
124
124
  const client = makeClient(args);
125
125
  try {