@xmtp/convos-cli 0.1.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/LICENSE +21 -0
- package/README.md +572 -0
- package/bin/dev.js +4 -0
- package/bin/run.js +4 -0
- package/dist/baseCommand.d.ts +46 -0
- package/dist/baseCommand.js +171 -0
- package/dist/commands/agent/serve.d.ts +67 -0
- package/dist/commands/agent/serve.js +662 -0
- package/dist/commands/conversation/add-members.d.ts +19 -0
- package/dist/commands/conversation/add-members.js +39 -0
- package/dist/commands/conversation/consent-state.d.ts +18 -0
- package/dist/commands/conversation/consent-state.js +24 -0
- package/dist/commands/conversation/download-attachment.d.ts +28 -0
- package/dist/commands/conversation/download-attachment.js +164 -0
- package/dist/commands/conversation/explode.d.ts +24 -0
- package/dist/commands/conversation/explode.js +156 -0
- package/dist/commands/conversation/info.d.ts +22 -0
- package/dist/commands/conversation/info.js +79 -0
- package/dist/commands/conversation/invite.d.ts +26 -0
- package/dist/commands/conversation/invite.js +137 -0
- package/dist/commands/conversation/lock.d.ts +24 -0
- package/dist/commands/conversation/lock.js +98 -0
- package/dist/commands/conversation/members.d.ts +22 -0
- package/dist/commands/conversation/members.js +39 -0
- package/dist/commands/conversation/messages.d.ts +31 -0
- package/dist/commands/conversation/messages.js +141 -0
- package/dist/commands/conversation/permissions.d.ts +18 -0
- package/dist/commands/conversation/permissions.js +33 -0
- package/dist/commands/conversation/profiles.d.ts +22 -0
- package/dist/commands/conversation/profiles.js +80 -0
- package/dist/commands/conversation/remove-members.d.ts +19 -0
- package/dist/commands/conversation/remove-members.js +36 -0
- package/dist/commands/conversation/send-attachment.d.ts +30 -0
- package/dist/commands/conversation/send-attachment.js +187 -0
- package/dist/commands/conversation/send-reaction.d.ts +21 -0
- package/dist/commands/conversation/send-reaction.js +38 -0
- package/dist/commands/conversation/send-remote-attachment.d.ts +30 -0
- package/dist/commands/conversation/send-remote-attachment.js +96 -0
- package/dist/commands/conversation/send-reply.d.ts +32 -0
- package/dist/commands/conversation/send-reply.js +170 -0
- package/dist/commands/conversation/send-text.d.ts +24 -0
- package/dist/commands/conversation/send-text.js +64 -0
- package/dist/commands/conversation/stream.d.ts +24 -0
- package/dist/commands/conversation/stream.js +81 -0
- package/dist/commands/conversation/sync.d.ts +18 -0
- package/dist/commands/conversation/sync.js +25 -0
- package/dist/commands/conversation/update-consent.d.ts +19 -0
- package/dist/commands/conversation/update-consent.js +35 -0
- package/dist/commands/conversation/update-description.d.ts +19 -0
- package/dist/commands/conversation/update-description.js +28 -0
- package/dist/commands/conversation/update-name.d.ts +19 -0
- package/dist/commands/conversation/update-name.js +29 -0
- package/dist/commands/conversation/update-profile.d.ts +24 -0
- package/dist/commands/conversation/update-profile.js +97 -0
- package/dist/commands/conversations/create.d.ts +26 -0
- package/dist/commands/conversations/create.js +165 -0
- package/dist/commands/conversations/join.d.ts +27 -0
- package/dist/commands/conversations/join.js +232 -0
- package/dist/commands/conversations/list.d.ts +20 -0
- package/dist/commands/conversations/list.js +109 -0
- package/dist/commands/conversations/process-join-requests.d.ts +26 -0
- package/dist/commands/conversations/process-join-requests.js +261 -0
- package/dist/commands/conversations/sync.d.ts +19 -0
- package/dist/commands/conversations/sync.js +50 -0
- package/dist/commands/identity/create.d.ts +21 -0
- package/dist/commands/identity/create.js +56 -0
- package/dist/commands/identity/info.d.ts +22 -0
- package/dist/commands/identity/info.js +63 -0
- package/dist/commands/identity/list.d.ts +19 -0
- package/dist/commands/identity/list.js +59 -0
- package/dist/commands/identity/remove.d.ts +23 -0
- package/dist/commands/identity/remove.js +51 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.js +91 -0
- package/dist/commands/reset.d.ts +17 -0
- package/dist/commands/reset.js +93 -0
- package/dist/help.d.ts +4 -0
- package/dist/help.js +31 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +15 -0
- package/dist/utils/client.d.ts +8 -0
- package/dist/utils/client.js +58 -0
- package/dist/utils/config.d.ts +15 -0
- package/dist/utils/config.js +1 -0
- package/dist/utils/identities.d.ts +49 -0
- package/dist/utils/identities.js +92 -0
- package/dist/utils/invite.d.ts +70 -0
- package/dist/utils/invite.js +339 -0
- package/dist/utils/metadata.d.ts +39 -0
- package/dist/utils/metadata.js +180 -0
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.js +42 -0
- package/dist/utils/random.d.ts +5 -0
- package/dist/utils/random.js +19 -0
- package/dist/utils/upload.d.ts +14 -0
- package/dist/utils/upload.js +51 -0
- package/dist/utils/xmtp.d.ts +45 -0
- package/dist/utils/xmtp.js +298 -0
- package/oclif.manifest.json +5562 -0
- package/package.json +124 -0
- package/skills/convos-cli/SKILL.md +588 -0
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: convos-cli
|
|
3
|
+
description: Use when working with Convos messaging - privacy-focused ephemeral messaging with per-conversation identities, invites, profiles, and group management via the convos CLI tool
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Convos CLI
|
|
7
|
+
|
|
8
|
+
The Convos CLI (`convos`) is a command-line tool for privacy-focused ephemeral messaging built on [XMTP](https://xmtp.org). Unlike standard XMTP, Convos creates a **unique identity per conversation** so conversations cannot be linked or correlated.
|
|
9
|
+
|
|
10
|
+
Key differences from standard XMTP:
|
|
11
|
+
|
|
12
|
+
- **Per-conversation identities**: Each conversation gets its own wallet, inbox, and database
|
|
13
|
+
- **No global wallet key**: Identities are created automatically when creating/joining conversations
|
|
14
|
+
- **Invite system**: Serverless QR code + URL invites for joining conversations
|
|
15
|
+
- **Per-conversation profiles**: Different display name and avatar in each conversation
|
|
16
|
+
- **Explode**: Permanently destroy a conversation and all cryptographic keys
|
|
17
|
+
- **Lock**: Prevent new members from being added
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
### Initialize Configuration
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# generate config and save to default path (~/.convos/.env)
|
|
25
|
+
convos init
|
|
26
|
+
|
|
27
|
+
# output config to console instead of writing to file
|
|
28
|
+
convos init --stdout
|
|
29
|
+
|
|
30
|
+
# initialize for production environment
|
|
31
|
+
convos init --env production
|
|
32
|
+
|
|
33
|
+
# overwrite existing config
|
|
34
|
+
convos init --force
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This creates a `.env` file with:
|
|
38
|
+
|
|
39
|
+
- `CONVOS_ENV` - Network environment (local, dev, production)
|
|
40
|
+
- `CONVOS_UPLOAD_PROVIDER` - Upload provider for attachments (e.g., `pinata`)
|
|
41
|
+
- `CONVOS_UPLOAD_PROVIDER_TOKEN` - Authentication token for upload provider
|
|
42
|
+
- `CONVOS_UPLOAD_PROVIDER_GATEWAY` - Custom gateway URL for upload provider
|
|
43
|
+
|
|
44
|
+
**Note:** Unlike standard XMTP, there is no global wallet key. Each conversation creates its own identity stored in `~/.convos/identities/`.
|
|
45
|
+
|
|
46
|
+
### Configuration Loading Priority
|
|
47
|
+
|
|
48
|
+
1. CLI flags (highest priority)
|
|
49
|
+
2. Explicit `--env-file <path>`
|
|
50
|
+
3. `.env` in the current working directory
|
|
51
|
+
4. `~/.convos/.env` (global default)
|
|
52
|
+
|
|
53
|
+
## Command Structure
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
convos [TOPIC] [COMMAND] [ARGUMENTS] [FLAGS]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Topics
|
|
60
|
+
|
|
61
|
+
| Topic | Purpose |
|
|
62
|
+
| ----- | ------- |
|
|
63
|
+
| `agent` | Agent mode — long-running sessions with streaming I/O |
|
|
64
|
+
| `identity` | Manage per-conversation identities (inboxes) |
|
|
65
|
+
| `conversations` | List, create, join, and stream conversations |
|
|
66
|
+
| `conversation` | Interact with a specific conversation |
|
|
67
|
+
|
|
68
|
+
### Standalone Commands
|
|
69
|
+
|
|
70
|
+
| Command | Purpose |
|
|
71
|
+
| ------- | ------- |
|
|
72
|
+
| `init` | Initialize configuration and directory structure |
|
|
73
|
+
| `reset` | Delete all identities and conversation data (preserves .env) |
|
|
74
|
+
|
|
75
|
+
## Output Modes
|
|
76
|
+
|
|
77
|
+
All commands support `--json` for machine-readable JSON output:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
convos conversations list --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use `--verbose` to see detailed client initialization logs. When combined with `--json`, verbose output goes to stderr:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
convos identity info <id> --verbose
|
|
87
|
+
convos conversations list --json --verbose 2>/dev/null
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Common Workflows
|
|
91
|
+
|
|
92
|
+
### Create a Conversation
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# create a conversation (auto-creates a per-conversation identity)
|
|
96
|
+
convos conversations create --name "My Group" --profile-name "Alice"
|
|
97
|
+
|
|
98
|
+
# create with admin-only permissions
|
|
99
|
+
convos conversations create --name "Announcement Channel" --permissions admin-only
|
|
100
|
+
|
|
101
|
+
# create and capture the conversation ID
|
|
102
|
+
CONV_ID=$(convos conversations create --name "Test" --json | jq -r '.conversationId')
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Send Messages
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# send a text message
|
|
109
|
+
convos conversation send-text <conversation-id> "Hello, world!"
|
|
110
|
+
|
|
111
|
+
# send a reaction
|
|
112
|
+
convos conversation send-reaction <conversation-id> <message-id> add "👍"
|
|
113
|
+
# remove a reaction
|
|
114
|
+
convos conversation send-reaction <conversation-id> <message-id> remove "👍"
|
|
115
|
+
|
|
116
|
+
# send a reply referencing another message
|
|
117
|
+
convos conversation send-reply <conversation-id> <message-id> "Replying to you"
|
|
118
|
+
|
|
119
|
+
# reply with a photo
|
|
120
|
+
convos conversation send-reply <conversation-id> <message-id> --file ./photo.jpg
|
|
121
|
+
|
|
122
|
+
# reply with a large file (auto-uploaded via provider)
|
|
123
|
+
convos conversation send-reply <conversation-id> <message-id> --file ./video.mp4
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Send Attachments
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# send a photo (small files ≤1MB sent inline, large files auto-uploaded via provider)
|
|
130
|
+
convos conversation send-attachment <conversation-id> ./photo.jpg
|
|
131
|
+
|
|
132
|
+
# force remote upload even for small files
|
|
133
|
+
convos conversation send-attachment <conversation-id> ./photo.jpg --remote
|
|
134
|
+
|
|
135
|
+
# override MIME type
|
|
136
|
+
convos conversation send-attachment <conversation-id> ./file.bin --mime-type image/png
|
|
137
|
+
|
|
138
|
+
# use upload provider via flags (no .env needed)
|
|
139
|
+
convos conversation send-attachment <conversation-id> ./photo.jpg \
|
|
140
|
+
--upload-provider pinata --upload-provider-token <jwt>
|
|
141
|
+
|
|
142
|
+
# encrypt only — outputs encrypted file + decryption keys for manual upload
|
|
143
|
+
convos conversation send-attachment <conversation-id> ./photo.jpg --encrypt
|
|
144
|
+
|
|
145
|
+
# send a pre-uploaded encrypted file with decryption keys
|
|
146
|
+
convos conversation send-remote-attachment <conversation-id> <url> \
|
|
147
|
+
--content-digest <hex> --secret <base64> --salt <base64> \
|
|
148
|
+
--nonce <base64> --content-length <bytes> --filename photo.jpg
|
|
149
|
+
|
|
150
|
+
# download an attachment (handles both inline and remote transparently)
|
|
151
|
+
convos conversation download-attachment <conversation-id> <message-id>
|
|
152
|
+
|
|
153
|
+
# download to a specific path
|
|
154
|
+
convos conversation download-attachment <conversation-id> <message-id> --output ./photo.jpg
|
|
155
|
+
|
|
156
|
+
# save encrypted payload without decrypting
|
|
157
|
+
convos conversation download-attachment <conversation-id> <message-id> --raw
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
To enable automatic upload for large files, configure a provider in your `.env`:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
CONVOS_UPLOAD_PROVIDER=pinata
|
|
164
|
+
CONVOS_UPLOAD_PROVIDER_TOKEN=<your-pinata-jwt>
|
|
165
|
+
# Optional: custom gateway URL
|
|
166
|
+
CONVOS_UPLOAD_PROVIDER_GATEWAY=https://your-gateway.mypinata.cloud
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Supported upload providers: `pinata`
|
|
170
|
+
|
|
171
|
+
### Read Messages
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# list messages (default: descending order)
|
|
175
|
+
convos conversation messages <conversation-id>
|
|
176
|
+
# sync from network and limit results
|
|
177
|
+
convos conversation messages <conversation-id> --sync --limit 10
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Stream Messages in Real-Time
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# stream messages from a single conversation
|
|
184
|
+
convos conversation stream <conversation-id>
|
|
185
|
+
# stop after 60 seconds
|
|
186
|
+
convos conversation stream <conversation-id> --timeout 60
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### List Conversations
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# list all conversations across all identities
|
|
193
|
+
convos conversations list
|
|
194
|
+
# sync from network before listing
|
|
195
|
+
convos conversations list --sync
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Invite System
|
|
199
|
+
|
|
200
|
+
Convos uses a serverless invite system. The creator generates a cryptographic invite URL; the person joining must open the URL in the Convos app (or scan the QR code); then the creator processes the join request to add them to the group.
|
|
201
|
+
|
|
202
|
+
**Important: Adding someone to a conversation is a multi-step process:**
|
|
203
|
+
|
|
204
|
+
1. **Generate an invite** (creator side) — produces a URL and QR code
|
|
205
|
+
2. **Person opens the invite URL in Convos or scans the QR code** — this sends a join request to the creator via DM
|
|
206
|
+
3. **Creator processes the join request** — this validates the request and adds the person to the group
|
|
207
|
+
|
|
208
|
+
The creator must process join requests *after* the person has opened/scanned the invite. If you don't know when that will happen, use `--watch` with a timeout to stream and process requests as they arrive.
|
|
209
|
+
|
|
210
|
+
#### Create an Invite
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# generate invite — displays QR code in terminal
|
|
214
|
+
convos conversation invite <conversation-id>
|
|
215
|
+
|
|
216
|
+
# generate invite with 1-hour expiry
|
|
217
|
+
convos conversation invite <conversation-id> --expires-in 3600
|
|
218
|
+
|
|
219
|
+
# single-use invite
|
|
220
|
+
convos conversation invite <conversation-id> --single-use
|
|
221
|
+
|
|
222
|
+
# JSON output (suppresses QR code)
|
|
223
|
+
convos conversation invite <conversation-id> --json
|
|
224
|
+
|
|
225
|
+
# capture invite URL for scripting
|
|
226
|
+
INVITE_URL=$(convos conversation invite <conversation-id> --json | jq -r '.url')
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Person Joins via Invite
|
|
230
|
+
|
|
231
|
+
The person being invited must open the invite URL in the Convos app or scan the QR code with Convos. This can be done:
|
|
232
|
+
|
|
233
|
+
- **On iOS**: Open the URL in Safari (redirects to Convos app) or scan the QR code from within the app
|
|
234
|
+
- **Via CLI**: Use `convos conversations join`
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# join using a raw invite slug
|
|
238
|
+
convos conversations join <invite-slug>
|
|
239
|
+
|
|
240
|
+
# join using a full invite URL
|
|
241
|
+
convos conversations join "https://dev.convos.org/v2?i=<slug>"
|
|
242
|
+
|
|
243
|
+
# join with a display name
|
|
244
|
+
convos conversations join <slug> --profile-name "Bob"
|
|
245
|
+
|
|
246
|
+
# send join request without waiting for acceptance
|
|
247
|
+
convos conversations join <slug> --no-wait
|
|
248
|
+
|
|
249
|
+
# wait up to 2 minutes for acceptance
|
|
250
|
+
convos conversations join <slug> --timeout 120
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### Process Join Requests (Creator Side)
|
|
254
|
+
|
|
255
|
+
After the person has opened/scanned the invite, the creator must process the join request:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# process all pending join requests (use when you know the invite has already been opened)
|
|
259
|
+
convos conversations process-join-requests
|
|
260
|
+
|
|
261
|
+
# process for a specific conversation only
|
|
262
|
+
convos conversations process-join-requests --conversation <id>
|
|
263
|
+
|
|
264
|
+
# watch for join requests with a timeout (use when you don't know when the invite will be opened)
|
|
265
|
+
convos conversations process-join-requests --watch --conversation <id>
|
|
266
|
+
# note: use ctrl-c or a timeout to stop watching
|
|
267
|
+
|
|
268
|
+
# continuously watch for all join requests (keep running in background)
|
|
269
|
+
convos conversations process-join-requests --watch
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Per-Conversation Profiles
|
|
273
|
+
|
|
274
|
+
Each conversation has independent profiles — you can have a different name and avatar in each.
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# set display name
|
|
278
|
+
convos conversation update-profile <conversation-id> --name "Alice"
|
|
279
|
+
|
|
280
|
+
# set name and avatar
|
|
281
|
+
convos conversation update-profile <conversation-id> --name "Alice" --image "https://example.com/avatar.jpg"
|
|
282
|
+
|
|
283
|
+
# go anonymous (clear profile)
|
|
284
|
+
convos conversation update-profile <conversation-id> --name "" --image ""
|
|
285
|
+
|
|
286
|
+
# view all member profiles
|
|
287
|
+
convos conversation profiles <conversation-id>
|
|
288
|
+
convos conversation profiles <conversation-id> --json
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Identity Management
|
|
292
|
+
|
|
293
|
+
Identities are created automatically when creating/joining conversations, but you can manage them directly.
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# list all identities
|
|
297
|
+
convos identity list
|
|
298
|
+
|
|
299
|
+
# create an identity manually
|
|
300
|
+
convos identity create --label "Work Chat" --profile-name "Alice"
|
|
301
|
+
|
|
302
|
+
# view identity details (connects to XMTP to show inbox ID)
|
|
303
|
+
convos identity info <identity-id>
|
|
304
|
+
|
|
305
|
+
# remove an identity (destroys all keys — irreversible)
|
|
306
|
+
convos identity remove <identity-id> --force
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Reset All Data
|
|
310
|
+
|
|
311
|
+
Delete all identities and conversation data. The `.env` configuration is preserved.
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
# reset with confirmation prompt
|
|
315
|
+
convos reset
|
|
316
|
+
|
|
317
|
+
# reset without confirmation
|
|
318
|
+
convos reset --force
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Group Management
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# view members
|
|
325
|
+
convos conversation members <conversation-id>
|
|
326
|
+
|
|
327
|
+
# add members by inbox ID
|
|
328
|
+
convos conversation add-members <conversation-id> <inbox-id>
|
|
329
|
+
|
|
330
|
+
# remove members
|
|
331
|
+
convos conversation remove-members <conversation-id> <inbox-id>
|
|
332
|
+
|
|
333
|
+
# update group name
|
|
334
|
+
convos conversation update-name <conversation-id> "New Name"
|
|
335
|
+
|
|
336
|
+
# update group description
|
|
337
|
+
convos conversation update-description <conversation-id> "New description"
|
|
338
|
+
|
|
339
|
+
# view permissions
|
|
340
|
+
convos conversation permissions <conversation-id>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Lock a Conversation
|
|
344
|
+
|
|
345
|
+
Prevent new members from joining by setting the addMember permission to deny. This also invalidates all existing invites. Only super admins can lock/unlock.
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# lock
|
|
349
|
+
convos conversation lock <conversation-id>
|
|
350
|
+
|
|
351
|
+
# unlock (previously shared invites remain invalid — generate new ones)
|
|
352
|
+
convos conversation lock <conversation-id> --unlock
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Explode a Conversation
|
|
356
|
+
|
|
357
|
+
Permanently destroy a conversation and all its cryptographic keys. Sends an ExplodeSettings notification to all members (so iOS and other clients can trigger their cleanup), updates group metadata with the expiration timestamp, removes all members, then destroys the local identity. **Irreversible.**
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# explode immediately
|
|
361
|
+
convos conversation explode <conversation-id> --force
|
|
362
|
+
|
|
363
|
+
# schedule explosion for a future date (ISO8601)
|
|
364
|
+
convos conversation explode <conversation-id> --scheduled "2025-03-01T00:00:00Z"
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
When scheduled, the ExplodeSettings message is sent with a future `expiresAt` date. Members are notified but not removed — clients handle cleanup when the time arrives. When immediate (no `--scheduled`), members are removed and the local identity is destroyed right away.
|
|
368
|
+
|
|
369
|
+
### Sync Data from Network
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
# sync conversation list
|
|
373
|
+
convos conversations sync
|
|
374
|
+
|
|
375
|
+
# sync a single conversation
|
|
376
|
+
convos conversation sync <conversation-id>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Agent Mode
|
|
380
|
+
|
|
381
|
+
The `agent serve` command runs a long-running process that combines conversation creation, message streaming, join request processing, and stdin command handling — ideal for AI agents and bots.
|
|
382
|
+
|
|
383
|
+
### Quick Start (Agent)
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
# create a new conversation and start serving
|
|
387
|
+
convos agent serve --name "My Bot" --profile-name "Assistant"
|
|
388
|
+
|
|
389
|
+
# attach to an existing conversation
|
|
390
|
+
convos agent serve <conversation-id>
|
|
391
|
+
|
|
392
|
+
# create with admin-only permissions
|
|
393
|
+
convos agent serve --name "Agent" --permissions admin-only
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Protocol
|
|
397
|
+
|
|
398
|
+
The agent uses an **ndjson** (newline-delimited JSON) protocol:
|
|
399
|
+
|
|
400
|
+
- **stdout**: Events (one JSON object per line)
|
|
401
|
+
- **stdin**: Commands (one JSON object per line)
|
|
402
|
+
- **stderr**: QR code + diagnostic logs
|
|
403
|
+
|
|
404
|
+
#### Events (stdout)
|
|
405
|
+
|
|
406
|
+
| Event | Description | Key Fields |
|
|
407
|
+
| ----- | ----------- | ---------- |
|
|
408
|
+
| `ready` | Session started | `conversationId`, `inviteUrl`, `inboxId` |
|
|
409
|
+
| `message` | New message received | `id`, `senderInboxId`, `content`, `contentType`, `sentAt` |
|
|
410
|
+
| `member_joined` | Member joined via invite | `inboxId`, `conversationId` |
|
|
411
|
+
| `sent` | Message sent confirmation | `id`, `text`, `replyTo` (optional) |
|
|
412
|
+
| `error` | Error occurred | `message` |
|
|
413
|
+
|
|
414
|
+
#### Commands (stdin)
|
|
415
|
+
|
|
416
|
+
```jsonl
|
|
417
|
+
{"type":"send","text":"Hello, world!"}
|
|
418
|
+
{"type":"send","text":"Replying to you","replyTo":"<message-id>"}
|
|
419
|
+
{"type":"react","messageId":"<message-id>","emoji":"👍"}
|
|
420
|
+
{"type":"react","messageId":"<message-id>","emoji":"👍","action":"remove"}
|
|
421
|
+
{"type":"attach","file":"./photo.jpg"}
|
|
422
|
+
{"type":"attach","file":"./photo.jpg","replyTo":"<message-id>"}
|
|
423
|
+
{"type":"attach","file":"./photo.jpg","mimeType":"image/jpeg"}
|
|
424
|
+
{"type":"remote-attach","url":"https://...","contentDigest":"<hex>","secret":"<base64>","salt":"<base64>","nonce":"<base64>","contentLength":12345,"filename":"photo.jpg"}
|
|
425
|
+
{"type":"stop"}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
| Command | Required Fields | Optional Fields |
|
|
429
|
+
| ------- | --------------- | --------------- |
|
|
430
|
+
| `send` | `text` | `replyTo` |
|
|
431
|
+
| `react` | `messageId`, `emoji` | `action` (`add`/`remove`, default: `add`) |
|
|
432
|
+
| `attach` | `file` (local path) | `mimeType`, `replyTo` |
|
|
433
|
+
| `remote-attach` | `url`, `contentDigest`, `secret`, `salt`, `nonce`, `contentLength` | `filename`, `scheme` |
|
|
434
|
+
| `stop` | — | — |
|
|
435
|
+
|
|
436
|
+
Small attachments (≤1MB) are sent inline. Larger files are auto-encrypted and uploaded via the configured upload provider (e.g., Pinata).
|
|
437
|
+
|
|
438
|
+
### How It Works
|
|
439
|
+
|
|
440
|
+
When started, `agent serve`:
|
|
441
|
+
|
|
442
|
+
1. **Creates or attaches** to a conversation
|
|
443
|
+
2. **Displays QR code** invite on stderr (so users can scan and join)
|
|
444
|
+
3. **Emits `ready` event** with conversation ID, invite URL, and identity info
|
|
445
|
+
4. **Processes pending join requests** from before the agent started
|
|
446
|
+
5. **Streams messages** — emits `message` events as they arrive in real-time
|
|
447
|
+
6. **Streams DM join requests** — automatically adds new members and emits `member_joined`
|
|
448
|
+
7. **Reads stdin** — accepts `send` and `stop` commands
|
|
449
|
+
|
|
450
|
+
All of these run concurrently. The agent stays alive until `SIGINT`, `SIGTERM`, stdin close, or a `stop` command.
|
|
451
|
+
|
|
452
|
+
### Example: Agent Integration
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
# Start the agent, pipe commands in, read events out
|
|
456
|
+
convos agent serve --name "Bot" --profile-name "AI Assistant" | while IFS= read -r event; do
|
|
457
|
+
type=$(echo "$event" | jq -r '.event')
|
|
458
|
+
case "$type" in
|
|
459
|
+
ready)
|
|
460
|
+
echo "Bot ready! Invite URL: $(echo "$event" | jq -r '.inviteUrl')" >&2
|
|
461
|
+
;;
|
|
462
|
+
message)
|
|
463
|
+
content=$(echo "$event" | jq -r '.content')
|
|
464
|
+
echo "Received: $content" >&2
|
|
465
|
+
# Send a reply (write JSON command to agent's stdin)
|
|
466
|
+
msg_id=$(echo "$event" | jq -r '.id')
|
|
467
|
+
echo "{\"type\":\"send\",\"text\":\"You said: $content\",\"replyTo\":\"$msg_id\"}"
|
|
468
|
+
;;
|
|
469
|
+
member_joined)
|
|
470
|
+
inbox=$(echo "$event" | jq -r '.inboxId')
|
|
471
|
+
echo "New member: $inbox" >&2
|
|
472
|
+
echo "{\"type\":\"send\",\"text\":\"Welcome!\"}"
|
|
473
|
+
;;
|
|
474
|
+
esac
|
|
475
|
+
done
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Agent Flags
|
|
479
|
+
|
|
480
|
+
| Flag | Description |
|
|
481
|
+
| ---- | ----------- |
|
|
482
|
+
| `--name` | Conversation name (when creating new) |
|
|
483
|
+
| `--description` | Conversation description (when creating new) |
|
|
484
|
+
| `--permissions` | `all-members` or `admin-only` (when creating new) |
|
|
485
|
+
| `--profile-name` | Display name for this conversation |
|
|
486
|
+
| `--identity` | Use an existing unlinked identity |
|
|
487
|
+
| `--label` | Local label for the identity |
|
|
488
|
+
| `--no-invite` | Skip generating an invite (attach mode) |
|
|
489
|
+
|
|
490
|
+
## Important Concepts
|
|
491
|
+
|
|
492
|
+
### Per-Conversation Identities
|
|
493
|
+
|
|
494
|
+
Every conversation has its own:
|
|
495
|
+
|
|
496
|
+
- **Wallet key** (secp256k1 private key)
|
|
497
|
+
- **DB encryption key** (32-byte key)
|
|
498
|
+
- **XMTP inbox** (unique inbox ID)
|
|
499
|
+
- **Local database** (SQLite)
|
|
500
|
+
|
|
501
|
+
Identities are stored in `~/.convos/identities/<id>.json`. Databases are stored in `~/.convos/db/<env>/<id>.db3`.
|
|
502
|
+
|
|
503
|
+
### Invite Flow
|
|
504
|
+
|
|
505
|
+
1. **Creator** generates an invite URL/QR code (contains encrypted conversation token + creator's inbox ID)
|
|
506
|
+
2. **Person opens the invite URL in Convos app** (or scans the QR code) — this creates a per-conversation identity and sends a DM join request to the creator
|
|
507
|
+
3. **Creator processes the join request** — validates the invite signature, decrypts the conversation token, and adds the person to the group
|
|
508
|
+
4. Person is now a member with their own isolated identity
|
|
509
|
+
|
|
510
|
+
**Key point:** Step 3 must happen *after* step 2. The creator must either run `process-join-requests` after the invite has been opened, or use `--watch` to stream and process requests as they arrive.
|
|
511
|
+
|
|
512
|
+
### Consent States
|
|
513
|
+
|
|
514
|
+
| State | Meaning |
|
|
515
|
+
| ----- | ------- |
|
|
516
|
+
| `allowed` | Messages are welcome |
|
|
517
|
+
| `denied` | Messages are blocked |
|
|
518
|
+
| `unknown` | No decision made |
|
|
519
|
+
|
|
520
|
+
### Environment Networks
|
|
521
|
+
|
|
522
|
+
| Network | Use Case |
|
|
523
|
+
| ------- | -------- |
|
|
524
|
+
| `local` | Local XMTP node |
|
|
525
|
+
| `dev` | Development/testing (default) |
|
|
526
|
+
| `production` | Production use |
|
|
527
|
+
|
|
528
|
+
### Data Directory
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
~/.convos/
|
|
532
|
+
├── .env # Global config (env only)
|
|
533
|
+
├── identities/
|
|
534
|
+
│ ├── <id-1>.json # Identity: wallet key, db key, conversation link
|
|
535
|
+
│ └── <id-2>.json
|
|
536
|
+
└── db/
|
|
537
|
+
└── dev/ # XMTP databases by environment
|
|
538
|
+
├── <id-1>.db3
|
|
539
|
+
└── <id-2>.db3
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## Error Handling
|
|
543
|
+
|
|
544
|
+
1. **Not initialized**: Run `convos init` to create configuration
|
|
545
|
+
2. **No identities**: Create a conversation or identity first
|
|
546
|
+
3. **Identity not found**: Use `convos identity list` to see available identities
|
|
547
|
+
4. **Conversation not found**: Sync first with `convos conversations sync`
|
|
548
|
+
5. **Permission denied**: Check group permissions with `convos conversation permissions`
|
|
549
|
+
6. **Invite expired or invalid**: Generate a new invite with `convos conversation invite`
|
|
550
|
+
|
|
551
|
+
## Complete Example
|
|
552
|
+
|
|
553
|
+
```bash
|
|
554
|
+
# 1. initialize (first time only)
|
|
555
|
+
convos init --env dev
|
|
556
|
+
|
|
557
|
+
# 2. create a conversation
|
|
558
|
+
CONV=$(convos conversations create --name "Project Team" --profile-name "Alice" --json)
|
|
559
|
+
CONV_ID=$(echo "$CONV" | jq -r '.conversationId')
|
|
560
|
+
|
|
561
|
+
# 3. generate an invite for others to join
|
|
562
|
+
convos conversation invite "$CONV_ID"
|
|
563
|
+
|
|
564
|
+
# 4. wait for the person to open the invite URL or scan the QR code,
|
|
565
|
+
# then process their join request
|
|
566
|
+
convos conversations process-join-requests --conversation "$CONV_ID"
|
|
567
|
+
|
|
568
|
+
# OR: if you don't know when they'll open it, watch for requests
|
|
569
|
+
# convos conversations process-join-requests --watch --conversation "$CONV_ID"
|
|
570
|
+
|
|
571
|
+
# 5. send a message
|
|
572
|
+
convos conversation send-text "$CONV_ID" "Welcome to the team!"
|
|
573
|
+
|
|
574
|
+
# 6. stream messages
|
|
575
|
+
convos conversation stream "$CONV_ID" --timeout 300
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
## Tips
|
|
579
|
+
|
|
580
|
+
1. **Always display the full QR code**: The `conversation invite` and `conversations create` commands output a scannable QR code rendered in Unicode block characters followed by the invite URL. When showing the user the result, you **must** display the complete, unmodified command output so the QR code renders correctly in the terminal. Do not summarize, truncate, or omit the QR code — it is the primary way users share invites. Always show the full stdout output to the user. When running `agent serve`, the QR code is saved as a PNG file (path in the `qrCodePath` field of the `ready` event) — display it to the user using the read tool so they can scan it.
|
|
581
|
+
2. **Never use markdown in messages**: Convos does not render markdown. When sending messages (via `send-text`, `send-reply`, or agent `send` commands), always use plain text. Do not use markdown formatting like `**bold**`, `*italic*`, `# headings`, `` `code` ``, `[links](url)`, or bullet lists with `- ` or `* `. Write naturally in plain text instead.
|
|
582
|
+
3. **Identities are automatic**: You rarely need to manage them directly — creating/joining conversations handles it
|
|
583
|
+
4. **Use JSON output for scripting**: Add `--json` flag when extracting data programmatically
|
|
584
|
+
5. **Sync before reading**: Add `--sync` flag when reading messages to ensure fresh data
|
|
585
|
+
6. **Process join requests after invite is opened**: After generating an invite, wait for the person to open/scan it, then run `process-join-requests`. If you don't know when they'll open it, use `--watch` to stream requests as they arrive
|
|
586
|
+
7. **Lock before exploding**: Lock a conversation first to prevent new joins, then explode when ready
|
|
587
|
+
8. **Dangerous operations require --force**: Commands like `explode`, `identity remove`, and `lock` prompt for confirmation unless `--force` is passed
|
|
588
|
+
9. **Check command help**: Run `convos <command> --help` for full flag documentation
|