@ghostystudio/cli 0.9.0 → 0.9.1

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 +19 -5
  2. package/dist/index.js +39 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -8,24 +8,29 @@ npx -y @ghostystudio/cli login
8
8
  npm i -g @ghostystudio/cli && ghosty login
9
9
  ```
10
10
 
11
- `ghosty login` opens your browser (OAuth2 + PKCE). If you already have a session on ghosty.studio, opening the link is all it takes. A coding agent can drive it for you: `ghosty login --json` prints `{"event":"login_url","url":…}` first so the agent can hand you the link.
11
+ `ghosty login` opens your browser (OAuth2 + PKCE). If you already have a session on ghosty.studio, opening the link is all it takes. A coding agent can drive it for you: `ghosty login --json` prints `{"event":"login_url","url":…}` first so the agent can hand you the link. Over SSH, CI or from another device, `ghosty login --device` gives you a link + code instead (automatic when there is no local browser).
12
12
 
13
13
  ## Commands
14
14
 
15
15
  ```bash
16
16
  ghosty whoami
17
+ ghosty usage # plan and usage this week / month (also: ghosty me usage)
17
18
  ghosty agents ls
19
+ ghosty agents create --name NAME [--engine E] [--model M] [--prompt TEXT | --prompt-file FILE] [--env K=V,…]
18
20
  ghosty agents get <id> [--fields name,model,prompt]
19
- ghosty agents set <id> [--name] [--model] [--prompt | --prompt-file FILE]
21
+ ghosty agents set <id> [--name] [--engine] [--model] [--prompt | --prompt-file FILE] [--env K=V,…] [--connect ID,…] [--disconnect ID,…]
22
+ ghosty agents rm <id> [--yes]
20
23
  ghosty agents restart <id>
