@ghostlytools/cli 1.2.4 → 1.3.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.
- package/README.md +25 -9
- package/dist/assets/api-Dq2QXQDk.js +4172 -0
- package/dist/assets/api-Dq2QXQDk.js.map +1 -0
- package/dist/assets/api-TiB5QSG9.js +3 -0
- package/dist/assets/apiKit-CA2x5GJF.js +200 -0
- package/dist/assets/apiKit-CA2x5GJF.js.map +1 -0
- package/dist/assets/apps-BxV9i_Y4.js +786 -0
- package/dist/assets/apps-BxV9i_Y4.js.map +1 -0
- package/dist/assets/apps-C-T8jeji.js +2 -0
- package/dist/assets/{arkade-CdnKGDbg.js → arkade-C_qDmHnm.js} +2 -2
- package/dist/assets/{arkade-CdnKGDbg.js.map → arkade-C_qDmHnm.js.map} +1 -1
- package/dist/assets/backup-Bugnn3Ue.js +2 -0
- package/dist/assets/backup-CnMN2oUK.js +731 -0
- package/dist/assets/backup-CnMN2oUK.js.map +1 -0
- package/dist/assets/bark_ffi_wasm_bg-EY2uc0Bx.js.map +1 -1
- package/dist/assets/bitcoind-CZchoh43.js +349 -0
- package/dist/assets/bitcoind-CZchoh43.js.map +1 -0
- package/dist/assets/bitcoindProvider-DGw3xBSa.js +97 -0
- package/dist/assets/bitcoindProvider-DGw3xBSa.js.map +1 -0
- package/dist/assets/bitcoindevkit_bg-B-iLWrmX.js.map +1 -1
- package/dist/assets/buttons-Bj7Vf7Pn.js +2 -0
- package/dist/assets/buttons-CvNBzh2S.js +496 -0
- package/dist/assets/buttons-CvNBzh2S.js.map +1 -0
- package/dist/assets/{endpoint-pgFkR2AS.js → endpoint-BOTFMpfS.js} +56 -18
- package/dist/assets/endpoint-BOTFMpfS.js.map +1 -0
- package/dist/assets/envelope-WjingYSc.js +90 -0
- package/dist/assets/envelope-WjingYSc.js.map +1 -0
- package/dist/assets/errors-DO5z6h_l.js +105 -0
- package/dist/assets/errors-DO5z6h_l.js.map +1 -0
- package/dist/assets/fedimint_client_wasm_bg-BtHHlFpp.js.map +1 -1
- package/dist/assets/{fileBytes-Dbifu5I5.js → fileBytes-CfSXjTFa.js} +2 -2
- package/dist/assets/{fileBytes-Dbifu5I5.js.map → fileBytes-CfSXjTFa.js.map} +1 -1
- package/dist/assets/fileBytes-CgbibpbV.js +2 -0
- package/dist/assets/{fileBytes-BcYZhNgF.js → fileBytes-Di7VZtmU.js} +6 -19
- package/dist/assets/fileBytes-Di7VZtmU.js.map +1 -0
- package/dist/assets/fileBytesIdb-CFP-DSkZ.js +2 -0
- package/dist/assets/{fileBytesIdb-DzSaqI0A.js → fileBytesIdb-D5u6H8X_.js} +4 -4
- package/dist/assets/{fileBytesIdb-DzSaqI0A.js.map → fileBytesIdb-D5u6H8X_.js.map} +1 -1
- package/dist/assets/{fileBytesOpfs-Dx8RZiV5.js → fileBytesOpfs-Dd1N4ERH.js} +3 -3
- package/dist/assets/{fileBytesOpfs-Dx8RZiV5.js.map → fileBytesOpfs-Dd1N4ERH.js.map} +1 -1
- package/dist/assets/groupFiles-IEUW3DQz.js +3202 -0
- package/dist/assets/groupFiles-IEUW3DQz.js.map +1 -0
- package/dist/assets/host-CWt-jtqz.js +4673 -0
- package/dist/assets/host-CWt-jtqz.js.map +1 -0
- package/dist/assets/hyperdhtRelay-BT_wRxab.js +21 -0
- package/dist/assets/hyperdhtRelay-BT_wRxab.js.map +1 -0
- package/dist/assets/{hyperdhtRelay-C1p0nkle.js → hyperdhtRelay-CPYwSLLS.js} +25 -10
- package/dist/assets/hyperdhtRelay-CPYwSLLS.js.map +1 -0
- package/dist/assets/{idb-CTF6LF5B.js → idb-B5L8wuOm.js} +7 -5
- package/dist/assets/idb-B5L8wuOm.js.map +1 -0
- package/dist/assets/irohWeb-4oChIOIp.js +544 -0
- package/dist/assets/irohWeb-4oChIOIp.js.map +1 -0
- package/dist/assets/{joinTrace-CO8mlhNO.js → joinTrace-CjRDFy85.js} +2 -7
- package/dist/assets/{joinTrace-CO8mlhNO.js.map → joinTrace-CjRDFy85.js.map} +1 -1
- package/dist/assets/joinTrace-D-fnt2p3.js +2 -0
- package/dist/assets/main-DbqcdShN.js +4409 -0
- package/dist/assets/main-DbqcdShN.js.map +1 -0
- package/dist/assets/{mainline-BH6s8HVi.js → mainline-ZkiOnevs.js} +11 -6
- package/dist/assets/mainline-ZkiOnevs.js.map +1 -0
- package/dist/assets/mints-BrlY773j.js +74 -0
- package/dist/assets/mints-BrlY773j.js.map +1 -0
- package/dist/assets/mints-CqTdA4Gk.js +2 -0
- package/dist/assets/networkReason-CetKkTPo.js +154 -0
- package/dist/assets/networkReason-CetKkTPo.js.map +1 -0
- package/dist/assets/nwc-CgkqyvsE.js +612 -0
- package/dist/assets/nwc-CgkqyvsE.js.map +1 -0
- package/dist/assets/nwcProvider-4eVz_8HP.js +77 -0
- package/dist/assets/nwcProvider-4eVz_8HP.js.map +1 -0
- package/dist/assets/privateFolder-Bk9C9oFv.js +38 -0
- package/dist/assets/privateFolder-Bk9C9oFv.js.map +1 -0
- package/dist/assets/profiles-BHc9pEYg.js +139 -0
- package/dist/assets/profiles-BHc9pEYg.js.map +1 -0
- package/dist/assets/registry-DlAKO0Fy.js +3793 -0
- package/dist/assets/registry-DlAKO0Fy.js.map +1 -0
- package/dist/assets/registry-OBJBnHVQ.js +2 -0
- package/dist/assets/resolve-CouHhCpJ.js +591 -0
- package/dist/assets/resolve-CouHhCpJ.js.map +1 -0
- package/dist/assets/{restoredRows-C_84q0Pd.js → restoredRows-Db3oUTko.js} +2 -2
- package/dist/assets/{restoredRows-C_84q0Pd.js.map → restoredRows-Db3oUTko.js.map} +1 -1
- package/dist/assets/{server-0zfNpABQ.js → server-Ss0gJ-nw.js} +1275 -1404
- package/dist/assets/server-Ss0gJ-nw.js.map +1 -0
- package/dist/assets/{src-CbLkHfz8.js → src-DDzSERyc.js} +882 -134
- package/dist/assets/src-DDzSERyc.js.map +1 -0
- package/dist/assets/turnRefs-B87dtrHM.js +323 -0
- package/dist/assets/turnRefs-B87dtrHM.js.map +1 -0
- package/dist/assets/types-C4_KafL_.js +122 -0
- package/dist/assets/types-C4_KafL_.js.map +1 -0
- package/dist/assets/{usdt-Qf4UuygS.js → usdt-Fj8CQO2z.js} +3 -3
- package/dist/assets/{usdt-Qf4UuygS.js.map → usdt-Fj8CQO2z.js.map} +1 -1
- package/dist/ghostly.mjs +4 -22077
- package/dist/ghostly.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/assets/endpoint-pgFkR2AS.js.map +0 -1
- package/dist/assets/fileBytes-BcYZhNgF.js.map +0 -1
- package/dist/assets/hyperdhtRelay-C1p0nkle.js.map +0 -1
- package/dist/assets/idb-CTF6LF5B.js.map +0 -1
- package/dist/assets/mainline-BH6s8HVi.js.map +0 -1
- package/dist/assets/rolldown-runtime-8H4AJuhK.js +0 -14
- package/dist/assets/server-0zfNpABQ.js.map +0 -1
- package/dist/assets/src-CbLkHfz8.js.map +0 -1
package/README.md
CHANGED
|
@@ -92,8 +92,11 @@ The rows are in alphabetical order of their first command, and every command of
|
|
|
92
92
|
| Command | What it does |
|
|
93
93
|
|---|---|
|
|
94
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 |
|
|
95
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` |
|
|
96
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 |
|
|
97
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}` |
|
|
98
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}` |
|
|
99
102
|
| `call auto [on\|off] [--from <chat>]… [--rate n]` | Answer calls by themselves, from anyone or the chats named (kept in the profile) |
|
|
@@ -110,7 +113,7 @@ The rows are in alphabetical order of their first command, and every command of
|
|
|
110
113
|
| `chat transport <chat> <auto\|dht\|webrtc\|iroh\|hyperdht>` | What carries the chat |
|
|
111
114
|
| `chat verify <chat> --code <code>` | Mark the contact verified after comparing the codes out of band |
|
|
112
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 |
|
|
113
|
-
| `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 |
|
|
114
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 |
|
|
115
118
|
| `engine <method> [json \| -] [--confirm-real] [--show-secret]`, `engine --list` | Any call of the app's engine |
|
|
116
119
|
| `events [--since seq]` | What the event journal holds, without following |
|
|
@@ -124,7 +127,7 @@ The rows are in alphabetical order of their first command, and every command of
|
|
|
124
127
|
| `group edit <group> <message> [text… \| --text <text> \| --stdin] [--mention <member>]… [--force]` | Replace the text of a message you sent to the group (`<message>` is the `messageId` `group send` gave). Every member sees it in place, marked edited; mentions whose `@name` is still in the text stay, `--mention` adds more. Answers `{group, messageId, edits, sent, edges}`; `--wait sent` and `--timeout` as for `group send`. The text the message already has is no edit: `sent: false, unchanged: true`. A private group's members whose edge is down get it when it opens, a community's with the catch-up; a member on an older app keeps the old text |
|
|
125
128
|
| `group hub <group> <member> [--pin \| --exclude \| --auto]` | Past 16 members: pin a member as a hub, keep one from being a hub, or leave it to their app (a daemon offers itself) |
|
|
126
129
|
| `group invite <group> <chat>`, `group remove <group> <member>`, `group admin <group> <member>` | Membership, for the admin (each prints the group; `--show-secret` for its link) |
|
|
127
|
-
| `group leave <group
|
|
130
|
+
| `group leave <group> --yes`, `group forget <group> --yes`, `group accept\|decline <group>` | Membership. Leaving deletes the group's history and files on this device, so it asks for `--yes` (`confirm`, exit 5, without it), as `group forget` does; forget also deletes a group you were removed from, which keeps its history. An admin's leave hands the role to a member who is online and names them: `{left, admin: {key, name}}` |
|
|
128
131
|
| `group list [--show-secret]`, `group show <group> [--show-secret]`, `group history <group>` | Groups, members, history; a message names its author (`member` key, `nick` from the roster, or the name an author no longer in it had). The entry link prints as `<hidden>` without `--show-secret` |
|
|
129
132
|
| `group react <group> <message> <emoji> [--remove]` | React to a group's message. `refused` when the profile is not a member any more |
|
|
130
133
|
| `group rename <group> <name>` | A new name, for the admin (1 to 64 characters on one line); the picture stays. Members see it once it reaches them; until then, and on apps from before names, the group keeps the name it had when they got in |
|
|
@@ -156,7 +159,7 @@ The rows are in alphabetical order of their first command, and every command of
|
|
|
156
159
|
| `status` | The profile, its chats, whether WebRTC and calls run, the last event seq |
|
|
157
160
|
| `store sign <index> --key <file> [--out <dir>]` | Sign a store index (WISP 1200 · Stores) with the store key file (kept offline; made when missing and the index names no `key`): writes `ghostly-store.json`, canonical, and `ghostly-store.sig` beside the index or in `--out`. Refused, with the reason, when a client would refuse the index (`expires` more than 90 days ahead, a bad field), or when the index already there, signed by the same key, has a higher `sequence` (`rollback`) or the same one with other content (`equivocation`) |
|
|
158
161
|
| `task send <chat\|group> --title <title> [--status s] [--progress n \| --steps a/b] [--step "…"] [--item state:text]… [--pr-url url --pr-number n --additions n --deletions n --files n --pr-state s --pr-checks c] [--branch b] [--tag label]… [--parent task] [--link url]… [--id id] [--json json\|-\|file] [--force]`, `task update <chat\|group> <task> [fields…]` | A task card for a bot's work (WISP 405 · Status Cards): a title, a status (queued, running, blocked, done, failed, cancelled), progress, the step it is on, up to 20 steps or log lines (`--item done:Codec`; a lowercase word before the colon must be an item state: pending, running, done, failed or skipped) and its pull request, shown as a small card that apps without cards read as text. Optional, and ignored by apps from before them: where the pull request stands (`--pr-state draft`, `open`, `merged` or `closed`; an open one puts the task in the board's Review column) and its checks (`--pr-checks passing`, `failing` or `pending`), up to 3 tags of 24 characters (`--tag core --tag web`; an update's tags replace the card's), and `--parent <task>`, a task of yours in the same chat that this one is a part of (sent first; its parts stack under it on the board). `send` prints the task's id and message; `update` merges the fields given over the card (an update's `--item` list replaces the card's: give all of them) and edits its message, at most once per 2.5 s (sooner updates merge into the next). `--json` takes the whole card; `null` in it removes a field. Only the CLI sends cards: the app shows them |
|
|
159
|
-
| `typing <chat> [--kind typing\|recording\|thinking] [--status "<text>"] [--for s] [--stop]` | Show the contact you are writing, recording or thinking, or a short status line in its place ("Transcribing your audio…", 40 characters, no links): live chats only, it holds 6 s there; `--for s` keeps it on that long (up to 600 s; a one-shot stays that long); a new kind or status shows at once; a message to the chat or `--stop` ends it |
|
|
162
|
+
| `typing <chat> [--kind typing\|recording\|thinking] [--status "<text>"] [--for s] [--stop]` | Show the contact you are writing, recording or thinking, or a short status line in its place ("Transcribing your audio…", 40 characters, no links): live chats only, it holds 6 s there; `--for s` keeps it on that long (up to 600 s; a one-shot stays that long once the chat is live, and stops with `live: false` when it is not live within 15 s); a new kind or status shows at once; a message to the chat or `--stop` ends it |
|
|
160
163
|
| `usage send [<chat\|group>] [--all] --left <percent> [--window "5 h"] [--resets <time>] [--label Claude] [--account <name>] [--also week=80@<time>]… [--used n --limit n] [--id id] [--json json\|-\|file] [--force]` | How much of a quota the bot has left (WISP 405 § Usage): the percent (or `--used` of `--limit`), what it is of, the account, the window, when it resets, and up to 3 other windows (`--also week=80@2026-10-10T00:00:00Z`). The app shows a small meter on the chat's row and in its header, amber under 20%, red under 5%, muted once 6 h old or past the reset. One card per chat: the first report sends it, later ones edit it in place (quiet, paced as `task update`'s); each report is whole, so a field it leaves out goes. `--all` reports to every 1:1 chat with a contact. See [docs/AI-AGENTS.md](../../docs/AI-AGENTS.md#reporting-usage) for where a bot gets its numbers |
|
|
161
164
|
| `version` | This CLI's version, `{"version":"…"}` (also `ghostly --version`) |
|
|
162
165
|
| `wallet create <type> [--network testnet] [--provider id] [--value name=value]… [--stdin] [--invite code] [--api-key key]` | A wallet: `cashu`, `lightning` (a card: its source's form in `--value`), `arkade`, `spark` (on Mainnet, `--api-key` is your Breez API key), `bitcoin` (BDK), `fedimint` (`--invite` is the federation's invite code), `usdt`. With `--stdin`, secret fields come as `name=value` lines on stdin (`api-key=…` too), out of `ps` and the shell's history |
|
|
@@ -238,9 +241,10 @@ A spend on Mainnet needs the engine's `confirmedReal` (the app asks the person).
|
|
|
238
241
|
|
|
239
242
|
SSH (`ssh-keygen`), OpenPGP (`gpg`) and Bitcoin (a wallet's "sign message") proofs are made with the tool: `identity
|
|
240
243
|
add` prints the statement and the command, `identity complete` takes its output. A domain or a DID publishes a record,
|
|
241
|
-
then `identity complete` asks the engine to look it up. In-app signers (a Nostr signer over NIP-46, Pubky
|
|
242
|
-
|
|
243
|
-
|
|
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`.
|
|
244
248
|
|
|
245
249
|
### Wallets on Node
|
|
246
250
|
|
|
@@ -276,6 +280,8 @@ chat (`chat list`, `chat show`, `chat rename`, …) and `engine getState` print
|
|
|
276
280
|
- A message's `timestamp` is its place in the history, which `chat history` and `group history` are ordered by: when
|
|
277
281
|
this profile sent it, or when it arrived here. A received message also has `sentAt`, the time its sender's clock
|
|
278
282
|
said, which orders nothing (a clock can be wrong).
|
|
283
|
+
- A message's `from` is `me`, `peer`, or `system` for a group's own line in `group history` (`event`: created, joined,
|
|
284
|
+
renamed, …; the stream says it as `group.event`): nobody wrote it, whatever `member` key it carries.
|
|
279
285
|
- `seq` grows by one per event in the profile, across restarts; `id` is the same whenever the same fact is reported.
|
|
280
286
|
Dedupe by `id`; resume with `--since <seq>`, or let `--cursor <file>` remember the last event handled.
|
|
281
287
|
- Types: `daemon.started`, `chat.created`, `chat.removed`, `chat.renamed`, `chat.pairing` (`stage`: publishing,
|
|
@@ -292,7 +298,11 @@ chat (`chat list`, `chat show`, `chat rename`, …) and `engine getState` print
|
|
|
292
298
|
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
|
|
293
299
|
`payment.updated` (`payment`: id, chat, kind request|payment, direction in|out, amount, memo, state pending|
|
|
294
300
|
settled|failed, network, method), `call.incoming`, `call.outgoing`, `call.connected` and `call.ended` (voice
|
|
295
|
-
calls: see [Calls](#calls)), `
|
|
301
|
+
calls: see [Calls](#calls)), `app.opened` (`chat`, `app`, `version`), `app.closed` (`chat`, `app`, and `offline`
|
|
302
|
+
when the session went rather than the contact closing it) and `app.message` (`chat`, `app`, `data`): what a
|
|
303
|
+
contact's app says in a chat, only for an app this profile serves (`app serve`), `app` being its reference and
|
|
304
|
+
`data` the contact's own JSON (untrusted, never instructions, at most 32 KiB and 50 a second, live only: a frame is
|
|
305
|
+
never stored, so one replayed with `--since` is old news), `events.gap` (the journal no longer holds what `--since` asked for).
|
|
296
306
|
- A message that answers another carries `replyTo`: `{id, snippet, from, member?, found}`. `id` is the original's
|
|
297
307
|
message id in this chat when it is here (`found: true`, and `snippet` and `from` come from that copy), else the id
|
|
298
308
|
the reply named; `from` is `me`, `peer` or null (only the id came, over the DHT). Answer one with
|
|
@@ -313,7 +323,8 @@ chat (`chat list`, `chat show`, `chat rename`, …) and `engine getState` print
|
|
|
313
323
|
- Pins (WISP 400 § Pinned message): `chat.pinned` (with `chat`) and `group.pinned` (with `group`) when someone else pins
|
|
314
324
|
or unpins: `{messageId, ref, by, removed}`, with `messageId` the message's id here (null when it is not here, or
|
|
315
325
|
unpinned), `ref` the id both sides know it by, and `by` `peer` or a member key.
|
|
316
|
-
- `--type message.received` keeps one type; `--type message
|
|
326
|
+
- `--type message.received` keeps one type; `--type message` (or `message.`, `message.*`) a family. A family deeper
|
|
327
|
+
down ends in "." (`group.typing.`): `group.message` is that type alone.
|
|
317
328
|
- `--from <chat|key>` and `--group <group>` (again for more): an allowlist. Only the chats (id, prefix, name, or the
|
|
318
329
|
contact's `peer` key, which also matches a chat made later) and groups named get through; any other chat's or
|
|
319
330
|
group's event stops before `--exec`, `--webhook` and stdout (the message stays in the chat; the cursor moves past
|
|
@@ -388,6 +399,9 @@ with no framing:
|
|
|
388
399
|
rest of it, then plays padded.
|
|
389
400
|
- Barge-in: `ghostly call flush` (or `call.flush` on the socket API) drops everything queued, at once. Stop writing
|
|
390
401
|
before you flush.
|
|
402
|
+
- A call that ended unanswered (you hung up while it rang, or it rang out) is followed by the next one in that chat
|
|
403
|
+
no sooner than 2 s later: `call start` refuses sooner with `busy` and `details.retryAfterMs`. The contact's app
|
|
404
|
+
would not ring a call that comes that fast after a missed one.
|
|
391
405
|
- The socket exists from `call start`/`call answer`, so the program may connect before the media is up. One program
|
|
392
406
|
at a time: a new connection replaces the old one. When the call ends, the program reads EOF and the socket is
|
|
393
407
|
removed.
|
|
@@ -428,7 +442,9 @@ nothing on that machine can answer: allow local network traffic in the VPN, or p
|
|
|
428
442
|
`ghostly settings set iceServers '[{"urls":"turn:turn.example.org:3478","username":"…","credential":"…"}]'` (the
|
|
429
443
|
same setting chats use). A relay connects the calls no direct path can: a VPN that takes every packet through its
|
|
430
444
|
tunnel, a NAT that maps each destination apart. The media stays encrypted end to end; the relay sees both
|
|
431
|
-
addresses and when and how much is sent.
|
|
445
|
+
addresses and when and how much is sent. The CLI (libdatachannel) reaches TURN over UDP only: a `turns:` or
|
|
446
|
+
`?transport=tcp` address stays in the setting for the apps, which use it, and `settings set` warns that the CLI does
|
|
447
|
+
not. Behind a network that blocks UDP, the CLI has no relay.
|
|
432
448
|
|
|
433
449
|
## Transports
|
|
434
450
|
|