@ghostlytools/cli 1.2.3 → 1.3.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 (86) hide show
  1. package/README.md +18 -7
  2. package/dist/assets/api-BiaX6l6f.js +3 -0
  3. package/dist/assets/api-CrxVxtY1.js +4071 -0
  4. package/dist/assets/api-CrxVxtY1.js.map +1 -0
  5. package/dist/assets/apiKit-CajiDxdK.js +196 -0
  6. package/dist/assets/apiKit-CajiDxdK.js.map +1 -0
  7. package/dist/assets/apps-CbfiCSIw.js +787 -0
  8. package/dist/assets/apps-CbfiCSIw.js.map +1 -0
  9. package/dist/assets/apps-t23gkc28.js +2 -0
  10. package/dist/assets/{arkade-B-ALutmU.js → arkade-D4BVJFEQ.js} +2 -2
  11. package/dist/assets/{arkade-B-ALutmU.js.map → arkade-D4BVJFEQ.js.map} +1 -1
  12. package/dist/assets/backup-BAMi2lAq.js +731 -0
  13. package/dist/assets/backup-BAMi2lAq.js.map +1 -0
  14. package/dist/assets/backup-Cg52WeQi.js +2 -0
  15. package/dist/assets/bark_ffi_wasm_bg-EY2uc0Bx.js.map +1 -1
  16. package/dist/assets/bitcoindevkit_bg-B-iLWrmX.js.map +1 -1
  17. package/dist/assets/buttons-CWl2yNJu.js +2 -0
  18. package/dist/assets/buttons-CX1pKB0j.js +497 -0
  19. package/dist/assets/buttons-CX1pKB0j.js.map +1 -0
  20. package/dist/assets/{endpoint-pgFkR2AS.js → endpoint-Dn7H8qE1.js} +14 -8
  21. package/dist/assets/endpoint-Dn7H8qE1.js.map +1 -0
  22. package/dist/assets/envelope-BvU0fLEt.js +90 -0
  23. package/dist/assets/envelope-BvU0fLEt.js.map +1 -0
  24. package/dist/assets/errors-my6VJR_0.js +77 -0
  25. package/dist/assets/errors-my6VJR_0.js.map +1 -0
  26. package/dist/assets/{fileBytes-Dbifu5I5.js → fileBytes-CfSXjTFa.js} +2 -2
  27. package/dist/assets/{fileBytes-Dbifu5I5.js.map → fileBytes-CfSXjTFa.js.map} +1 -1
  28. package/dist/assets/fileBytes-CgbibpbV.js +2 -0
  29. package/dist/assets/{fileBytes-BcYZhNgF.js → fileBytes-Di7VZtmU.js} +6 -19
  30. package/dist/assets/fileBytes-Di7VZtmU.js.map +1 -0
  31. package/dist/assets/fileBytesIdb-CFP-DSkZ.js +2 -0
  32. package/dist/assets/{fileBytesIdb-DzSaqI0A.js → fileBytesIdb-D5u6H8X_.js} +4 -4
  33. package/dist/assets/{fileBytesIdb-DzSaqI0A.js.map → fileBytesIdb-D5u6H8X_.js.map} +1 -1
  34. package/dist/assets/{fileBytesOpfs-Dx8RZiV5.js → fileBytesOpfs-Dd1N4ERH.js} +3 -3
  35. package/dist/assets/{fileBytesOpfs-Dx8RZiV5.js.map → fileBytesOpfs-Dd1N4ERH.js.map} +1 -1
  36. package/dist/assets/groupFiles-BNTSDaoq.js +7685 -0
  37. package/dist/assets/groupFiles-BNTSDaoq.js.map +1 -0
  38. package/dist/assets/groupFiles-DBbjOLuD.js +2088 -0
  39. package/dist/assets/groupFiles-DBbjOLuD.js.map +1 -0
  40. package/dist/assets/host-Cmd205Dc.js +4648 -0
  41. package/dist/assets/host-Cmd205Dc.js.map +1 -0
  42. package/dist/assets/hyperdhtRelay-BT_wRxab.js +21 -0
  43. package/dist/assets/hyperdhtRelay-BT_wRxab.js.map +1 -0
  44. package/dist/assets/{hyperdhtRelay-hKC9DpIH.js → hyperdhtRelay-CEmBpT0Q.js} +26 -10
  45. package/dist/assets/hyperdhtRelay-CEmBpT0Q.js.map +1 -0
  46. package/dist/assets/{idb-CTF6LF5B.js → idb-B5L8wuOm.js} +7 -5
  47. package/dist/assets/idb-B5L8wuOm.js.map +1 -0
  48. package/dist/assets/irohWeb--YyEA-hX.js +545 -0
  49. package/dist/assets/irohWeb--YyEA-hX.js.map +1 -0
  50. package/dist/assets/{joinTrace-CO8mlhNO.js → joinTrace-CjRDFy85.js} +2 -7
  51. package/dist/assets/{joinTrace-CO8mlhNO.js.map → joinTrace-CjRDFy85.js.map} +1 -1
  52. package/dist/assets/joinTrace-D-fnt2p3.js +2 -0
  53. package/dist/assets/main-BzNN6bkx.js +4302 -0
  54. package/dist/assets/main-BzNN6bkx.js.map +1 -0
  55. package/dist/assets/{mainline-DriRu_hb.js → mainline-D5D5C-jT.js} +14 -6
  56. package/dist/assets/mainline-D5D5C-jT.js.map +1 -0
  57. package/dist/assets/mints-BrlY773j.js +74 -0
  58. package/dist/assets/mints-BrlY773j.js.map +1 -0
  59. package/dist/assets/mints-CqTdA4Gk.js +2 -0
  60. package/dist/assets/networkReason-DxZWHw6v.js +154 -0
  61. package/dist/assets/networkReason-DxZWHw6v.js.map +1 -0
  62. package/dist/assets/privateFolder-Bk9C9oFv.js +38 -0
  63. package/dist/assets/privateFolder-Bk9C9oFv.js.map +1 -0
  64. package/dist/assets/profiles-B6F4oa9K.js +139 -0
  65. package/dist/assets/profiles-B6F4oa9K.js.map +1 -0
  66. package/dist/assets/{restoredRows-C_84q0Pd.js → restoredRows-Db3oUTko.js} +2 -2
  67. package/dist/assets/{restoredRows-C_84q0Pd.js.map → restoredRows-Db3oUTko.js.map} +1 -1
  68. package/dist/assets/{server-DHMXMwNn.js → server-CBCEYKMN.js} +1290 -277
  69. package/dist/assets/server-CBCEYKMN.js.map +1 -0
  70. package/dist/assets/{src-_FzJkeAJ.js → src-DhfGgAUu.js} +1068 -2266
  71. package/dist/assets/src-DhfGgAUu.js.map +1 -0
  72. package/dist/assets/turnRefs-ChEfgbSX.js +323 -0
  73. package/dist/assets/turnRefs-ChEfgbSX.js.map +1 -0
  74. package/dist/assets/{usdt-D0lO2pRR.js → usdt-C1Xao2xH.js} +3 -3
  75. package/dist/assets/{usdt-D0lO2pRR.js.map → usdt-C1Xao2xH.js.map} +1 -1
  76. package/dist/ghostly.mjs +4 -21992
  77. package/dist/ghostly.mjs.map +1 -1
  78. package/package.json +1 -1
  79. package/dist/assets/endpoint-pgFkR2AS.js.map +0 -1
  80. package/dist/assets/fileBytes-BcYZhNgF.js.map +0 -1
  81. package/dist/assets/hyperdhtRelay-hKC9DpIH.js.map +0 -1
  82. package/dist/assets/idb-CTF6LF5B.js.map +0 -1
  83. package/dist/assets/mainline-DriRu_hb.js.map +0 -1
  84. package/dist/assets/rolldown-runtime-8H4AJuhK.js +0 -14
  85. package/dist/assets/server-DHMXMwNn.js.map +0 -1
  86. package/dist/assets/src-_FzJkeAJ.js.map +0 -1