24
+ ghosty agents demo <id> [--slug NAME] [--on | --off] [--vence "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N]
25
+ [--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate] # public /p/ link, no account needed
21
26
  ghosty agents doctor <id> [--verbose] # exits 1 when it finds a problem
22
27
  ghosty agents docs ls|grant|revoke <id> [doc] [--write] [--no-deliver]
23
28
  ghosty agents set <id> --voice elevenlabs:ID --voice-replies auto --auto-stage on
24
29
 
25
30
  ghosty files ls|get|put|rm <id> [path] [--file LOCAL] [--out LOCAL]
26
31
  ghosty skills ls|get|add|rm <id> [slug] [--file SKILL.md | --dir FOLDER] [--out DIR]
27
- ghosty dbs ls|tables|query|import|grant|revoke <id> [db] [--write] [--external-write t1,t2] [--from easybits:ID --dry-run]
28
- ghosty turns ls <id> [--errors] [--since 1h] [--limit N]
32
+ ghosty dbs ls|tables|query|import|grant|revoke <id> [db] [--write] [--arg V]… [--external-write t1,t2] [--from easybits:ID --tables a,b --append --dry-run]
33
+ ghosty turns ls <id> [--errors | --status running|done|stopped|error] [--since 1h] [--limit N]
29
34
  ghosty channels whatsapp ls|enable|disable <id> [number] [--dry-run]
30
35
  ghosty board archive <id> --integration X | --column X | --before 30d [--dry-run]
31
36
  ghosty mcp get|set <id> [--file servers.json]
@@ -43,14 +48,23 @@ ghosty schedule rm <id> <schedule-id>
43
48
  ghosty me files ls|upload|rm [--kind image|video|audio|document|other]
44
49
  ghosty credentials ls|set|rm [provider] [--from-env VAR] # never as an argument
45
50
  ghosty docs
51
+
52
+ ghosty partner ls|enable|credentials|agent|tenants|audit|try # one agent for each of YOUR customers: ghosty partner --help
46
53
  ```
47
54
 
48
- Global: `--json` (stdout is JSON only), `--token <token>` / `GHOSTY_TOKEN` (a `gat_…` agent token reaches only that agent), `--help`, `--version`.
55
+ Global: `--json` (stdout is JSON only), `--token <token>` / `GHOSTY_TOKEN` (a `gat_…` agent token reaches only that agent), `--profile <name>` / `GHOSTY_PROFILE` (a separate saved session, e.g. one per account), `--yes`, `--help`, `--version`. Env: `GHOSTY_URL`, `XDG_CONFIG_HOME`, `NO_COLOR`; partner commands sign with `GHOSTY_PARTNER_KEY` + `GHOSTY_PARTNER_SECRET` when set.
56
+
57
+ Aliases: `creds` = `credentials`, `db` = `dbs`, `dbs sql` = `dbs query`.
49
58
 
50
59
  Every command has its own help with examples: `ghosty <command> --help` or `ghosty help <command>`.
51
60
 
52
61
  Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
53
62
 
63
+ ### Changes in 0.9.1
64
+
65
+ - `ghosty agents --help` describes every `agents demo` flag; `ghosty usage --help` has its own page.
66
+ - "Learn more" links point to the exact section of https://www.ghosty.studio/docs/cli/comandos; `partner --help` links to /docs/cli/partners.
67
+
54
68
  ### Changes in 0.9.0
55
69
 
56
70
  - `try --waba`: a test turn through the **real** WhatsApp Business path (inherited context, price rule, board, voice decision). It prints what it would have sent (text, voice note, files) and sends nothing. `--media` for photos/audio/PDF and `--history` to seed what was said before. `--whatsapp` is now an alias.
package/dist/index.js CHANGED
@@ -282,7 +282,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
282
282
  const req = httpsRequest(`${base}${path}`, {
283
283
  method: "POST",
284
284
  timeout: timeoutMs,
285
- headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.9.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
285
+ headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.9.1"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
286
286
  }, (res) => {
287
287
  let buf = "";
288
288
  res.on("data", (c) => buf += c);
@@ -324,7 +324,7 @@ async function request(path, opts = {}, retried = false) {
324
324
  method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
325
325
  headers: {
326
326
  authorization: `Bearer ${token}`,
327
- "user-agent": `ghosty-cli/${"0.9.0"}`,
327
+ "user-agent": `ghosty-cli/${"0.9.1"}`,
328
328
  ...opts.body !== void 0 ? { "content-type": "application/json" } : {},
329
329
  ...opts.headers
330
330
  },
@@ -744,7 +744,7 @@ async function agentsDemo(id, v) {
744
744
  if (v.on) body.enabled = true;
745
745
  if (v.off) body.enabled = false;
746
746
  if (v.turns) body.maxTurns = Number(v.turns);
747
- if (v.hours) body.trialHours = Number(v.hours);
747
+ if (v.vence !== void 0) body.venceEl = v.vence === "no" ? null : new Date(v.vence).toISOString();
748
748
  if (v["per-ip"]) body.perIpDay = Number(v["per-ip"]);
749
749
  if (v.welcome !== void 0) body.welcome = v.welcome;
750
750
  if (v.chips !== void 0) body.chips = v.chips.split("|").map((c) => c.trim()).filter(Boolean);
@@ -759,7 +759,7 @@ async function agentsDemo(id, v) {
759
759
  d,
760
760
  () => [
761
761
  `${d.enabled ? lavender("\u25CF on") : dim("\u25CB off")} ${d.url ?? dim("(no link yet: --slug NAME)")}`,
762
- dim(`trial: ${d.trialHours} h from the first message \xB7 cap ${d.maxTurns} messages per visitor \xB7 ${d.perIpDay} per IP per day`),
762
+ dim(`expires: ${d.venceEl ? new Date(d.venceEl).toLocaleString("es-MX") : "never"} \xB7 cap ${d.maxTurns} messages per visitor \xB7 ${d.perIpDay} per IP per day`),
763
763
  d.welcome ? `welcome: ${d.welcome}` : dim("welcome: (default greeting)"),
764
764
  d.starter ? `starter: \u2728 ${d.starter}` : dim("starter: (none)"),
765
765
  d.chips.length ? `chips: ${d.chips.join(" | ")}` : dim("chips: (default)"),
@@ -1069,7 +1069,7 @@ ${bold("Options")}
1069
1069
  --json Machine-readable output
1070
1070
 
1071
1071
  ${bold("Server credential mode")} GHOSTY_PARTNER_KEY=gpk_\u2026 GHOSTY_PARTNER_SECRET=gps_\u2026 ghosty partner agent get
1072
- ${dim("Docs: https://www.ghosty.studio/docs/cli")}`;
1072
+ ${dim("Docs: https://www.ghosty.studio/docs/cli/partners")}`;
1073
1073
  var enc5 = encodeURIComponent;
1074
1074
  function partnerCreds() {
1075
1075
  const key = process.env.GHOSTY_PARTNER_KEY;
@@ -1090,7 +1090,7 @@ async function call(path, v, init = {}) {
1090
1090
  "x-ghosty-ts": ts,
1091
1091
  "x-ghosty-sig": sig,
1092
1092
  "content-type": "application/json",
1093
- "user-agent": `ghosty-cli/${"0.9.0"}`
1093
+ "user-agent": `ghosty-cli/${"0.9.1"}`
1094
1094
  },
1095
1095
  body: method === "GET" ? void 0 : raw
1096
1096
  });
@@ -1537,6 +1537,7 @@ Archive ${plan.matched} card(s) on \xAB${plan.board}\xBB? (reversible: a new mes
1537
1537
 
1538
1538
  // src/help.ts
1539
1539
  var DOCS = "https://www.ghosty.studio/docs/cli";
1540
+ var REF = `${DOCS}/comandos`;
1540
1541
  var HELPS = {
1541
1542
  agents: {
1542
1543
  summary: "Create, inspect, change, check and delete agents.",
@@ -1548,7 +1549,7 @@ var HELPS = {
1548
1549
  "ghosty agents doctor <agent-id> [--verbose]",
1549
1550
  "ghosty agents docs ls|grant|revoke <agent-id> [doc] [--write] [--no-deliver]",
1550
1551
  "ghosty agents restart <agent-id>",
1551
- "ghosty agents demo <agent-id> [--slug NAME] [--on | --off] \u2026",
1552
+ 'ghosty agents demo <agent-id> [--slug NAME] [--on | --off] [--vence "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate]',
1552
1553
  "ghosty agents rm <agent-id> [--yes]"
1553
1554
  ],
1554
1555
  flags: [
@@ -1559,17 +1560,28 @@ var HELPS = {
1559
1560
  ["--verbose", "doctor: also list the checks that passed"],
1560
1561
  ["--write", "docs grant: the agent may replace the document (default: read only)"],
1561
1562
  ["--no-deliver", "docs grant: it can read it but never send it to whoever writes"],
1562
- ["--yes", "rm: skip the confirmation (required without a terminal)"]
1563
+ ["--yes", "rm: skip the confirmation (required without a terminal)"],
1564
+ ["--slug NAME", "demo: link name; a 6-char code is appended (/p/NAME-CODE)"],
1565
+ ["--on | --off", "demo: turn the public link on or off"],
1566
+ ["--vence DATE|no", `demo: fixed expiry in your machine's time ("2026-10-15T20:00"); no = never`],
1567
+ ["--turns N", "demo: messages per visitor (default 150)"],
1568
+ ["--per-ip N", "demo: messages per IP per day (default 30)"],
1569
+ ["--welcome TEXT", "demo: chat greeting (empty = default)"],
1570
+ ["--starter TEXT", 'demo: highlighted first suggestion ("" removes it)'],
1571
+ ['--chips "a|b|c"', "demo: suggestions, separated by |"],
1572
+ ["--sponsor on|off", "demo: copies people keep run on YOUR engine key"],
1573
+ ["--rotate", "demo: new code; the old link stops working"]
1563
1574
  ],
