@ghostystudio/cli 0.63.0 → 0.66.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 (3) hide show
  1. package/README.md +17 -0
  2. package/dist/index.js +126 -33
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -36,6 +36,7 @@ ghosty agents rm <id> [--from-workspace] [--yes] # --from-workspace: turn it o
36
36
  ghosty agents set <id> [--tool wa:tool=off,…] [--bag NAME|none] [--avatar URL|FILE]
37
37
  ghosty agents restart <id>
38
38
  ghosty agents box <id> [--check PATH]… [--contains PATH=TEXT]… [--recycle] # is its machine on the new image?
39
+ ghosty agents box <id> --start # start (or wake) its box now, without spending a turn
39
40
  ghosty agents demo enable|disable <id>
40
41
  ghosty agents demo <id> [--slug NAME] [--expires "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N]
41
42
  [--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate] # public /p/ link, no account needed
@@ -110,6 +111,22 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
110
111
 
111
112
  Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
112
113
 
114
+ ### Changes in 0.66.0
115
+
116
+ - `usage --agent <id> --by visitor`: /c without an account, one row per visitor — USD, messages, page/PDF and whether they created an account — with USD per visitor and per new account.
117
+
118
+ ### Changes in 0.65.0
119
+
120
+ - `agents show <id>`: alias of `agents get`.
121
+ - `agents doctor <id>` prints the agent's card above the checks: engine, model, effort (`FLEET_EFFORT`), native subagents, whether it answers /c without an account and, for staff, its box size (`info` in `--json`).
122
+ - `turns ls <id> --canal anon|messenger|whatsapp|…`: every row says its channel (`canal`; older rows deduced from the session key).
123
+ - `usage --agent <id> [--by model,day,canal] [--cost]`: one agent's tokens and USD at the provider's list price (what it would cost on the API).
124
+ - `agents ls --json`: `model` and the workspace slug on every row.
125
+
126
+ ### Changes in 0.64.0
127
+
128
+ - `agents box <id> --start`: start (or wake) the agent's box now, without spending a turn. Within the plan's boxes (503 if the space is full); the next turn uses that box.
129
+
113
130
  ### Changes in 0.63.0
114
131
 
115
132
  - `settings ls | set <KEY> <value|+id|-id> | unset <KEY>` (staff): platform switches without a deploy — who answers /c without an account in a box (`ANON_NATIVE_AGENT_ID`), native subagents by agent and surface, the page builder for everyone. Logged.
package/dist/index.js CHANGED
@@ -8478,7 +8478,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
8478
8478
  const req = httpsRequest(`${base}${path}`, {
8479
8479
  method: "POST",
8480
8480
  timeout: timeoutMs,
8481
- headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.63.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
8481
+ headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.66.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
8482
8482
  }, (res) => {
8483
8483
  let buf = "";
8484
8484
  res.on("data", (c) => buf += c);
@@ -8520,7 +8520,7 @@ async function request(path, opts = {}, retried = false) {
8520
8520
  method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
8521
8521
  headers: {
8522
8522
  authorization: `Bearer ${token}`,
8523
- "user-agent": `ghosty-cli/${"0.63.0"}`,
8523
+ "user-agent": `ghosty-cli/${"0.66.0"}`,
8524
8524
  "accept-language": lang(),
8525
8525
  ...opts.body !== void 0 ? { "content-type": "application/json" } : {},
8526
8526
  ...opts.headers
@@ -9094,17 +9094,18 @@ async function agentsLs(workspace, f = {}) {
9094
9094
  const r = await api("/api/v2/me/agents?client=cli");
9095
9095
  const list = (workspace ? r.agentes.filter((a) => a.espacio?.nombre === workspace) : r.agentes).filter((a) => !f.engine || (a.motor ?? a.origen) === f.engine);
9096
9096
  if (f.ids) return void process.stdout.write(list.map((a) => a.id).join("\n") + (list.length ? "\n" : ""));
9097
- const spaceOf = (a) => a.espacio?.tipo === "workspace" ? a.espacio.nombre : a.espacio?.tipo ?? "";
9097
+ const spaceOf = (a) => a.espacio?.tipo === "workspace" ? a.espacio.nombre : a.workspaceSlug ?? a.espacio?.tipo ?? "";
9098
9098
  const rows = list.map((a) => ({
9099
9099
  id: a.id,
9100
9100
  name: a.nombre,
9101
9101
  engine: a.motor ?? a.origen,
9102
+ model: a.modelId ?? null,
9102
9103
  source: a.origen,
9103
9104
  workspace: spaceOf(a),
9104
9105
  lastActivity: a.ultimaActividad ?? null,
9105
9106
  ...a.compartidoPor ? { sharedBy: a.compartidoPor } : {}
9106
9107
  }));
9107
- out(rows, () => `${table(rows, ["id", "name", "engine", "workspace", "lastActivity"])}${workspace ? `
9108
+ out(rows, () => `${table(rows, ["id", "name", "engine", "model", "workspace", "lastActivity"])}${workspace ? `
9108
9109
  ${dim(t(`only ${workspace} (ghosty use) \xB7 all: --all`, `s\xF3lo ${workspace} (ghosty use) \xB7 todos: --all`))}` : ""}`);
9109
9110
  }
9110
9111
  function parseEnv(raw) {
@@ -9826,7 +9827,12 @@ async function writeEmbedComponent(e, baseUrl2, file, force) {
9826
9827
  return relative(process.cwd(), path) || path;
9827
9828
  }
9828
9829
  async function agentsBox(id, v) {
9829
- id = need(id, "agent id", "ghosty agents box <agent-id> [--check PATH] [--contains PATH=TEXT] [--recycle]");
9830
+ id = need(id, "agent id", "ghosty agents box <agent-id> [--check PATH] [--contains PATH=TEXT] [--recycle | --start]");
9831
+ if (v.start) {
9832
+ const r2 = await api(agentPath(id, "/box"), { method: "POST", body: { start: true } });
9833
+ out(r2, () => `${lavender("\u2713")} ${t("Box up", "Caja arriba")}: ${bold(r2?.sandboxId ?? "?")} ${dim(serverText(r2?.note ?? ""))}`);
9834
+ return;
9835
+ }
9830
9836
  if (v.recycle) {
9831
9837
  const r2 = await api(agentPath(id, "/box"), { method: "POST", body: { recycle: true, ...v.force ? { force: true } : {}, ...v.reenv ? { reenv: true } : {} } });
9832
9838
  out(r2, () => `${lavender("\u2713")} ${t("Recycled.", "Reciclada.")} ${dim(serverText(r2?.note ?? ""))}
@@ -10438,7 +10444,7 @@ async function call(path, v, init = {}) {
10438
10444
  "x-ghosty-ts": ts,
10439
10445
  "x-ghosty-sig": sig,
10440
10446
  "content-type": "application/json",
10441
- "user-agent": `ghosty-cli/${"0.63.0"}`
10447
+ "user-agent": `ghosty-cli/${"0.66.0"}`
10442
10448
  },
10443
10449
  body: method === "GET" ? void 0 : raw
10444
10450
  });
@@ -11150,6 +11156,7 @@ async function turnsCmd(sub, id, turnId, v) {
11150
11156
  if (status) q.set("state", status);
11151
11157
  if (v.since) q.set("since", v.since);
11152
11158
  if (v.session) q.set("session", v.session);
11159
+ if (v.canal) q.set("canal", v.canal);
11153
11160
  q.set("limit", v.limit ?? "20");
11154
11161
  const r = await api(agentPath2(id, `/turns?${q}`));
11155
11162
  const when = (s2) => s2.slice(0, 16).replace("T", " ");
@@ -11158,13 +11165,14 @@ async function turnsCmd(sub, id, turnId, v) {
11158
11165
  started: when(tu.startedAt),
11159
11166
  state: tu.state === "error" ? red(tu.state) : tu.state,
11160
11167
  secs: tu.ms == null ? "" : Math.round(tu.ms / 1e3),
11168
+ canal: tu.canal ?? "",
11161
11169
  from: tu.surface ?? "",
11162
11170
  session: tu.sessionId.slice(0, 24),
11163
11171
  resumed: resumedCell(tu.sdk),
11164
11172
  error: serverText(tu.error ?? "").replace(/\s+/g, " ").slice(0, 90)
11165
11173
  }));
11166
11174
  const tally = Object.entries(r.counts).map(([k, n]) => `${k} ${n}`).join(" \xB7 ");
11167
- out(r, () => rows.length ? `${table(rows, ["id", "started", "state", "secs", "from", "session", ...rows.some((r2) => r2.resumed) ? ["resumed"] : [], "error"])}
11175
+ out(r, () => rows.length ? `${table(rows, ["id", "started", "state", "secs", "canal", "from", "session", ...rows.some((r2) => r2.resumed) ? ["resumed"] : [], "error"])}
11168
11176
  ${dim(`${v.since ? t(`since ${v.since}: `, `desde ${v.since}: `) : ""}${tally} \xB7 ${t("where the time went", "en qu\xE9 se fue el tiempo")}: ghosty turns show ${id} <turn-id>`)}` : dim(t(`No ${status ?? ""} turns${v.since ? ` since ${v.since}` : ""}.`, `Sin turnos${status ? ` ${status}` : ""}${v.since ? ` desde ${v.since}` : ""}.`)));
11169
11177
  }
11170
11178
  async function turnsGrep(id, text, v) {
@@ -11237,6 +11245,15 @@ async function turnShow(id, turnId, full = false) {
11237
11245
  return [head, ...io, ...r.steps.map(line2), dim(`${t("slowest", "lo m\xE1s lento")}: ${top || "\u2014"}`)].join("\n");
11238
11246
  });
11239
11247
  }
11248
+ function doctorInfoLines(i) {
11249
+ const yes = t("yes", "s\xED");
11250
+ return [
11251
+ `${dim(t("model", "modelo"))} ${i.engine} \xB7 ${i.model ?? t("default", "por defecto")} \xB7 effort ${i.effort ?? t("model default", "el del modelo")}`,
11252
+ ...i.box ? [`${dim(t("box", "caja"))} ${i.box.memMb} MB \xB7 ${t(`${i.box.workersPerVm} conversations per box`, `${i.box.workersPerVm} conversaciones por caja`)}`] : [],
11253
+ `${dim(t("native subagents", "subagentes nativos"))} ${i.nativeSubagents ? yes : "no"}`,
11254
+ `${dim(t("answers /c without an account", "atiende /c sin cuenta"))} ${i.anonNative ? yes : "no"}`
11255
+ ];
11256
+ }
11240
11257
  async function agentsDoctor(id, v) {
11241
11258
  id = need2(id, t("agent id", "el id del agente"), "ghosty agents doctor <agent-id>");
11242
11259
  const r = await api(agentPath2(id, "/doctor"));
@@ -11244,7 +11261,7 @@ async function agentsDoctor(id, v) {
11244
11261
  if (globals.json) out(r);
11245
11262
  else {
11246
11263
  const mark = { ok: lavender("\u2713"), warn: "\x1B[33m!\x1B[0m", error: red("\u2717") };
11247
- const lines = [];
11264
+ const lines = r.info ? doctorInfoLines(r.info) : [];
11248
11265
  for (const c of r.checks) {
11249
11266
  if (c.level === "ok" && !v.verbose) continue;
11250
11267
  lines.push(`${process.stdout.isTTY ? mark[c.level] : { ok: "\u2713", warn: "!", error: "\u2717" }[c.level]} ${serverText(c.title)}`);
@@ -12122,6 +12139,8 @@ var HELPS_ES = {
12122
12139
  ["# pause it there; it keeps its @handle", "# lo pausa ah\xED; conserva su @handle"],
12123
12140
  ["# archive: stops answering everywhere, hidden, deleted after 7 days unless restored", "# archivar: deja de contestar en todos lados, se oculta y se borra a los 7 d\xEDas si no lo restauras"],
12124
12141
  ["# archived agents and when they get deleted", "# los archivados y cu\xE1ndo se borran"],
12142
+ ["# --json: model and workspace on every row", "# --json: modelo y espacio en cada fila"],
12143
+ ["# also: model, effort, native subagents, answers /c, box size (staff)", "# tambi\xE9n: modelo, effort, subagentes nativos, si atiende /c, tama\xF1o de caja (staff)"],
12125
12144
  ["# remove it from there; the agent stays", "# lo quita de ah\xED; el agente sigue"],
12126
12145
  ["# web widget: chat bubble on your site, only on those domains", "# widget web: burbuja de chat en tu sitio, s\xF3lo en esos dominios"],
12127
12146
  ["# state + the <script> to paste", "# su estado + el <script> para pegar"]
@@ -12190,6 +12209,7 @@ var HELPS_ES = {
12190
12209
  ["--check PATH", "box: este archivo debe existir en la m\xE1quina (repetible), p. ej. un archivo que trae la imagen nueva"],
12191
12210
  ["--contains PATH=TEXT", "box: ese archivo debe contener TEXT (un cambio que no agrega archivos)"],
12192
12211
  ["--recycle", "box: reemplaza sus m\xE1quinas (nunca a media respuesta); pool: la nueva nace en el siguiente turno; ACP (goose, lite) igual, con el historial del \xFAltimo respaldo"],
12212
+ ["--start", "box: levanta (o despierta) su caja ya, sin gastar un turno; dentro de las cajas del plan (503 si el espacio est\xE1 lleno)"],
12193
12213
  ["--reenv / --force", "box --recycle en ACP: --reenv s\xF3lo re-hornea el env en la misma caja; --force la recrea aunque est\xE9 ocupada (due\xF1o o staff)"],
12194
12214
  ["--unset-env K1,K2", "set: borra esas variables del env (--env K= tambi\xE9n borra K)"],
12195
12215
  ["--tool [ch:]tool=on|off", "set: prende/apaga una tool en un canal (wa:actualizar_identidad=off) o en todos (crm_buscar=off); separadas por comas"],
@@ -12272,7 +12292,8 @@ var HELPS_ES = {
12272
12292
  ["--quota-hits", "ls --workspace: mensajes (WhatsApp Business y Teams) que no abrieron turno porque se acab\xF3 el saldo"],
12273
12293
  ["--all", "stats (staff): cuenta tambi\xE9n staff, canal prueba y agentes borrados"],
12274
12294
  ["--session S", "ls: s\xF3lo los turnos de esa conversaci\xF3n. Los de Claude dicen \xABresumed\xBB: \u2713 = retom\xF3 la sesi\xF3n del SDK, \xAB1.er turno\xBB = primer turno de una sesi\xF3n nueva del SDK (no es p\xE9rdida de memoria), \u26A0 desde cero (orphan|stale|replaced) = perdi\xF3 la memoria"],
12275
- ["--role R", "grep: user (lo que escribi\xF3 el cliente) | agent (lo que contest\xF3 el agente)"]
12295
+ ["--role R", "grep: user (lo que escribi\xF3 el cliente) | agent (lo que contest\xF3 el agente)"],
12296
+ ["--canal C", "ls: s\xF3lo los turnos de ese canal: chat | teams | whatsapp | wa | messenger | programado | prueba | demo | embed | anon (/c sin cuenta). Cada fila (y --json) dice su canal"]
12276
12297
  ],
12277
12298
  notes: ["--skipped guarda 30 d\xEDas y s\xF3lo ve lo que Formmy reenvi\xF3: si Formmy no reenv\xEDa (ghosty channels whatsapp ls, \xABformmy forwards\xBB), a gs nunca le llega el mensaje.", "show imprime lo que entr\xF3 y lo que sali\xF3 en cualquier motor o canal (grupos de WhatsApp tambi\xE9n); la l\xEDnea de tiempo lee el transcript del worker, as\xED que s\xF3lo motores del pool (no ACP/goose)."]
12278
12299
  },
@@ -12490,14 +12511,18 @@ var HELPS_ES = {
12490
12511
  ]
12491
12512
  },
12492
12513
  usage: {
12493
- summary: "Tu plan y cu\xE1nto llevas usado esta semana y este mes. Con --workspace: turnos y tokens facturables de un espacio por agente y/o por d\xEDa. Con --boxes: sus cajas contra el tope.",
12514
+ summary: "Tu plan y cu\xE1nto llevas usado esta semana y este mes. Con --workspace: turnos y tokens facturables de un espacio por agente y/o por d\xEDa. Con --agent: tokens y USD de un agente por modelo, d\xEDa o canal. Con --boxes: sus cajas contra el tope.",
12515
+ replace: [["# one agent: tokens and USD per model", "# un agente: tokens y USD por modelo"]],
12494
12516
  flags: [
12495
12517
  ["--images", "(staff de Ghosty) cargos de im\xE1genes contra las que entregaron los agentes, por plan; costo guardado contra la tabla. Mucha diferencia = el medidor no est\xE1 reportando"],
12496
12518
  ["--plan P", "--images: s\xF3lo free | pro | power | max | workspace"],
12497
12519
  ["--boxes", "las cajas del espacio contra su tope (spares, dormidas) y, por agente: conversaciones por caja, cajas, despiertas, spares, turnos corriendo ahora"],
12498
12520
  ["--workspace SLUG", "qu\xE9 espacio (due\xF1o o staff); con --boxes el default es el de ghosty use"],
12499
12521
  ["--by agent|day|agent,day", "--workspace: filas por agente (default), por d\xEDa (CDMX) o las dos \xB7 con --boxes: template = toda la flota por template (staff)"],
12500
- ["--days N", "--workspace: cu\xE1ntos d\xEDas hacia atr\xE1s (default 14, m\xE1x. 92)"]
12522
+ ["--days N", "--workspace / --agent: cu\xE1ntos d\xEDas hacia atr\xE1s (default 14, m\xE1x. 92)"],
12523
+ ["--agent ID", "el gasto de un agente por modelo (default), d\xEDa (CDMX) y/o canal (anon = /c sin cuenta, messenger, whatsapp\u2026; other = chat/Teams)"],
12524
+ ["--cost", "--agent: USD a precio de lista del proveedor por fila (con escritura de cach\xE9): lo que costar\xEDa el agente por API"],
12525
+ ["--by visitor", "--agent: /c sin cuenta, un rengl\xF3n por visitante: USD, mensajes, si se llev\xF3 p\xE1gina o PDF y si cre\xF3 cuenta; abajo, USD por visitante y por cuenta nueva"]
12501
12526
  ],
12502
12527
  notes: ["failed = turnos que terminaron en error o se detuvieron. \xABno balance\xBB = mensajes que no abrieron turno porque se acab\xF3 la bolsa (ghosty turns ls --workspace X --quota-hits los lista)."]
12503
12528
  },
@@ -12656,16 +12681,16 @@ var HELPS = {
12656
12681
  agents: {
12657
12682
  summary: "Create, inspect, change, check and delete agents.",
12658
12683
  usage: [
12659
- "ghosty agents ls [--engine E] [--ids] [--sponsor EMAIL | --owner EMAIL]",
12684
+ "ghosty agents ls [--engine E] [--ids] [--sponsor EMAIL | --owner EMAIL] # --json: model and workspace on every row",
12660
12685
  "ghosty agents ls --handle build [--workspace WS] # who is @build in Teams (that workspace, or all of yours)",
12661
12686
  "ghosty agents create --name NAME [--engine E] [--model M] [--prompt TEXT | --prompt-file FILE] [--env K=V,\u2026] [--workspace SLUG] [--channels teams=off,\u2026] [--like AGENT [--copy-dbs] [--board same|main|new|NAME] [--no-notify] [--dry-run]]",
12662
- "ghosty agents get <agent-id> [--fields name,model,prompt] [--prompt-out FILE]",
12687
+ "ghosty agents get|show <agent-id> [--fields name,model,prompt] [--prompt-out FILE]",
12663
12688
  "ghosty agents export <agent-id> [--out DIR] # the agent as a file; see ghosty apply --help",
12664
12689
  "ghosty agents set <agent-id> [--name] [--engine] [--model] [--prompt | --prompt-file] [--env K=V,\u2026] [--unset-env K1,K2] [--connect ID,\u2026] [--disconnect ID,\u2026] [--voice E:ID] [--voice-replies auto|off] [--auto-stage on|off] [--toolsets crm,sales | +crm,-sales] [--tool [channel:]tool=on|off,\u2026] [--bag NAME|none] [--box MB[:N]] [--avatar URL|FILE]",
12665
12690
  "ghosty agents set <agent-id> --engine E [--model M] --dry-run # what changing the engine does (sessions, machines, memory), without changing it",
12666
12691
  "ghosty agents set <agent-id> --prompt-base <base-agent-id> --prompt-overlay overlay.json [--dry-run [--out FILE]] | --prompt-base none",
12667
12692
  "ghosty agents set <agent-id> --prompt-patch overlay.json [--prompt-append FILE] [--dry-run] # change one piece of the prompt, on the server's current one",
12668
- "ghosty agents doctor <agent-id> [--verbose]",
12693
+ "ghosty agents doctor <agent-id> [--verbose] # also: model, effort, native subagents, answers /c, box size (staff)",
12669
12694
  "ghosty agents doctor --user <email> [agent-id] [--turns 8] # staff: their agents, latest turns, plan and boxes",
12670
12695
  "ghosty agents docs ls|grant|revoke <agent-id> [doc\u2026] [--write] [--no-deliver] [--like AGENT]",
12671
12696
  "ghosty agents docs add <agent-id> --url URL | --file PATH [--name N] [--description TEXT] [--grant read|write|no] [--no-deliver]",
@@ -12682,6 +12707,7 @@ var HELPS = {
12682
12707
  "ghosty agents teams rm <agent-id> <workspace> [--yes] # remove it from there; the agent stays",
12683
12708
  "ghosty agents restart <agent-id>",
12684
12709
  "ghosty agents box <agent-id> [--check PATH]\u2026 [--contains PATH=TEXT]\u2026 [--recycle]",
12710
+ "ghosty agents box <agent-id> --start # start (or wake) its box now, without spending a turn",
12685
12711
  "ghosty agents demo enable|disable <agent-id>",
12686
12712
  'ghosty agents demo <agent-id> [--slug NAME] [--expires "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate]',
12687
12713
  "ghosty agents embed enable|disable <agent-id> [--domains a.com,*.b.com] # web widget: chat bubble on your site, only on those domains",
@@ -12759,6 +12785,7 @@ var HELPS = {
12759
12785
  ["--check PATH", "box: this file must exist in the machine (repeatable), e.g. a file the new image brings"],
12760
12786
  ["--contains PATH=TEXT", "box: that file must contain TEXT (a change that adds no files)"],
12761
12787
  ["--recycle", "box: replace its machines (not mid-turn); pool: the new one starts on the next turn; ACP (goose, lite) too, history from its last backup"],
12788
+ ["--start", "box: start (or wake) its box now, without a turn; within the plan's boxes (503 if the space is full)"],
12762
12789
  ["--reenv / --force", "box --recycle on ACP: --reenv only re-bakes the env in the same box; --force recreates it even if busy (owner or staff)"],
12763
12790
  ["--unset-env K1,K2", "set: delete these env variables (--env K= also deletes K)"],
12764
12791
  ["--tool [ch:]tool=on|off", "set: one tool on/off in one channel (wa:actualizar_identidad=off) or everywhere (crm_buscar=off); comma-separated"],
@@ -12797,6 +12824,7 @@ var HELPS = {
12797
12824
  "ghosty agents embed <id> --theme-source site --site-url https://palmeralegal.mx",
12798
12825
  "ghosty agents embed <id> theme > tema.json \xB7 ghosty agents embed <id> --style-file tema.json",
12799
12826
  `ghosty agents embed <id> --copy '{"waking":"Un momento, por favor","thinking":["Revisando su consulta\u2026","Consultando el expediente\u2026"],"showDuration":false}'`,
12827
+ "ghosty agents box <id> --start",
12800
12828
  "ghosty agents box <id> --contains /opt/claude-worker/skills/pdf-doc/render-doc.mjs=pdf-templates",
12801
12829
  "ghosty agents set <id> --tool wa:actualizar_identidad=off,teams:actualizar_identidad=on",
12802
12830
  'ghosty agents set minighosty --bag "MiniGhosty" --avatar https://www.ghosty.studio/avatars/minighosty.png',
@@ -12895,7 +12923,7 @@ var HELPS = {
12895
12923
  },
12896
12924
  turns: {
12897
12925
  summary: "An agent's recent turns: what answered, what failed and why, and where one turn's time went.",
12898
- usage: ["ghosty turns ls <agent-id> [--errors | --status STATE | --skipped] [--since 1h] [--limit N]", "ghosty turns ls --workspace <slug> --quota-hits [--days 14]", "ghosty turns show <agent-id> [turn-id | last] [--full]", 'ghosty turns grep <agent-id> "text" [--since 7d] [--role user|agent] [--session S] # what the customer or the agent said, and its turn', "ghosty turns cancel <agent-id> <conversation-id> # stop the turn AND its background jobs", "ghosty turns stats [--since 14d] [--all] # staff: real failure rate by engine, channel (Teams/A2A too) and error"],
12926
+ usage: ["ghosty turns ls <agent-id> [--errors | --status STATE | --skipped] [--canal C] [--since 1h] [--limit N]", "ghosty turns ls --workspace <slug> --quota-hits [--days 14]", "ghosty turns show <agent-id> [turn-id | last] [--full]", 'ghosty turns grep <agent-id> "text" [--since 7d] [--role user|agent] [--session S] # what the customer or the agent said, and its turn', "ghosty turns cancel <agent-id> <conversation-id> # stop the turn AND its background jobs", "ghosty turns stats [--since 14d] [--all] # staff: real failure rate by engine, channel (Teams/A2A too) and error"],
12899
12927
  flags: [
12900
12928
  ["--errors", "only failed turns (same as --status error)"],
12901
12929
  ["--skipped", "ls: WhatsApp Business customer messages that did NOT open a turn, and why (operator active, records only, paused, reaction, channel off, no balance)"],
@@ -12906,9 +12934,10 @@ var HELPS = {
12906
12934
  ["--quota-hits", "ls --workspace: messages (WhatsApp Business and Teams) that got no turn because the balance ran out"],
12907
12935
  ["--all", "stats (staff): also count staff users, the test channel and deleted agents"],
12908
12936
  ["--session S", "ls: only this conversation's turns. Claude turns show \xABresumed\xBB: \u2713 = it kept the SDK session, \xAB1st turn\xBB = first turn of a new SDK session (not a memory loss), \u26A0 from scratch (orphan|stale|replaced) = it lost its memory"],
12909
- ["--role R", "grep: user (what the customer wrote) | agent (what the agent answered)"]
12937
+ ["--role R", "grep: user (what the customer wrote) | agent (what the agent answered)"],
12938
+ ["--canal C", "ls: only turns from that channel: chat | teams | whatsapp | wa | messenger | programado | prueba | demo | embed | anon (/c without an account). Each row (and --json) says its canal"]
12910
12939
  ],
12911
- examples: ["ghosty turns ls <id> --errors --since 1h", "ghosty turns ls --workspace descti --quota-hits --days 30", "ghosty turns ls <id> --skipped --since 1d", "ghosty turns ls <id> --json --limit 100", "ghosty turns show <id> # last turn: each tool, its seconds, output tokens", 'ghosty turns grep <id> "IVA" --since 7d --role agent'],
12940
+ examples: ["ghosty turns ls <id> --errors --since 1h", "ghosty turns ls <id> --canal anon --since 1d", "ghosty turns ls --workspace descti --quota-hits --days 30", "ghosty turns ls <id> --skipped --since 1d", "ghosty turns ls <id> --json --limit 100", "ghosty turns show <id> # last turn: each tool, its seconds, output tokens", 'ghosty turns grep <id> "IVA" --since 7d --role agent'],
12912
12941
  notes: ["--skipped keeps 30 days and only sees what Formmy forwarded: if Formmy doesn't forward (ghosty channels whatsapp ls, \xABformmy forwards\xBB), gs never gets the message.", "show prints what came in and what went out on any engine or channel (WhatsApp groups too); the timeline reads the worker's transcript, so pool engines only (not ACP/goose)."],
12913
12942
  learn: `${REF}#turnos`
12914
12943
  },
@@ -13232,17 +13261,20 @@ HELPS.board = HELPS.cards;
13232
13261
  HELPS.conversations = HELPS.chat;
13233
13262
  HELPS.usage = {
13234
13263
  ...HELPS.me,
13235
- summary: "Your plan and how much you've used this week and month. With --workspace: a workspace's turns and billable tokens per agent and/or day. With --boxes: its boxes against its limit.",
13236
- usage: ["ghosty usage", "ghosty me usage", "ghosty usage --workspace SLUG [--by agent|day|agent,day] [--days 14]", "ghosty usage --boxes [--workspace SLUG]", "ghosty usage --images [--plan free] [--since 7d] [--by user] # staff"],
13264
+ summary: "Your plan and how much you've used this week and month. With --workspace: a workspace's turns and billable tokens per agent and/or day. With --agent: one agent's tokens and USD per model, day or channel. With --boxes: its boxes against its limit.",
13265
+ usage: ["ghosty usage", "ghosty me usage", "ghosty usage --workspace SLUG [--by agent|day|agent,day] [--days 14]", "ghosty usage --agent ID [--by model,day,canal] [--cost] [--days 14] # one agent: tokens and USD per model", "ghosty usage --boxes [--workspace SLUG]", "ghosty usage --images [--plan free] [--since 7d] [--by user] # staff"],
13237
13266
  flags: [
13238
13267
  ["--images", "(Ghosty staff) image charges vs images agents delivered, per plan; stored cost vs the price table. A big gap = the meter isn't reporting"],
13239
13268
  ["--plan P", "--images: only free | pro | power | max | workspace"],
13240
13269
  ["--boxes", "the workspace's boxes against its limit (spares, asleep) and, per agent: conversations per box, boxes, awake, spares, turns running now"],
13241
13270
  ["--workspace SLUG", "which workspace (owner or staff); with --boxes the default is the one from ghosty use"],
13242
13271
  ["--by agent|day|agent,day", "--workspace: rows per agent (default), per day (CDMX) or both \xB7 with --boxes: template = the whole fleet by template (staff)"],
13243
- ["--days N", "--workspace: how far back (default 14, max 92)"]
13272
+ ["--days N", "--workspace / --agent: how far back (default 14, max 92)"],
13273
+ ["--agent ID", "one agent's spend per model (default), day (CDMX) and/or canal (anon = /c without an account, messenger, whatsapp\u2026; other = chat/Teams)"],
13274
+ ["--cost", "--agent: USD at the provider's list price per row (cache writes included): what the agent would cost on the API"],
13275
+ ["--by visitor", "--agent: /c without an account, one row per visitor: USD, messages, whether they got a page or a PDF and whether they created an account; below, USD per visitor and per new account"]
13244
13276
  ],
13245
- examples: ["ghosty usage", "ghosty usage --json", "ghosty usage --workspace descti --by agent,day --days 14", "ghosty usage --boxes --workspace siiqtec", "ghosty usage --images --plan free --by user"],
13277
+ examples: ["ghosty usage", "ghosty usage --json", "ghosty usage --workspace descti --by agent,day --days 14", "ghosty usage --agent <id> --by model,day --cost", "ghosty usage --boxes --workspace siiqtec", "ghosty usage --images --plan free --by user"],
13246
13278
  notes: ["failed = turns that ended in error or were stopped. \xABno balance\xBB = messages that got no turn because the bag ran out (ghosty turns ls --workspace X --quota-hits lists them)."],
13247
13279
  learn: `${REF}#uso`
13248
13280
  };
@@ -14100,6 +14132,61 @@ ${dim(t(`${total2} message(s) unanswered for lack of balance in ${r.days} day(s)
14100
14132
  ${table(rows, cols)}
14101
14133
  ${dim(t(`${fmtTokens(total)} billable tokens \xB7 failed = error or stopped \xB7 no balance: ghosty turns ls --workspace ${r.workspace} --quota-hits`, `${fmtTokens(total)} tokens facturables \xB7 failed = error o detenido \xB7 sin saldo: ghosty turns ls --workspace ${r.workspace} --quota-hits`))}`);
14102
14134
  }
14135
+ var USAGE_DIMS = ["model", "day", "canal"];
14136
+ function groupAgentUsage(rows, by) {
14137
+ const groups = /* @__PURE__ */ new Map();
14138
+ for (const r of rows) {
14139
+ const k = by.map((d) => r[d]).join("|");
14140
+ const g = groups.get(k) ?? { day: by.includes("day") ? r.day : "", model: by.includes("model") ? r.model : "", canal: by.includes("canal") ? r.canal : "", turns: 0, inputTokens: 0, outputTokens: 0, cacheRead: 0, cacheCreation: 0, billable: 0, usd: 0 };
14141
+ g.turns += r.turns;
14142
+ g.inputTokens += r.inputTokens;
14143
+ g.outputTokens += r.outputTokens;
14144
+ g.cacheRead += r.cacheRead;
14145
+ g.cacheCreation += r.cacheCreation;
14146
+ g.billable += r.billable;
14147
+ g.usd += r.usd;
14148
+ groups.set(k, g);
14149
+ }
14150
+ return [...groups.values()].sort((a, b) => a.day.localeCompare(b.day) || b.usd - a.usd);
14151
+ }
14152
+ async function agentUsage(id, v) {
14153
+ if (v.by?.trim() === "visitor") return anonVisitorUsage(id, v);
14154
+ const by = (v.by ?? "model").split(",").map((x) => x.trim()).filter(Boolean);
14155
+ if (!by.length || by.some((b) => !USAGE_DIMS.includes(b))) throw usage(t("With --agent, --by takes model, day and/or canal (or visitor alone).", "Con --agent, --by acepta model, day y/o canal (o visitor solo)."), "ghosty usage --agent <id> --by model,day --cost");
14156
+ const r = await api(`/api/v2/agents/${enc10(id)}/usage?days=${enc10(v.days ?? "14")}`);
14157
+ const groups = groupAgentUsage(r.rows, by);
14158
+ const rows = groups.map((g) => ({ ...Object.fromEntries(by.map((d) => [d, g[d]])), turns: g.turns, tokens: fmtTokens(g.billable), "cache read": fmtTokens(g.cacheRead), out: fmtTokens(g.outputTokens), ...v.cost ? { usd: `$${g.usd.toFixed(2)}` } : {} }));
14159
+ const cols = [...by, "turns", "tokens", "cache read", "out", ...v.cost ? ["usd"] : []];
14160
+ const turns = r.rows.reduce((n, x) => n + x.turns, 0);
14161
+ const foot = v.cost ? t(`$${r.totalUsd.toFixed(2)} USD at provider list price (cache writes included) \xB7 ${turns} turn(s)`, `$${r.totalUsd.toFixed(2)} USD a precio de lista del proveedor (con escritura de cach\xE9) \xB7 ${turns} turno(s)`) : t(`${turns} turn(s) \xB7 USD per row: --cost`, `${turns} turno(s) \xB7 USD por fila: --cost`);
14162
+ out({ ...r, groups }, () => rows.length ? `${bold(r.agent)} ${dim(t(`last ${r.days} day(s), CDMX days`, `\xFAltimos ${r.days} d\xEDa(s), d\xEDas en hora CDMX`))}
14163
+ ${table(rows, cols)}
14164
+ ${dim(foot)}` : dim(t(`No usage in ${r.days} day(s).`, `Sin uso en ${r.days} d\xEDa(s).`)));
14165
+ }
14166
+ async function anonVisitorUsage(id, v) {
14167
+ const r = await api(`/api/v2/agents/${enc10(id)}/usage?days=${enc10(v.days ?? "14")}&visitors=1`);
14168
+ const vs = r.visitors ?? { list: [], total: { visitors: 0, accounts: 0, usd: 0 } };
14169
+ const yes = t("yes", "s\xED");
14170
+ const rows = vs.list.map((x) => ({
14171
+ visitor: x.visitor.slice(0, 8),
14172
+ first: x.firstAt ? x.firstAt.slice(0, 16).replace("T", " ") : "",
14173
+ msgs: x.messages,
14174
+ usd: `$${x.usd.toFixed(3)}`,
14175
+ page: x.page ? yes : "",
14176
+ pdf: x.pdfs || "",
14177
+ account: x.accountAt ? x.accountAt.slice(0, 10) : ""
14178
+ }));
14179
+ const { visitors, accounts, usd } = vs.total;
14180
+ const perVisitor = visitors ? usd / visitors : 0;
14181
+ const perAccount = accounts ? usd / accounts : null;
14182
+ const foot = t(
14183
+ `${visitors} visitor(s) \xB7 ${accounts} created an account (${visitors ? Math.round(accounts / visitors * 100) : 0}%) \xB7 $${usd.toFixed(2)} USD \xB7 $${perVisitor.toFixed(3)} per visitor${perAccount !== null ? ` \xB7 $${perAccount.toFixed(2)} per new account` : ""} (provider list price; times in UTC)`,
14184
+ `${visitors} visitante(s) \xB7 ${accounts} crearon cuenta (${visitors ? Math.round(accounts / visitors * 100) : 0}%) \xB7 $${usd.toFixed(2)} USD \xB7 $${perVisitor.toFixed(3)} por visitante${perAccount !== null ? ` \xB7 $${perAccount.toFixed(2)} por cuenta nueva` : ""} (precio de lista del proveedor; horas en UTC)`
14185
+ );
14186
+ out(r, () => rows.length ? `${bold(r.agent)} ${dim(t(`/c without an account, last ${r.days} day(s)`, `/c sin cuenta, \xFAltimos ${r.days} d\xEDa(s)`))}
14187
+ ${table(rows, ["visitor", "first", "msgs", "usd", "page", "pdf", "account"])}
14188
+ ${dim(foot)}` : dim(t(`No visitors in ${r.days} day(s).`, `Sin visitantes en ${r.days} d\xEDa(s).`)));
14189
+ }
14103
14190
 
14104
14191
  // src/commands/demos.ts
14105
14192
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -14813,6 +14900,7 @@ ${bold("Session")}
14813
14900
  completion zsh|bash|fish Tab completion for commands, flags, agents and workspaces
14814
14901
  usage Your plan and how much you've used this week and month [--boxes: boxes vs the workspace limit \xB7 --boxes --by template: the whole fleet (staff) \xB7 --images [--plan free] [--by user]: image charges vs deliveries (staff)]
14815
14902
  usage --workspace SLUG A workspace's turns and tokens per agent/day [--by agent,day] [--days 14]
14903
+ usage --agent ID One agent's tokens per model/day/channel [--by model,day,canal] [--cost: USD at API list price] [--days 14]
14816
14904
  plan apply [workspace] Apply a scheduled plan now, showing what changes [--dry-run]
14817
14905
  engines ls Engines and models valid for --engine/--model [--models]
14818
14906
 
@@ -14842,7 +14930,7 @@ ${bold("Agents")}
14842
14930
  [--like AGENT [--copy-dbs] [--board same|main|new|NAME] [--no-notify] [--dry-run]] with another agent's setup (not its prompt, env or channels)
14843
14931
  agents export <id> The agent as a file (YAML, no secrets) [--out DIR: agent.yaml + its skills]
14844
14932
  apply <file|dir> Make an agent match a file: shows the plan (+ ~ -), asks, applies [--agent X] [--create] [--prune] [--dry-run]
14845
- agents get <id> Show an agent's config [--fields name,model,prompt] [--prompt-out FILE]
14933
+ agents get|show <id> Show an agent's config [--fields name,model,prompt] [--prompt-out FILE]
14846
14934
  agents set <id> Change identity or engine [--name] [--engine] [--model] [--prompt | --prompt-file FILE] [--env K=V,\u2026]
14847
14935
  [--connect google-drive,\u2026] [--disconnect \u2026] give/remove access to your connectors
14848
14936
  [--channels wa=on,teams=off] turn channels on/off (wa = personal WhatsApp)
@@ -14854,7 +14942,7 @@ ${bold("Agents")}
14854
14942
  [--prompt-patch overlay.json | --prompt-append FILE [--dry-run]] change one piece of the prompt, on the server's current one
14855
14943
  [--tool wa:tool=off,\u2026] [--bag NAME|none] [--box MB[:N]] [--avatar URL|FILE] a tool per channel \xB7 its token bag and box size (staff) \xB7 its face in Teams
14856
14944
  [--prompt-mode append|replace] replace = its prompt WITHOUT Ghosty's house persona
14857
- agents doctor <id> Check the config: overlapping skills, tools the prompt names, broken grants, failing turns
14945
+ agents doctor <id> Check the config: overlapping skills, tools the prompt names, broken grants, failing turns; prints model, effort, native subagents, /c and box (staff)
14858
14946
  agents docs ls|grant|revoke <id> [doc] Documents it reads and may send [--write] [--no-deliver]
14859
14947
  agents docs grant <id> A B\u2026 Grant several documents at once [--like AGENT] copies another agent's
14860
14948
  agents docs add <id> Upload a document and grant it --url URL | --file PATH [--description] [--grant read|write|no]
@@ -14865,7 +14953,7 @@ ${bold("Agents")}
14865
14953
  agents teams ls|on|off|rm <id> [ws] Which Teams workspaces it answers in, and its @handle there [--handle x] [--factory plan,build,check: its Software Factory roles]
14866
14954
  agents rm <id> Delete an agent (owner only; asks you to type its name, or --yes) [--from-workspace: turn it off in Teams first]
14867
14955
  agents restart <id> Restart an ACP agent (needsRestart) so it loads new skills
14868
- agents box <id> The machine serving it: is it on the new image? [--check PATH]\u2026 [--contains PATH=TEXT]\u2026 [--recycle [--reenv] [--force]]
14956
+ agents box <id> The machine serving it: is it on the new image? [--check PATH]\u2026 [--contains PATH=TEXT]\u2026 [--recycle [--reenv] [--force]] [--start]
14869
14957
  agents demo enable|disable <id> Turn its public demo link on or off
14870
14958
  agents demo <id> Public demo link /p/<slug>: anyone tries it without an account, "Keep it" clones it to theirs
14871
14959
  agents embed enable|disable <id> Web widget: a chat bubble on YOUR site (one <script>), only on the domains you list [--domains a.com,*.b.com] [--per-visitor N] [--per-ip N] [--welcome T] [--color #hex] [--rotate]
@@ -14935,7 +15023,7 @@ ${bold("Talk to an agent")}
14935
15023
  conversations ls <id> List conversations
14936
15024
  conversations show <id> <conversation> What was said [--limit 20] (0 = all)
14937
15025
  conversations archive|rm <id> --kind test|channel|personal Clean its history (rm: never customers) [--before 7d] [--dry-run]
14938
- turns ls <id> Recent turns and why they failed [--errors] [--skipped] [--since 1h] [--limit N]
15026
+ turns ls <id> Recent turns, their channel and why they failed [--errors] [--skipped] [--canal anon|messenger|\u2026] [--since 1h] [--limit N]
14939
15027
  turns ls --workspace SLUG --quota-hits Messages that got no turn because the balance ran out [--days 14]
14940
15028
  turns show <id> [turn] What came in, what it answered, and where the time went (default: last) [--full]
14941
15029
  turns grep <id> "text" Find what the customer or the agent said, and the turn [--since 7d] [--role user|agent] [--session S]
@@ -14987,6 +15075,7 @@ ${bold("Sesi\xF3n")}
14987
15075
  completion zsh|bash|fish Autocompletado con TAB: comandos, opciones, agentes y espacios
14988
15076
  usage Tu plan y cu\xE1nto llevas usado esta semana y este mes [--boxes: cajas contra el tope del espacio \xB7 --boxes --by template: toda la flota (staff) \xB7 --images [--plan free] [--by user]: cargos de im\xE1genes contra entregas (staff)]
14989
15077
  usage --workspace SLUG Turnos y tokens de un espacio por agente/d\xEDa [--by agent,day] [--days 14]
15078
+ usage --agent ID Tokens de un agente por modelo/d\xEDa/canal [--by model,day,canal] [--cost: USD a precio de lista del API] [--days 14]
14990
15079
  plan apply [espacio] Aplica ya un plan programado, ense\xF1ando qu\xE9 cambia [--dry-run]
14991
15080
  engines ls Motores y modelos v\xE1lidos para --engine/--model [--models]
14992
15081
 
@@ -15016,7 +15105,7 @@ ${bold("Agentes")}
15016
15105
  [--like AGENTE [--copy-dbs] [--board same|main|new|NOMBRE] [--no-notify] [--dry-run]] con la configuraci\xF3n de otro agente (no su prompt, env ni canales)
15017
15106
  agents export <id> El agente como archivo (YAML, sin secretos) [--out DIR: agent.yaml + sus skills]
15018
15107
  apply <archivo|dir> Deja un agente igual que un archivo: ense\xF1a el plan (+ ~ -), pregunta y aplica [--agent X] [--create] [--prune] [--dry-run]
15019
- agents get <id> Muestra la configuraci\xF3n de un agente [--fields name,model,prompt] [--prompt-out ARCHIVO]
15108
+ agents get|show <id> Muestra la configuraci\xF3n de un agente [--fields name,model,prompt] [--prompt-out ARCHIVO]
15020
15109
  agents set <id> Cambia identidad o motor [--name] [--engine] [--model] [--prompt | --prompt-file ARCHIVO] [--env K=V,\u2026]
15021
15110
  [--connect google-drive,\u2026] [--disconnect \u2026] dale o qu\xEDtale acceso a tus conectores
15022
15111
  [--channels wa=on,teams=off] prende/apaga canales (wa = WhatsApp personal)
@@ -15028,7 +15117,7 @@ ${bold("Agentes")}
15028
15117
  [--prompt-patch overlay.json | --prompt-append ARCHIVO [--dry-run]] cambia un pedazo del prompt, sobre el actual del servidor
15029
15118
  [--tool wa:tool=off,\u2026] [--bag NOMBRE|none] [--box MB[:N]] [--avatar URL|ARCHIVO] una tool por canal \xB7 su bolsa de tokens y tama\xF1o de caja (staff) \xB7 su cara en Teams
15030
15119
  [--prompt-mode append|replace] replace = su prompt SIN la persona de casa de Ghosty
15031
- agents doctor <id> Revisa la configuraci\xF3n: skills encimadas, tools que nombra el prompt, permisos rotos, turnos que fallan
15120
+ agents doctor <id> Revisa la configuraci\xF3n: skills encimadas, tools que nombra el prompt, permisos rotos, turnos que fallan; dice modelo, effort, subagentes nativos, /c y caja (staff)
15032
15121
  agents docs ls|grant|revoke <id> [doc] Documentos que lee y puede enviar [--write] [--no-deliver]
15033
15122
  agents docs grant <id> A B\u2026 Da varios documentos a la vez [--like AGENTE] copia los de otro agente
15034
15123
  agents docs add <id> Sube un documento y d\xE1selo --url URL | --file RUTA [--description] [--grant read|write|no]
@@ -15039,7 +15128,7 @@ ${bold("Agentes")}
15039
15128
  agents teams ls|on|off|rm <id> [equipo] En qu\xE9 equipos de Teams contesta y con qu\xE9 @handle [--handle x] [--factory plan,build,check: sus roles de la Software Factory]
15040
15129
  agents rm <id> Borra un agente (s\xF3lo el due\xF1o; te pide escribir su nombre, o --yes) [--from-workspace: antes lo desactiva en Teams]
15041
15130
  agents restart <id> Reinicia un agente ACP (needsRestart) para que cargue skills nuevas
15042
- agents box <id> La m\xE1quina que lo atiende: \xBFya trae la imagen nueva? [--check RUTA]\u2026 [--contains RUTA=TEXTO]\u2026 [--recycle [--reenv] [--force]]
15131
+ agents box <id> La m\xE1quina que lo atiende: \xBFya trae la imagen nueva? [--check RUTA]\u2026 [--contains RUTA=TEXTO]\u2026 [--recycle [--reenv] [--force]] [--start]
15043
15132
  agents demo enable|disable <id> Prende o apaga su liga p\xFAblica de demo
15044
15133
  agents demo <id> Liga p\xFAblica de demo /p/<slug>: cualquiera lo prueba sin cuenta y \xABQued\xE1rmelo\xBB lo clona a la suya
15045
15134
  agents embed enable|disable <id> Widget web: burbuja de chat en TU sitio (un <script>), s\xF3lo en los dominios que pongas [--domains a.com,*.b.com] [--per-visitor N] [--per-ip N] [--welcome T] [--color #hex] [--rotate]
@@ -15109,7 +15198,7 @@ ${bold("Hablar con un agente")}
15109
15198
  conversations ls <id> Lista conversaciones
15110
15199
  conversations show <id> <conversaci\xF3n> Qu\xE9 se dijo [--limit 20] (0 = todo)
15111
15200
  conversations archive|rm <id> --kind test|channel|personal Limpia su historial (rm: nunca clientes) [--before 7d] [--dry-run]
15112
- turns ls <id> Turnos recientes y por qu\xE9 fallaron [--errors] [--skipped] [--since 1h] [--limit N]
15201
+ turns ls <id> Turnos recientes, su canal y por qu\xE9 fallaron [--errors] [--skipped] [--canal anon|messenger|\u2026] [--since 1h] [--limit N]
15113
15202
  turns ls --workspace SLUG --quota-hits Mensajes que no abrieron turno porque se acab\xF3 el saldo [--days 14]
15114
15203
  turns show <id> [turno] Qu\xE9 lleg\xF3, qu\xE9 contest\xF3 y en qu\xE9 se fue el tiempo (default: el \xFAltimo) [--full]
15115
15204
  turns grep <id> "texto" Busca lo que dijo el cliente o el agente, y su turno [--since 7d] [--role user|agent] [--session S]
@@ -15151,7 +15240,7 @@ ${bold("C\xF3digos de salida")} 0 bien \xB7 1 error de la API \xB7 2 uso incorr
15151
15240
  ${dim("Nota: `ghosty` puede chocar con otro binario en tu PATH (p. ej. la TUI de Ghosty). Rev\xEDsalo con `which -a ghosty`; corre `npx @ghostystudio/cli` para ir a la segura.")}
15152
15241
  ${dim("Documentaci\xF3n: https://www.ghosty.studio/docs/cli")}`;
15153
15242
  var COMMANDS = ["login", "logout", "whoami", "usage", "use", "apply", "plan", "engines", "bags", "spaces", "workspaces", "staff", "settings", "audit", "factory", "demos", "sites", "push", "novedades", "completion", "cards", "agents", "files", "skills", "mcp", "dbs", "turns", "try", "chat", "conversations", "schedule", "partner", "me", "channels", "board", "boards", "credentials", "connectors", "browser", "support", "docs", "help"];
15154
- var AGENTS_SUBS = ["ls", "create", "get", "set", "export", "doctor", "docs", "share", "unshare", "shares", "teams", "rm", "restart", "demo", "embed", "box"];
15243
+ var AGENTS_SUBS = ["ls", "create", "get", "show", "set", "export", "doctor", "docs", "share", "unshare", "shares", "teams", "rm", "restart", "demo", "embed", "box"];
15155
15244
  function unknown(what, input, known, helpCmd) {
15156
15245
  const s2 = suggest(input, known);
15157
15246
  return usage(t(`Unknown command: ${what}.`, `Comando desconocido: ${what}.`), s2 ? t(`Did you mean "${s2}"? Run: ${helpCmd}`, `\xBFQuisiste decir "${s2}"? Corre: ${helpCmd}`) : t(`Run: ${helpCmd}`, `Corre: ${helpCmd}`));
@@ -15343,6 +15432,7 @@ async function main() {
15343
15432
  column: { type: "string" },
15344
15433
  before: { type: "string" },
15345
15434
  recycle: { type: "boolean" },
15435
+ start: { type: "boolean" },
15346
15436
  role: { type: "string" },
15347
15437
  handle: { type: "string" },
15348
15438
  factory: { type: "string" },
@@ -15374,6 +15464,8 @@ async function main() {
15374
15464
  archived: { type: "boolean" },
15375
15465
  "quota-hits": { type: "boolean" },
15376
15466
  by: { type: "string" },
15467
+ cost: { type: "boolean" },
15468
+ canal: { type: "string" },
15377
15469
  models: { type: "boolean" },
15378
15470
  teams: { type: "string" },
15379
15471
  owner: { type: "string" },
@@ -15421,7 +15513,7 @@ async function main() {
15421
15513
  const tokens = splitTokens(pos, v);
15422
15514
  globals.token = tokens.session;
15423
15515
  globals.profile = v.profile;
15424
- if (v.version) return out({ version: "0.63.0" }, () => "0.63.0");
15516
+ if (v.version) return out({ version: "0.66.0" }, () => "0.66.0");
15425
15517
  for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
15426
15518
  const context = (await readConfig()).workspace;
15427
15519
  if (!explicitToken()?.startsWith("gat_")) {
@@ -15479,7 +15571,7 @@ async function main() {
15479
15571
  }
15480
15572
  return agentsCreate(v);
15481
15573
  }
15482
- if (sub === "get") return agentsGet(a1, v.fields, v["prompt-out"]);
15574
+ if (sub === "get" || sub === "show") return agentsGet(a1, v.fields, v["prompt-out"]);
15483
15575
  if (sub === "share" || sub === "unshare" || sub === "shares") return agentsShare(sub, a1, a2, v);
15484
15576
  if (sub === "teams") return agentsTeams(a1, a2, pos[4], v);
15485
15577
  if (sub === "set") return agentsSet(a1, v);
@@ -15553,6 +15645,7 @@ async function main() {
15553
15645
  if (v.images) return imageUsage(v);
15554
15646
  if (v.boxes && v.by === "template") return fleetBoxes();
15555
15647
  if (v.boxes) return boxesUsage(v.workspace ?? context);
15648
+ if (v.agent) return agentUsage(v.agent, v);
15556
15649
  if (v.workspace || v.by || v.days) return workspaceUsage(v.workspace ?? context, v);
15557
15650
  return meUsage();
15558
15651
  case "engines":
@@ -15592,7 +15685,7 @@ async function main() {
15592
15685
  throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
15593
15686
  }
15594
15687
  }
15595
- var notice = updateNotice("0.63.0").catch(() => null);
15688
+ var notice = updateNotice("0.66.0").catch(() => null);
15596
15689
  main().then(
15597
15690
  async () => {
15598
15691
  const n = await notice;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostystudio/cli",
3
- "version": "0.63.0",
3
+ "version": "0.66.0",
4
4
  "description": "Official Ghosty Studio CLI — configure, test and chat with your agents from the terminal. Built for humans and coding agents.",
5
5
  "type": "module",
6
6
  "bin": {