ciphermesh 2.12.0 → 2.14.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.
- package/CHANGELOG.md +187 -0
- package/README.md +8 -6
- package/README.pt-BR.md +8 -6
- package/docs/ARCHITECTURE.md +332 -230
- package/docs/PROTOCOL.md +160 -5
- package/docs/SETUP.md +18 -0
- package/docs/commands.json +15 -7
- package/docs/design/multi-device.md +290 -0
- package/docs/design/sender-keys-on-relay.md +34 -3
- package/package.json +3 -3
- package/src/client/ChatController.js +736 -26
- package/src/client/UI.js +617 -124
- package/src/client/keyboard.js +388 -0
- package/src/crypto/DeviceIdentity.js +307 -0
- package/src/crypto/KeyManager.js +176 -4
- package/src/crypto/TrustStore.js +153 -0
- package/src/p2p/P2PChatController.js +94 -4
- package/src/protocol/messages.js +25 -1
- package/src/protocol/validators.js +16 -0
- package/src/server/SessionManager.js +63 -6
- package/src/server/WebSocketServer.js +40 -1
- package/src/shared/constants.js +9 -1
- package/src/shared/desktopNotify.js +204 -0
- package/src/shared/deviceProvisioning.js +112 -0
- package/src/shared/notifyWorker.js +46 -0
- package/src/shared/tips.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,193 @@
|
|
|
3
3
|
Notable changes per release. Older versions are reconstructed from the git
|
|
4
4
|
history — the commit bodies and pull requests remain the fuller record.
|
|
5
5
|
|
|
6
|
+
## 2.14.0
|
|
7
|
+
|
|
8
|
+
**The chat, read properly.** Three things a user reported in the same session:
|
|
9
|
+
notifications wrecking the screen, Shift+Enter sending instead of breaking a
|
|
10
|
+
line, and long messages running the whole width of the terminal.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Messages are laid out as blocks.** A header naming the sender, then the text
|
|
15
|
+
wrapped at 65 % of the window (78 columns at most) and indented under it,
|
|
16
|
+
instead of one line handed to the terminal's own wrapping and left to run into
|
|
17
|
+
the border. Own messages are no longer right-aligned — everything starts at the
|
|
18
|
+
same column and a coloured rule down the left says what a message is: yellow
|
|
19
|
+
when it mentions you, magenta for a DM, the accent for your own.
|
|
20
|
+
|
|
21
|
+
Runs from one sender fold under a single header, but only inside the same
|
|
22
|
+
minute, so folding a run never costs you a timestamp. Notices — system, error,
|
|
23
|
+
`/me`, tombstones — share the gutter and wrap with a hanging indent, though at
|
|
24
|
+
the window's width rather than the reading width, so `/help`'s table is not
|
|
25
|
+
folded in half on a window with room to spare.
|
|
26
|
+
|
|
27
|
+
Everything is laid out again when the terminal is resized, stored room buffers
|
|
28
|
+
included, so the scrollback is never left measured for a window you no longer
|
|
29
|
+
have.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **Shift+Enter inserts a newline.** A terminal cannot tell it from Enter unless
|
|
34
|
+
asked, so CipherMesh now negotiates the kitty keyboard protocol and xterm's
|
|
35
|
+
`modifyOtherKeys` on startup and undoes both on the way out. What the terminal
|
|
36
|
+
reports back is decoded ahead of the UI's key parser, which could not read it —
|
|
37
|
+
and without that step would have typed `13;2u` into the composer.
|
|
38
|
+
|
|
39
|
+
**Alt+Enter was broken too** and works now, on every terminal, protocol or not;
|
|
40
|
+
Ctrl+J still does the same. `CIPHERMESH_LEGACY_KEYS=1` turns the negotiation off
|
|
41
|
+
for terminals that dislike it.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **Desktop notifications no longer wreck the chat on Windows.** SnoreToast, the
|
|
46
|
+
back-end behind `node-notifier`, ignores the pipes it is given when
|
|
47
|
+
notifications are disabled for the application and writes its diagnostics to
|
|
48
|
+
the attached console instead — the one the chat is drawn on. A room could
|
|
49
|
+
become unreadable, one burst per incoming message, with `/notify off` the only
|
|
50
|
+
way out.
|
|
51
|
+
|
|
52
|
+
Notifications are now delivered on Windows by a detached helper with no console
|
|
53
|
+
of its own, so nothing it prints can reach the terminal. The first refusal also
|
|
54
|
+
mutes them for the session and says so once, in one line with the reason
|
|
55
|
+
summarised rather than the raw command line; sound alerts keep working and
|
|
56
|
+
`/notify on` retries. And they are rate-limited to one per three seconds, which
|
|
57
|
+
was the other half of the complaint.
|
|
58
|
+
|
|
59
|
+
### Internal
|
|
60
|
+
|
|
61
|
+
- **`docs/ARCHITECTURE.md` matches the code again, and a test keeps it that
|
|
62
|
+
way.** It listed `play-sound` as a production dependency, which it is not, and
|
|
63
|
+
omitted seven of the eleven that are; its directory tree named files that do
|
|
64
|
+
not exist and 2 of the 27 modules under `src/shared/`; about half the document
|
|
65
|
+
was still Portuguese; and it called the project SecureLAN Chat, three renames
|
|
66
|
+
later. `test/architecture-doc.test.js` now fails on any of those — the same
|
|
67
|
+
shape as the command-list check, for the same reason.
|
|
68
|
+
|
|
69
|
+
- The UI can be tested headlessly. `UI` takes the streams blessed drives, so the
|
|
70
|
+
layout — wrapping, alignment, relayout — runs against a fake terminal instead
|
|
71
|
+
of only being checked by eye.
|
|
72
|
+
|
|
73
|
+
- eslint 10.9.1, github/codeql-action 4.37.9.
|
|
74
|
+
|
|
75
|
+
## 2.13.0
|
|
76
|
+
|
|
77
|
+
**Multi-device.** One identity, several devices, and none of them holding a copy
|
|
78
|
+
of the others' secrets.
|
|
79
|
+
|
|
80
|
+
Until now two machines could only share an identity by sharing its private key —
|
|
81
|
+
`/backup` copies the whole thing — after which the relay refused the second
|
|
82
|
+
nickname, each message reached exactly one of them, and a peer verifying both
|
|
83
|
+
was shown the same fingerprint twice and told that was normal. That is replaced.
|
|
84
|
+
|
|
85
|
+
An identity is now an Ed25519 key that only ever signs. Each device has its own
|
|
86
|
+
message key, listed and signed by that identity. Adding a device grants it a
|
|
87
|
+
signed place on the list; it never receives the identity secret, so a stolen
|
|
88
|
+
phone is a stolen phone rather than a stolen identity, and only the device
|
|
89
|
+
holding the secret can add or remove.
|
|
90
|
+
|
|
91
|
+
`/room` also learned to say how the room is sending, and why.
|
|
92
|
+
|
|
93
|
+
### Added
|
|
94
|
+
|
|
95
|
+
- **`/device`: one identity, several devices.** A second device asks with
|
|
96
|
+
`/device request`, the device holding the identity key answers with
|
|
97
|
+
`/device add`, and the new one takes it with `/device accept`. Two short
|
|
98
|
+
strings, small enough for a QR code, and neither of them secret — a request is
|
|
99
|
+
a public key and a grant is a signed statement that goes to every peer anyway.
|
|
100
|
+
|
|
101
|
+
The identity secret never moves. A secondary can prove which identity it
|
|
102
|
+
belongs to and can publish that proof, but it cannot sign a new list, so
|
|
103
|
+
adding and removing stay with one device. Two costs come with that and are
|
|
104
|
+
worth knowing: losing that device means no more adding or removing, and a
|
|
105
|
+
secondary does not rotate its message key, because it could not re-sign the
|
|
106
|
+
list that names it.
|
|
107
|
+
|
|
108
|
+
`/device remove` signs a shorter list **and rotates the room**. A removed
|
|
109
|
+
device still holds every member's sender chain, and a chain ratchets forward —
|
|
110
|
+
dropping it from a list stops the relay delivering to it and does not stop it
|
|
111
|
+
reading. It keeps what it already received; that is what forward secrecy
|
|
112
|
+
means.
|
|
113
|
+
|
|
114
|
+
- **Verification follows the identity, not the device.** Once both sides can,
|
|
115
|
+
`/verify` compares identity keys, so adding or rotating a device no longer
|
|
116
|
+
invalidates a verification. The switch is symmetric — both sides make it
|
|
117
|
+
together — so a pair is never shown two different codes, and `/verify` says
|
|
118
|
+
which of the two it is showing. Verifications you already have are carried
|
|
119
|
+
across silently, and only when a signed list names the very key you compared
|
|
120
|
+
digits over.
|
|
121
|
+
|
|
122
|
+
- **Another of someone's devices is not "their key changed".** It still warns
|
|
123
|
+
the first time, because claiming an identity proves nothing on its own. When
|
|
124
|
+
the proof arrives the warning is answered out loud, and that key is quiet from
|
|
125
|
+
then on. Your own other device is recognised as yours: `/users` counts people
|
|
126
|
+
rather than connections, a line you sent from your phone is shown as yours,
|
|
127
|
+
and your own nickname in your own line does not notify you.
|
|
128
|
+
|
|
129
|
+
- **`/room` reports how the room is sending, and why.** One ciphertext for the
|
|
130
|
+
room, or one envelope per member — and when it is the expensive one, the
|
|
131
|
+
reason: an older hub, deniable mode, or the peers by name.
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Sending: one ciphertext to the room (sender keys), read by 4
|
|
135
|
+
Sending: 4 envelopes per message — carol is on a build without sender keys
|
|
136
|
+
Sending: 2 envelopes per message — this relay cannot fan out a room-addressed message
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
An older hub is reported ahead of older peers, because both can be true at
|
|
140
|
+
once and naming peers who are perfectly current sends you after the wrong
|
|
141
|
+
problem. P2P gets the same line for its own reasons: a mesh sends one frame
|
|
142
|
+
per peer either way, so there the saving is *encryptions*, and constant cover
|
|
143
|
+
is a reason to stay pairwise that the relay path does not have.
|
|
144
|
+
|
|
145
|
+
### Fixed
|
|
146
|
+
|
|
147
|
+
- **A second device no longer reads as an attack.** It arrives under the same
|
|
148
|
+
nickname with a key the trust record has never seen, which is the shape of a
|
|
149
|
+
man-in-the-middle and was reported as one.
|
|
150
|
+
|
|
151
|
+
- **Guarded key memory is released, not merely zeroed.** `KeyManager` zeroed its
|
|
152
|
+
secret keys on `destroy()` and left the pages `mlock`'d until the garbage
|
|
153
|
+
collector happened to run the finaliser. An operating system caps how much a
|
|
154
|
+
process may lock, and the cap is small on Linux and unlimited on macOS — so
|
|
155
|
+
the failure was invisible in development and landed as an abort in whatever
|
|
156
|
+
allocated next. The same pattern was fixed elsewhere in 2.12.0; this is the
|
|
157
|
+
rest of it in that file.
|
|
158
|
+
|
|
159
|
+
### Internal
|
|
160
|
+
|
|
161
|
+
- **The per-peer send loop is not being retired, and the plan that said it might
|
|
162
|
+
be was wrong.** It was written up as a compatibility shim that ages out once
|
|
163
|
+
everybody upgrades. It is not: it is the pairwise send path, and two of the
|
|
164
|
+
four things that need it need it permanently — `/deniable`, because
|
|
165
|
+
deniability is a property of the pairwise construction, and sender-key
|
|
166
|
+
distribution, because a distribution is authenticated by the envelope it
|
|
167
|
+
arrives in and the group path cannot bootstrap itself. Recorded in
|
|
168
|
+
`docs/design/sender-keys-on-relay.md`.
|
|
169
|
+
|
|
170
|
+
- **A design document for multi-device**, written from the code before any of
|
|
171
|
+
it moved, and kept as written with the decisions recorded in place. It is the
|
|
172
|
+
reason the arc could be built in eight landable steps.
|
|
173
|
+
|
|
174
|
+
- **One nickname may be held by several devices of one identity.** The relay
|
|
175
|
+
admits the second only if its JOIN carries a list signed by the identity the
|
|
176
|
+
name is already using and naming that JOIN's own key. No challenge is issued
|
|
177
|
+
and none is needed: replaying somebody else's list buys a seat in a room whose
|
|
178
|
+
messages you cannot read. The name is released when the last device leaves.
|
|
179
|
+
|
|
180
|
+
- **New capability `dl1`**, the first with no relay half — a device list travels
|
|
181
|
+
on the pairwise channel the relay already carries, so there is nothing for it
|
|
182
|
+
to agree to.
|
|
183
|
+
|
|
184
|
+
- **Multi-device is not coming to the mesh**, and the mesh now says so. A P2P
|
|
185
|
+
peer is keyed by nickname, which is exactly what two of your devices share, so
|
|
186
|
+
it is a different design. `/device`, `/create`, `/invite` and `/nick` explain
|
|
187
|
+
why they need a relay instead of guessing at a typo — `/device` used to
|
|
188
|
+
suggest `/voice`.
|
|
189
|
+
|
|
190
|
+
- Dependency bumps: `@noble/post-quantum` 0.7.0, `eslint` 10.8.1,
|
|
191
|
+
`globals` 17.11.0.
|
|
192
|
+
|
|
6
193
|
## 2.12.0
|
|
7
194
|
|
|
8
195
|
Sender keys now send. 2.11.0 shipped the half that reads a group message; this
|
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ forwarding, survives CGNAT).
|
|
|
54
54
|
| 🗂️ | **Encrypted local history** | Opt-in (passphrase only), Argon2id + XSalsa20-Poly1305, `/search` & `/export` |
|
|
55
55
|
| 🖼️ | **Image previews** | Received photos render right in the chat as colored half-blocks |
|
|
56
56
|
| 📎 | **Resumable transfers** | Lost chunks are re-requested; reconnects resume from where they stopped |
|
|
57
|
-
| 💬 | **Modern chat feel** |
|
|
57
|
+
| 💬 | **Modern chat feel** | Messages laid out as wrapped blocks with a coloured rule on your own, per-user emoji avatars, replies with quotes, `:fire:` → 🔥 |
|
|
58
58
|
| 🎞️ | **Animated UI** | Splash intro, reconnect spinner, live transfer bars (shimmer + ETA), a lock-closing handshake on connect, and a pulsing "new messages ↓" pill |
|
|
59
59
|
| 👻 | **Deniable & ephemeral** | Symmetric-crypto deniable mode; ephemeral messages _burn away_ char-by-char when they expire |
|
|
60
60
|
| 🔒 | **Private rooms** | `/create <room> <password>` — zero-knowledge: the password never leaves your machine (Argon2id → Ed25519 challenge-response) and room content gets an extra symmetric layer the relay can't fake its way into |
|
|
@@ -225,7 +225,7 @@ software was built for.
|
|
|
225
225
|
| `/leave [room]` | Leave a room; its buffer closes (the last room is protected) |
|
|
226
226
|
| `/create <room> <password>` | Create a **private room** 🔒 — see below |
|
|
227
227
|
| `/rooms` | List rooms (🔒 marks private ones) |
|
|
228
|
-
| `/room` | Current room
|
|
228
|
+
| `/room` | Current room, how it is sending it, and your buffer list |
|
|
229
229
|
| `/topic [text\|clear]` | Show or set the room topic — shown in the status bar and synced to whoever joins later |
|
|
230
230
|
| `/owner` | Room owner |
|
|
231
231
|
| `/kick` `/mute` `/ban` | Owner moderation — bound to the public key, so a rename does not undo a ban |
|
|
@@ -251,12 +251,13 @@ without verifying couldn't read a word. Share the password out-of-band.
|
|
|
251
251
|
|
|
252
252
|
| Command | Description |
|
|
253
253
|
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
254
|
-
| `/fingerprint [nick]` | Key fingerprint
|
|
255
|
-
| `/verify <nick>` | SAS code (~40-bit) + QR + key randomart for out-of-band verification |
|
|
254
|
+
| `/fingerprint [nick]` | Key fingerprint, the identity fingerprint when there is one, and a deterministic **randomart** picture of the key |
|
|
255
|
+
| `/verify <nick>` | SAS code (~40-bit) + QR + key randomart for out-of-band verification; says whether the code is over identity keys or device keys |
|
|
256
256
|
| `/verify-confirm <nick>` | Mark peer as verified |
|
|
257
257
|
| `/trust <nick>` / `/trustlist` | Accept new key / trust status |
|
|
258
258
|
| `/contacts [add\|remove\|all]` | Contact book — persistent aliases on trust records ("this fingerprint is João"); shows in `/users`, rides along in identity backups |
|
|
259
259
|
| `/backup [path]` | Encrypted backup of identity + verified peers (restore at startup) |
|
|
260
|
+
| `/device [list\|request\|add\|accept\|remove]` | Your devices under one identity. The identity key never leaves the device that holds it, so a second device is granted a signed place on the list rather than a copy of your identity. Removing one rotates the room, so nothing said afterwards reaches it |
|
|
260
261
|
| `/deniable [on\|off]` | Plausible-deniability mode |
|
|
261
262
|
| `/lock` / `/autolock <min\|off>` | Lock the screen behind the session passphrase — manually or after idle time (`autoLock` in config). Privacy for the "stepped away" moment; `/panic` is for the worst one |
|
|
262
263
|
| `/panic [yes]` | Duress wipe — securely erase all on-disk secrets (session, history, trust, keys) and exit |
|
|
@@ -301,13 +302,14 @@ A green **✓** next to a name marks a SAS-verified peer; a red **✗** flags a
|
|
|
301
302
|
| `/react <emoji>` | React to the last message — the emoji lands **on the message**, with a count when several people react |
|
|
302
303
|
| `/edit` `/delete` | Edit or delete your last message — the **original line is rewritten in place** (marked _(edited)_) or replaced by a tombstone, instead of a new line you have to mentally staple to it |
|
|
303
304
|
| `/pin` `/unpin` `/pins` | Pin messages |
|
|
304
|
-
| `/sound`
|
|
305
|
+
| `/sound` | Sound alerts on incoming messages |
|
|
306
|
+
| `/notify` | Desktop notifications — rate-limited, and muted for the session (with a line saying why) if the OS refuses them |
|
|
305
307
|
| `/dnd [on\|off\|mentions\|HH:MM-HH:MM]` | Do-not-disturb, mentions-only, or quiet hours |
|
|
306
308
|
| `/clear` | Clear the chat |
|
|
307
309
|
|
|
308
310
|
</details>
|
|
309
311
|
|
|
310
|
-
Typing `:fire:` anywhere becomes 🔥 (Tab autocompletes shortcodes). **Ctrl+K** opens a fuzzy command palette, **Ctrl+E** an emoji picker. PageUp/PageDown scroll the history. **
|
|
312
|
+
Typing `:fire:` anywhere becomes 🔥 (Tab autocompletes shortcodes). **Ctrl+K** opens a fuzzy command palette, **Ctrl+E** an emoji picker. PageUp/PageDown scroll the history. **Shift+Enter** inserts a newline for multi-line messages — CipherMesh negotiates the kitty keyboard protocol / `modifyOtherKeys` on startup so the terminal can tell it apart from Enter, and **Alt+Enter** and **Ctrl+J** do the same on terminals that support neither (`CIPHERMESH_LEGACY_KEYS=1` turns the negotiation off). Enter sends. Pasting multi-line text (code included) keeps its line breaks — paste, check, Enter. Markdown works: \`code\`, **bold**, _italic_, links, plus fenced \`\`\` code blocks and | tables |. Received images preview inline (half-blocks) and render full-res with `/img` on kitty/iTerm2. Messages are laid out as blocks — a header naming the sender, then the text wrapped well short of the window and indented under it, with a coloured rule down the left of your own, of DMs and of anything that mentions you. Day separators and message grouping keep the log clean.
|
|
311
313
|
|
|
312
314
|
### First run & config file
|
|
313
315
|
|
package/README.pt-BR.md
CHANGED
|
@@ -54,7 +54,7 @@ forwarding, imune a CGNAT).
|
|
|
54
54
|
| 🗂️ | **Histórico local cifrado** | Opt-in (só com passphrase), Argon2id + XSalsa20-Poly1305, `/search` e `/export` |
|
|
55
55
|
| 🖼️ | **Preview de imagens** | Fotos recebidas renderizam no chat em half-blocks coloridos |
|
|
56
56
|
| 📎 | **Transferências com resume** | Chunks perdidos são re-pedidos; reconexão retoma de onde parou |
|
|
57
|
-
| 💬 | **Cara de app moderno** |
|
|
57
|
+
| 💬 | **Cara de app moderno** | Mensagens em blocos com quebra de linha e uma barra colorida nas suas, avatar de emoji por usuário, reply com citação, `:fire:` → 🔥 |
|
|
58
58
|
| 🎞️ | **Interface animada** | Splash na abertura, spinner de reconexão, barra de transferência viva (shimmer + ETA), cadeado fechando no handshake e um selo pulsante "novas mensagens ↓" |
|
|
59
59
|
| 👻 | **Deniable e efêmeras** | Modo de negação plausível (crypto simétrica); mensagens efêmeras _queimam_ caractere a caractere ao expirar |
|
|
60
60
|
| 🔒 | **Salas privadas** | `/create <sala> <senha>` — zero-knowledge: a senha nunca sai da sua máquina (Argon2id → challenge-response Ed25519) e o conteúdo da sala ganha uma camada simétrica extra que nem um relay malicioso atravessa |
|
|
@@ -226,7 +226,7 @@ aquela para a qual este software foi feito.
|
|
|
226
226
|
| `/leave [sala]` | Sai de uma sala; o buffer fecha (a última sala é protegida) |
|
|
227
227
|
| `/create <sala> <senha>` | Cria uma **sala privada** 🔒 — veja abaixo |
|
|
228
228
|
| `/rooms` | Lista salas (🔒 marca as privadas) |
|
|
229
|
-
| `/room` | Sala atual
|
|
229
|
+
| `/room` | Sala atual, como está enviando, e sua lista de buffers |
|
|
230
230
|
| `/topic [texto\|clear]` | Mostra ou define o assunto da sala — aparece na barra de status e é sincronizado para quem entra depois |
|
|
231
231
|
| `/owner` | Dono da sala |
|
|
232
232
|
| `/kick` `/mute` `/ban` | Moderação (dono da sala) — presa à chave pública, então trocar de apelido não desfaz um ban |
|
|
@@ -252,10 +252,11 @@ sem verificar não leria uma palavra. Combine a senha por outro canal.
|
|
|
252
252
|
|
|
253
253
|
| Comando | Descrição |
|
|
254
254
|
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
255
|
-
| `/fingerprint [nick]` | Fingerprint
|
|
256
|
-
| `/verify <nick>` | Código SAS (~40 bits) + QR + randomart da chave para verificar |
|
|
255
|
+
| `/fingerprint [nick]` | Fingerprint, o fingerprint de identidade quando existe, e um **randomart** determinístico da chave |
|
|
256
|
+
| `/verify <nick>` | Código SAS (~40 bits) + QR + randomart da chave para verificar; diz se o código é sobre chaves de identidade ou de dispositivo |
|
|
257
257
|
| `/verify-confirm <nick>` | Marca o peer como verificado |
|
|
258
258
|
| `/backup [caminho]` | Backup cifrado da identidade + peers verificados (restaura no startup) |
|
|
259
|
+
| `/device [list\|request\|add\|accept\|remove]` | Seus dispositivos sob uma identidade. A chave de identidade nunca sai do dispositivo que a guarda: um segundo dispositivo recebe um lugar assinado na lista, não uma cópia da identidade. Remover um rotaciona a sala, então nada dito depois chega até ele |
|
|
259
260
|
| `/trust <nick>` / `/trustlist` | Aceita chave nova / status de confiança |
|
|
260
261
|
| `/contacts [add\|remove\|all]` | Agenda — apelidos persistentes nos registros de confiança ("esse fingerprint é o João"); aparece no `/users` e viaja no backup de identidade |
|
|
261
262
|
| `/deniable [on\|off]` | Modo de negação plausível |
|
|
@@ -301,14 +302,15 @@ Um **✓** verde ao lado de um nome indica um peer verificado por SAS; um **✗*
|
|
|
301
302
|
| `/react <emoji>` | Reage à última mensagem — o emoji aparece **na própria mensagem**, com contagem quando várias pessoas reagem |
|
|
302
303
|
| `/edit` `/delete` | Edita ou apaga sua última mensagem — a **linha original é reescrita no lugar** (marcada _(edited)_) ou vira uma lápide, em vez de uma linha nova que você precisa juntar mentalmente à original |
|
|
303
304
|
| `/pin` `/unpin` `/pins` | Fixa mensagens |
|
|
304
|
-
| `/sound`
|
|
305
|
+
| `/sound` | Alertas sonoros ao receber mensagens |
|
|
306
|
+
| `/notify` | Notificações de desktop — com limite de frequência, e silenciadas na sessão (com uma linha a dizer porquê) se o SO as recusar |
|
|
305
307
|
| `/dnd [on\|off\|mentions\|HH:MM-HH:MM]` | Não perturbe, só menções, ou horário silencioso |
|
|
306
308
|
| `/clear` | Limpa o chat |
|
|
307
309
|
|
|
308
310
|
</details>
|
|
309
311
|
|
|
310
312
|
Digitar `:fire:` em qualquer lugar vira 🔥 (Tab autocompleta shortcodes).
|
|
311
|
-
**Ctrl+K** abre uma paleta de comandos fuzzy, **Ctrl+E** um seletor de emoji. PageUp/PageDown rolam o histórico. **
|
|
313
|
+
**Ctrl+K** abre uma paleta de comandos fuzzy, **Ctrl+E** um seletor de emoji. PageUp/PageDown rolam o histórico. **Shift+Enter** insere uma nova linha para mensagens de várias linhas — o CipherMesh negocia o kitty keyboard protocol / `modifyOtherKeys` no arranque para o terminal conseguir distingui-lo do Enter, e **Alt+Enter** e **Ctrl+J** fazem o mesmo em terminais que não suportam nenhum dos dois (`CIPHERMESH_LEGACY_KEYS=1` desliga a negociação). Enter envia. Colar texto multi-linha (código incluso) preserva as quebras — cola, confere, Enter. Markdown funciona: \`código\`, **negrito**, _itálico_, links, além de blocos de código \`\`\` e | tabelas |. Imagens recebidas têm preview inline (half-blocks) e renderizam em alta resolução com `/img` no kitty/iTerm2. As mensagens são desenhadas em blocos — um cabeçalho com o remetente e, por baixo, o texto quebrado bem antes da largura da janela, com uma barra colorida à esquerda nas suas, nas DMs e em tudo o que te mencione. Separadores de dia e agrupamento de mensagens deixam o log limpo.
|
|
312
314
|
|
|
313
315
|
### Primeira execução & arquivo de config
|
|
314
316
|
|