1564
1575
  examples: [
1565
1576
  "ghosty agents doctor cmu7pgbyr0001gee3ruk172mm",
1566
1577
  "ghosty agents set <id> --prompt-file PROMPT.md",
1567
1578
  "ghosty agents set <id> --voice elevenlabs:21m00Tcm4TlvDq8ikWAM --voice-replies auto --auto-stage on",
1568
1579
  'ghosty agents docs grant <id> "Cat\xE1logo 2026.pdf"',
1569
- "ghosty agents docs grant <id> precios.xlsx --write --no-deliver"
1580
+ "ghosty agents docs grant <id> precios.xlsx --write --no-deliver",
1581
+ 'ghosty agents demo <id> --slug guardias --on --vence "2026-10-15T20:00" --starter "Ens\xE9\xF1ame c\xF3mo empezar"'
1570
1582
  ],
1571
- notes: ["doctor exits 1 when it finds a problem, so it can gate a script or CI."],
1572
- learn: `${DOCS}#agents`
1583
+ notes: ["doctor exits 1 when it finds a problem, so it can gate a script or CI.", "demo with no flags only prints its status: link, expiry, caps and numbers."],
1584
+ learn: `${REF}#agentes`
1573
1585
  },
1574
1586
  skills: {
1575
1587
  summary: "Skills of an agent (agentskills.io format: a folder with SKILL.md).",
@@ -1592,7 +1604,7 @@ var HELPS = {
1592
1604
  "ghosty skills rm <id> cotizacion # keeps a local copy first"
1593
1605
  ],
1594
1606
  notes: ["rm saves a copy under ~/.config/ghosty/trash/ and prints the command that restores it."],
1595
- learn: `${DOCS}#skills`
1607
+ learn: `${REF}#skills`
1596
1608
  },