package/README.md CHANGED
@@ -73,7 +73,8 @@ and `send --reply` for its answer: [examples/claude-code-agent.sh](examples/clau
73
73
  Each profile is a folder, `~/.ghostly/profiles/<name>/` (0700; files 0600), with its own chats, keys and wallets.
74
74
  `--profile <name>` (or `GHOSTLY_PROFILE`) picks one; `ghostly profile use <name>` sets the current one;
75
75
  `--home <dir>` (or `GHOSTLY_HOME`) moves the whole folder. The `default` profile is made on first use, others with
76
- `ghostly profile create <name>`.
76
+ `ghostly profile create <name>`. An empty `--profile` or `--home` (`-p "$BOT"` with `BOT` unset) is a usage error;
77
+ an empty `GHOSTLY_PROFILE` or `GHOSTLY_HOME` counts as unset.
77
78
 
78
79
  Only one process opens a profile at a time. When a daemon runs it, every command goes through the daemon's socket.
79
80
  When none does, a command runs the profile itself for as long as it needs (a **one-shot**) and leaves: `send` then
@@ -91,8 +92,11 @@ The rows are in alphabetical order of their first command, and every command of
91
92
  | Command | What it does |
92
93
  |---|---|
93
94
  | `app init <dir> [--name <name>] [--title <title>] [--force]` | Start an app (WISP 1200, Apps), run here with no profile or daemon: a small working one in `<dir>` (made when missing), which `app publish <dir>` signs as it is. It writes `ghostly-app.json` (`view: chat`, the `chat` permission), an `index.html` that says hello to the same app on the contact's side, typed against `@ghostlytools/sdk/app`, and a `README.md` with build, publish, verify and how to list it in a store. The name is `--name` (a lowercase letter, then up to 31 lowercase letters, digits or hyphens), else the folder's (`My App` gives `my-app`); the title is `--title` (one line, up to 40 characters), else the name's. When one of the three files is there nothing is written and it is `refused` (`details.reason` `exists`, `details.files`), unless `--force`, which replaces those three only. Answers `{dir, name, title, files, replaced?, next}` |
95
+ | `app open <chat> <ref\|name> [--no-card]`, `app close <chat> <ref\|name>` | A served app in a chat, as a bot (WISP 1200, Apps; needs the daemon, and `app serve` first). `app open` says the app is open on this side, in the version served, and sends the contact the app's card ("opened Chess", with what their app needs to get the same app and check it), unless their app is open in that chat already or `--no-card`. The two sides talk once both opened it; while the app stays open here, the engine says so again on every session that comes back. It answers `{chat, app, version, card, peer, live}`: `card` is the card's message id or null, `peer` the version the contact has open or null. A card that cannot go leaves nothing open. `app close` ends it: `{chat, app, closed}`. What is open is kept in memory: a restarted daemon opens again. `unavailable` in a one-shot, or on a daemon that started before the first app was served (`daemon restart`); `not_found` for an app not served; `refused`, in the engine's words, for a chat that is not a paired 1:1 chat |
94
96
  | `app publish <dir> --key <file> [--out <file>] [--sequence n]`, `app verify <bundle\|url>` | The publisher tools of WISP 1200 (Apps), run here with no profile or daemon. `app publish` bundles and signs an app: `<dir>/ghostly-app.json` holds the manifest's fields but `publisher`, `sequence` and `files`, and every other file in `<dir>` goes in (dot files are left out and listed in `skipped`). It writes `<dir>/app.ghostlyapp` (or `--out`), its `sequence` one more than the bundle already there, which only the same key may follow (`--sequence n` sets it, refused unless higher). `--key` names the publisher key file, a PKCS #8 PEM: made owner-only on first use (back it up: an app is updated only with its key), refused when others may read it or when it is inside `<dir>`, never printed; a folder holding any private key file is refused (`details.reason` `private-key`). `app verify` checks a bundle from a file or an `https` URL as a client does (jsDelivr only at a full commit, 16 MiB at most) and answers its manifest and digest, or `refused` (exit 1) with the WISP's reason in `details.reason` |
95
97
  | `app revoke <dir> --key <file> (--digest <digest>… \| --up-to <sequence>) [--reason <text>] [--bundle <file>]` | Revoke versions of your app (WISP 1200 · Revocation): by digest (base64url, as `app verify` prints it; `--digest` again for each, up to 64) or every version up to a `sequence`, with an optional one-line reason. The statement names the app of `<dir>/app.ghostlyapp` (or `--bundle`), is signed with that app's publisher key (any other key is refused, and none is made here), and is added to `<dir>/ghostly-revoke.json`, published beside the bundle; a client that reads it stops those versions. Answers `{app, digests \| upTo, current, added, revocations, file}`; `current` says whether the bundle in `<dir>` is among them |
98
+ | `app send <chat> <ref\|name> <json\|->` | One message of a served app's own protocol to the same app on the contact's side (WISP 1200, Apps; needs the daemon): any JSON value, on the command line or `-` for stdin, at most 32 KiB, at most 48 a second. It goes on the live session only, while both sides have the app open, and is never kept for later: `{chat, app, sent: true}`, or an error whose `details.reason` is the WISP's name for why it did not go: `not-open` (`refused`: `app open` first), `too-large` (`bad_request`), `offline` and `peer-closed` (`unavailable`: the chat is not live, or the contact's app is not open; wait for `app.opened`), `too-fast` (`refused`). The contact's messages come as `app.message` events |
99
+ | `app serve <bundle\|url> --grant chat [--grant name] [--url <url>]`, `app served`, `app unserve <ref\|name>` | Serve an app as a bot (WISP 1200, Apps): the profile speaks the app's messages in its chats itself, and no app runs here. `app serve` reads the signed bundle from a file or an `https` URL and checks it as `app verify` does (`refused` with the WISP's reason in `details.reason`). Each permission the manifest asks needs its `--grant`: `chat` (talk to the same app on the contact's side) and `name` (the profile's name in that chat); one left out is `confirm` (exit 5), naming it in `details.missing`. `internet` cannot be granted (no page runs here), a permission the app does not ask is `bad_request`, and an app that does not ask for `chat` is `refused`. A newer version replaces the one served; an older one, or another bundle under the same `sequence`, is `refused`. It answers `{served: {ref, title, version, sequence, digest, url?, permissions, granted, servedAt}, offered, restart?}`; `url` is where a contact's app reads the bundle (`--url`, else the URL served from, else the manifest's first source). The list is kept in the profile's folder (`apps.json`). A profile's engine offers `apps/1` to contacts only while it serves an app, and reads the list when it starts: `offered` says whether it does now, and `restart: true` that `daemon restart` is needed for it. `app served` answers `{apps, offered, restart?}`; `app unserve` removes one by its reference or its name |
96
100
  | `button press <chat\|group> <message> <button> [--wait none\|sent\|delivered] [--timeout s]` | Press a button of someone else's question, as a tap in the app does (WISP 406 · Message Buttons): the reply carries the button's label, and the asker hears `button.pressed`. `<message>` is the question's id (its event or `chat history`), `<button>` a button's id from its `card`. Refused (exit 1) like a tap: closed buttons, a second answer past `--once`, a second press within a second. A one-shot in a chat waits until it went out, as `send`. Answers `{chat \| group, messageId, button, label, replyId, delivery \| edges}` |