1597
1609
  dbs: {
1598
1610
  summary: "Databases an agent can use, and what it may write from customer channels.",
@@ -1621,7 +1633,7 @@ var HELPS = {
1621
1633
  "ghosty dbs import <id> totequim --from easybits:6a10c84c\u2026 --dry-run # reads $EASYBITS_API_KEY"
1622
1634
  ],
1623
1635
  notes: ["<db> is the database id or its name. From owner channels the agent reads and writes everything granted."],
1624
- learn: `${DOCS}#dbs`
1636
+ learn: `${REF}#bases-de-datos`
1625
1637
  },
1626
1638
  turns: {
1627
1639
  summary: "An agent's recent turns: what answered, what failed and why.",
@@ -1633,19 +1645,19 @@ var HELPS = {
1633
1645
  ["--limit N", "max rows (default 20, max 500)"]
1634
1646
  ],
1635
1647
  examples: ["ghosty turns ls <id> --errors --since 1h", "ghosty turns ls <id> --json --limit 100"],
1636
- learn: `${DOCS}#turns`
1648
+ learn: `${REF}#turnos`
1637
1649
  },
1638
1650
  files: {
1639
1651
  summary: "Files in the agent's machine.",
1640
1652
  usage: ["ghosty files ls <agent-id> [dir]", "ghosty files get <agent-id> <path> [--out LOCAL]", "ghosty files put <agent-id> <path> [--file LOCAL | < stdin]", "ghosty files rm <agent-id> <path> [--yes]"],
1641
1653
  examples: ["ghosty files put <id> knowledge/precios.md --file precios.md", "cat notas.md | ghosty files put <id> notas.md"],
1642
- learn: `${DOCS}#files`
1654
+ learn: `${REF}#archivos`
1643
1655
  },
1644
1656
  mcp: {
1645
1657
  summary: "MCP servers of an agent. set REPLACES the whole list.",
1646
1658
  usage: ["ghosty mcp get <agent-id>", "ghosty mcp set <agent-id> --file servers.json"],
1647
1659
  examples: ["ghosty mcp get <id> > servers.json && $EDITOR servers.json && ghosty mcp set <id> --file servers.json"],
1648
- learn: `${DOCS}#mcp`
1660
+ learn: `${REF}#servidores-mcp`
1649
1661
  },
1650
1662
  try: {
1651
1663
  summary: "Test turns: plain, through the real WhatsApp path (nothing is sent), or a replay of real conversations.",
@@ -1676,25 +1688,25 @@ var HELPS = {
1676
1688
  "Replays survive Ghosty deploys: a 503 is retried after its Retry-After; the report lives on your disk.",
1677
1689
  "--whatsapp is now an alias of --waba."
1678
1690
  ],
1679
- learn: `${DOCS}#try`
1691
+ learn: `${REF}#turnos-de-prueba`
1680
1692
  },
1681
1693
  chat: {
1682
1694
  summary: "Stream a conversation; with no message it is interactive.",
1683
1695
  usage: ['ghosty chat <agent-id> ["message"] [--conversation ID]', "ghosty conversations ls <agent-id>"],
1684
1696
  examples: ['ghosty chat <id> "hola"', "ghosty chat <id>"],
1685
- learn: `${DOCS}#chat`
1697
+ learn: `${REF}#conversaciones`
1686
1698
  },
1687
1699
  schedule: {
1688
1700
  summary: "Turns that run later, on the agent's own clock.",
1689
1701
  usage: ['ghosty schedule add <agent-id> "what to do" --in 30m | --at ISO [--every 12h --until ISO] [--conversation ID] [--title T]', "ghosty schedule ls <agent-id>", "ghosty schedule rm <agent-id> <schedule-id>"],
1690
1702
  examples: ['ghosty schedule add <id> "revisa pedidos pendientes" --every 12h --in 1h'],
1691
- learn: `${DOCS}#schedule`
1703
+ learn: `${REF}#programar-turnos`
1692
1704
  },
1693
1705
  me: {
1694
1706
  summary: "Your account: files and usage.",
1695
1707
  usage: ["ghosty me files ls|upload|rm [--kind image|video|audio|document|other]", "ghosty usage"],
1696
1708
  examples: ["ghosty me files ls --kind document"],
1697
- learn: `${DOCS}#me`
1709
+ learn: `${REF}#tu-cuenta`
1698
1710
  }
1699
1711
  };
1700
1712
  HELPS.credentials = {
@@ -1710,7 +1722,7 @@ HELPS.credentials = {
1710
1722
  "op read op://vault/claude/token | ghosty credentials set anthropic-oauth"
1711
1723
  ],
1712
1724
  notes: ["The key is never accepted as an argument: it would stay in your shell history and in `ps`."],
1713
- learn: `${DOCS}#credentials`
1725
+ learn: `${REF}#credenciales`
1714
1726
  };
1715
1727
  HELPS.creds = HELPS.credentials;
1716
1728
  HELPS.channels = {
@@ -1722,7 +1734,7 @@ HELPS.channels = {
1722
1734
  ],
1723
1735
  examples: ["ghosty channels whatsapp ls <id>", "ghosty channels whatsapp enable <id> 5512345678 --dry-run", "ghosty channels whatsapp disable <id> 5512345678"],
1724
1736
  notes: ["<number> is its id, its label or its last digits. One number, one agent: enabling it takes it from the other agent.", "Disabling keeps logging messages; nobody answers them."],
1725
- learn: `${DOCS}#channels`
1737
+ learn: `${REF}#canales-de-whatsapp`
1726
1738
  };
1727
1739
  HELPS.board = {
1728
1740
  summary: "The agent's sales board. It belongs to the WORKSPACE: you must be a member, a shared agent is not enough.",
@@ -1736,10 +1748,10 @@ HELPS.board = {
1736
1748
  ],
1737
1749
  examples: ["ghosty board archive <id> --integration prueba --dry-run", "ghosty board archive <id> --column Perdido --before 30d --yes"],
1738
1750
  notes: ["Archiving is reversible: when the customer writes again the card comes back. At least one filter is required."],
1739
- learn: `${DOCS}#board`
1751
+ learn: `${REF}#tablero`
1740
1752
  };
1741
1753
  HELPS.conversations = HELPS.chat;
1742
- HELPS.usage = HELPS.me;
1754
+ HELPS.usage = { ...HELPS.me, summary: "Your plan and how much you've used this week and month.", usage: ["ghosty usage", "ghosty me usage"], examples: ["ghosty usage", "ghosty usage --json"], learn: `${REF}#uso` };
1743
1755
  function helpText(cmd) {
1744
1756
  const h = HELPS[cmd];
1745
1757
  if (!h) return void 0;
@@ -1780,7 +1792,7 @@ ${bold("Agents")}
1780
1792
  agents rm <id> Delete an agent (owner only; asks you to type its name, or --yes)
1781
1793
  agents restart <id> Restart an ACP agent (needsRestart) so it loads new skills
1782
1794
  agents demo <id> Public demo link /p/<slug>: anyone tries it without an account, "Keep it" clones it to theirs
1783
- [--slug NAME] [--on | --off] [--hours N] [--turns N] [--per-ip N] [--welcome TEXT] [--chips "a|b|c"] [--starter TEXT] [--sponsor on|off] [--rotate]
1795
+ [--slug NAME] [--on | --off] [--vence "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXT] [--chips "a|b|c"] [--starter TEXT] [--sponsor on|off] [--rotate]
1784
1796
 
1785
1797
  ${bold("Configure an agent")}
1786
1798
  files ls|get|put|rm <id> [path] Files in the agent's machine [--file LOCAL] [--out LOCAL]
@@ -1881,7 +1893,7 @@ async function main() {
1881
1893
  on: { type: "boolean" },
1882
1894
  off: { type: "boolean" },
1883
1895
  turns: { type: "string" },
1884
- hours: { type: "string" },
1896
+ vence: { type: "string" },
1885
1897
  "per-ip": { type: "string" },
1886
1898
  welcome: { type: "string" },
1887
1899
  chips: { type: "string" },
@@ -1917,7 +1929,7 @@ async function main() {
1917
1929
  const tokens = splitTokens(pos, v);
1918
1930
  globals.token = tokens.session;
1919
1931
  globals.profile = v.profile;
1920
- if (v.version) return out({ version: "0.9.0" }, () => "0.9.0");
1932
+ if (v.version) return out({ version: "0.9.1" }, () => "0.9.1");
1921
1933
  const [cmd, sub, a1, a2] = pos;
1922
1934
  if (cmd === "partner" && (v.help || !sub || sub === "help")) return out({ help: PARTNER_HELP }, () => PARTNER_HELP);
1923
1935
  const topic = cmd === "help" ? sub : v.help ? cmd : void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostystudio/cli",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
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": {