97
101
  | `button update <chat\|group> <message> [--chosen <button>] [--close] [--text <text>] [--force] [--wait none\|confirmed\|sent] [--timeout s]` | Answer a question you sent with `send --button` (WISP 406 · Message Buttons): `--chosen` shows which button won, `--close` takes presses no more, `--text` changes the text (shown as edited; refused if it looks like a secret, unless `--force`); the buttons and, unless given, the text stay. `<message>` is the `messageId` send gave. Answers `{chat \| group, buttons, messageId, card, edits}` |
98
102
  | `call auto [on\|off] [--from <chat>]… [--rate n]` | Answer calls by themselves, from anyone or the chats named (kept in the profile) |
@@ -109,7 +113,7 @@ The rows are in alphabetical order of their first command, and every command of
109
113
  | `chat transport <chat> <auto\|dht\|webrtc\|iroh\|hyperdht>` | What carries the chat |
110
114
  | `chat verify <chat> --code <code>` | Mark the contact verified after comparing the codes out of band |
111
115
  | `chat wait <chat> [--until live\|text\|paired] [--timeout s]` | Wait for a chat to go live, carry text, or see its contact. Live means a session that exists now, in this run of the daemon: a chat that was live before a restart counts once its contact answers again |
112
- | `daemon [--detach]`, `daemon status`, `daemon stop`, `daemon restart` | Keep the profile online; `status` names its version and its socket (`socket`, for the [socket API](#the-socket-api)); `restart` stops it and starts this release's code in the background ([After an upgrade](#after-an-upgrade)). Ctrl-C, SIGTERM and the terminal closing (SIGHUP) stop it cleanly |
116
+ | `daemon [--detach] [--timeout s]`, `daemon status`, `daemon stop [--timeout s]`, `daemon restart [--timeout s]` | Keep the profile online; `status` names its version and its socket (`socket`, for the [socket API](#the-socket-api)); `restart` stops it and starts this release's code in the background ([After an upgrade](#after-an-upgrade)). Ctrl-C, SIGTERM and the terminal closing (SIGHUP) stop it cleanly |
113
117
  | `edit <chat> <message> [text… \| --text <text> \| --stdin] [--force] [--wait none\|confirmed] [--timeout s]` | Replace the text of a message you sent (1:1 chats, `group edit` for a group; `<message>` is the `messageId` `send` gave, or its wire id). The contact sees it in place, marked edited; `--wait confirmed` waits for its app to confirm (the default without a daemon). At most 100 edits a message, no time limit; an older contact app gets it once it shows edits |
114
118
  | `engine <method> [json \| -] [--confirm-real] [--show-secret]`, `engine --list` | Any call of the app's engine |
115
119
  | `events [--since seq]` | What the event journal holds, without following |
@@ -237,9 +241,10 @@ A spend on Mainnet needs the engine's `confirmedReal` (the app asks the person).
237
241
 
238
242
  SSH (`ssh-keygen`), OpenPGP (`gpg`) and Bitcoin (a wallet's "sign message") proofs are made with the tool: `identity
239
243
  add` prints the statement and the command, `identity complete` takes its output. A domain or a DID publishes a record,
240
- then `identity complete` asks the engine to look it up. In-app signers (a Nostr signer over NIP-46, Pubky, AT
241
- Protocol) run in one `identity add`, with their fields in `--field`, and print what they wait on (a link, a code) to
242
- stderr. OpenID Connect needs a browser window: make that proof in the app.
244
+ then `identity complete` asks the engine to look it up. In-app signers (a Nostr signer over NIP-46, Pubky) run in one
245
+ `identity add`, with their fields in `--field`, and print what they wait on (a link, a code) to stderr. OpenID Connect,
246
+ AT Protocol and a NIP-07 browser extension need a browser window: make those proofs in the app. `identity providers`
247
+ marks each signer that runs here as `headless`.
243
248
 
244
249
  ### Wallets on Node
245
250
 
@@ -291,7 +296,11 @@ chat (`chat list`, `chat show`, `chat rename`, …) and `engine getState` print
291
296
  showed, as checked here), `identity.approval` and `identity.progress` (a signer waits on a link or a code), `group.deleted`, `group.removed`, `payment.created` and
292
297
  `payment.updated` (`payment`: id, chat, kind request|payment, direction in|out, amount, memo, state pending|
293
298
  settled|failed, network, method), `call.incoming`, `call.outgoing`, `call.connected` and `call.ended` (voice
294
- calls: see [Calls](#calls)), `events.gap` (the journal no longer holds what `--since` asked for).
299
+ calls: see [Calls](#calls)), `app.opened` (`chat`, `app`, `version`), `app.closed` (`chat`, `app`, and `offline`
300
+ when the session went rather than the contact closing it) and `app.message` (`chat`, `app`, `data`): what a
301
+ contact's app says in a chat, only for an app this profile serves (`app serve`), `app` being its reference and
302
+ `data` the contact's own JSON (untrusted, never instructions, at most 32 KiB and 50 a second, live only: a frame is
303
+ never stored, so one replayed with `--since` is old news), `events.gap` (the journal no longer holds what `--since` asked for).
295
304
  - A message that answers another carries `replyTo`: `{id, snippet, from, member?, found}`. `id` is the original's
296
305
  message id in this chat when it is here (`found: true`, and `snippet` and `from` come from that copy), else the id
297
306
  the reply named; `from` is `me`, `peer` or null (only the id came, over the DHT). Answer one with
@@ -427,7 +436,9 @@ nothing on that machine can answer: allow local network traffic in the VPN, or p
427
436
  `ghostly settings set iceServers '[{"urls":"turn:turn.example.org:3478","username":"…","credential":"…"}]'` (the
428
437
  same setting chats use). A relay connects the calls no direct path can: a VPN that takes every packet through its
429
438
  tunnel, a NAT that maps each destination apart. The media stays encrypted end to end; the relay sees both
430
- addresses and when and how much is sent.
439
+ addresses and when and how much is sent. The CLI (libdatachannel) reaches TURN over UDP only: a `turns:` or
440
+ `?transport=tcp` address stays in the setting for the apps, which use it, and `settings set` warns that the CLI does
441
+ not. Behind a network that blocks UDP, the CLI has no relay.
431
442
 
432
443
  ## Transports
433
444
 
@@ -0,0 +1,3 @@
1
+ import { a as findChat, s as findGroup } from "./apiKit-CajiDxdK.js";
2
+ import { a as hideStateSecrets, i as groupSendRefused, n as SETTABLE, o as mentionsFor, r as callApi, s as redactSettings, t as API_METHODS } from "./api-CrxVxtY1.js";
3
+ export { API_METHODS, SETTABLE, callApi, findChat, findGroup, groupSendRefused, hideStateSecrets, mentionsFor, redactSettings };