Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
# Changelog

## 0.8.0

### Breaking Changes: Single-Inbox Identity Model (ADR 011)

The CLI now uses **one XMTP inbox per install**, shared across every conversation and DM — mirroring the [convos-ios single-inbox refactor](https://github.com/xmtplabs/convos-ios/pull/713). This replaces the previous per-conversation identity model (ADR 002), which created a fresh XMTP inbox for every conversation.

Agents benefit: one agent identity across every conversation it participates in.

**Behavior changes:**

- `conversations create` / `conversations join` no longer create a new identity per conversation. They use (or create on first use) the install's single identity at `~/.convos/identity.json`.
- `conversation explode` no longer destroys the identity. It sends `ExplodeSettings`, updates metadata, and calls `removeMembers` on every other member. Receiving clients drop the conversation on either the `ExplodeSettings` message or the MLS remove commit.
- `identity list` returns zero or one entries. `identity info` and `identity remove` take no id argument. `identity create` errors if an identity already exists.
- `conversations list` returns every group in the install's inbox (no more deduplication across identities); pass `--include-dms` to include DMs.
- `conversations sync` now performs a single `client.sync()` call.
- `agent serve` drops `--identity`. Bind to an existing conversation via positional arg, or create a new one.
- `reset` wipes the single identity.json and all db files. Legacy per-conversation identity files are swept out if found.

**Wire protocol is unchanged.** Invites, join requests, ProfileUpdate/ProfileSnapshot, and ExplodeSettings all interop with older CLI clients and the iOS app both pre- and post-refactor.

**Migration from 0.7.x:**

Existing `~/.convos/identities/*.json` files are no longer used. The CLI will create a fresh `identity.json` on first use. To clear the legacy files, run `convos reset`. To keep them as archival state, they will sit unused and can be removed manually.

**Data layout:**

```
~/.convos/
├── .env
├── identity.json (was: identities/<id>.json × N)
└── db/
└── dev/
└── main.db3 (was: db/dev/<id>.db3 × N)
```

**API changes:**

- `createClientForIdentity(identity, config, home)` → `getClient(config, home)` and `getIdentityAndClient(config, home)`. The client is cached per (home, env) for the process lifetime.
- `IdentityStore`: `list()`, `get(id)`, `create()`, `update(id, patch)`, `remove(id)`, `getByConversationId()`, `getByInviteTag()`, `getUnlinked()`, `getAllByConversationId()` are gone. Replaced with `load()`, `loadOrUpsert(opts)`, `exists()`, `update(patch)`, `delete()`, `getDbPath(env)`. `loadOrUpsert` overwrites `label`/`profileName` when those opts differ from the stored values.
- `Identity`: loses `conversationId` and `inviteTag` fields.

### Added

- `conversations list --include-dms` — include DMs alongside groups in output.

## 0.4.0 (2025-03-04)

### Features
Expand Down
92 changes: 49 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@
> [!CAUTION]
> This CLI is in beta status and ready for you to use. Software in this status may contain bugs or change based on feedback.

A command-line interface for [Convos](https://convos.org) — privacy-focused ephemeral messaging built on [XMTP](https://xmtp.org).
A command-line interface for [Convos](https://convos.org) — agent-focused messaging built on [XMTP](https://xmtp.org).

## Features

- **Per-conversation identities**: Every conversation gets its own XMTP inbox — no linkability across conversations
- **One identity per install**: A single XMTP inbox shared across every conversation and DM (per ADR 011), matching the iOS app
- **Multiple agents per machine**: Point each agent at its own `CONVOS_HOME` to keep identities isolated
- **Invite system**: Generate QR codes and invite links; join conversations without knowing the creator's address
- **Per-conversation profiles**: Different display name and avatar in each conversation
- **Explode**: Permanently destroy a conversation and all its cryptographic keys
- **Per-conversation profiles**: Display a different name/avatar in each conversation (the underlying identity stays the same)
- **Explode**: Notify members and remove them from a conversation
- **Lock**: Prevent new members from being added to a conversation
- **Agent mode**: Single long-running process for bots — streams messages, auto-processes joins, accepts commands via stdin
- **JSON output**: Every command supports `--json` for scripting and automation

## How Convos Differs from Standard XMTP
## Identity Model

Standard XMTP uses a single identity (wallet + inbox) across all conversations. Convos creates a **unique identity per conversation** for maximum privacy:
Convos runs one XMTP inbox per install, shared across every conversation and DM — the same model as the Convos iOS app after the single-inbox refactor ([ADR 011](https://github.com/xmtplabs/convos-ios/blob/main/docs/adr/011-single-inbox-identity-model.md)). The identity is created automatically on first use and lives at `~/.convos/identity.json`.

| Property | How |
| -------- | --- |
| **No linkability** | Conversations cannot be correlated by external observers |
| **Isolated keys** | Each conversation has its own wallet key, encryption key, and database |
| **Ephemeral** | Exploding a conversation destroys the cryptographic identity permanently |
| **Per-conversation profiles** | Different display names and avatars per conversation |
To run multiple independent agents on one machine, point each at its own `CONVOS_HOME`:

```bash
CONVOS_HOME=~/.convos/alice convos conversations create --name "Alice's Group"
CONVOS_HOME=~/.convos/bob convos conversations join <slug>
```

## Requirements

Expand Down Expand Up @@ -59,7 +60,7 @@ yarn dlx @xmtp/convos-cli --help
# 1. Initialize configuration
convos init

# 2. Create a conversation (auto-creates a per-conversation identity)
# 2. Create a conversation (creates the install's identity on first use)
convos conversations create --name "My Group" --profile-name "Alice"

# 3. Send a message
Expand All @@ -68,7 +69,7 @@ convos conversation send-text <conversation-id> "Hello!"
# 4. Generate an invite QR code for others to join
convos conversation invite <conversation-id>

# 5. List all conversations across all identities
# 5. List all conversations in this install's inbox
convos conversations list

# 6. Stream messages in real-time
Expand All @@ -82,10 +83,12 @@ Running `convos init` creates `~/.convos/.env` with:
| Variable | Description |
| ------------------------------ | ------------------------------------------------ |
| `CONVOS_ENV` | Network: `local`, `dev`, or `production` |
| `CONVOS_API_KEY` | Agent API key for uploads (auto-selects `convos-api` provider) |
| `CONVOS_API_KEY` | Agent API key — **required** for attachments >1MB and for profile images (auto-selects `convos-api` provider) |
| `CONVOS_UPLOAD_PROVIDER` | Upload provider override (`convos-api`, `pinata`, `s3`) |

Unlike standard XMTP, there is **no global wallet key**. Each conversation creates its own identity stored in `~/.convos/identities/`.
Without `CONVOS_API_KEY` (or another `CONVOS_UPLOAD_PROVIDER`), `conversation send-attachment` fails for files over 1MB and `conversation update-profile --image` cannot encrypt and upload the image.

The singleton identity for this install lives at `~/.convos/identity.json`. XMTP databases live at `~/.convos/db/<env>/main.db3`.

The default environment is `dev`. Use `--env` to change it:

Expand All @@ -105,7 +108,7 @@ Configuration is loaded in priority order:
| Topic | Purpose |
| ----- | ------- |
| `agent` | Agent mode — long-running sessions with streaming I/O |
| `identity` | Manage per-conversation identities (inboxes) |
| `identity` | Manage this install's singleton identity |
| `conversations` | List, create, join, and stream conversations |
| `conversation` | Interact with a specific conversation |

Expand Down Expand Up @@ -212,43 +215,44 @@ echo '{"type":"remote-attach","url":"https://...","contentDigest":"...","secret"
| `--description` | Conversation description (when creating new) |
| `--permissions` | `all-members` or `admin-only` (when creating new) |
| `--profile-name` | Display name for this conversation |
| `--identity` | Use an existing unlinked identity |
| `--label` | Local label for the identity |
| `--no-invite` | Skip generating an invite (attach mode only) |

## Usage Examples

### Identity Management

Each conversation has its own XMTP identity (wallet + inbox). Identities are created automatically when you create or join a conversation, but you can also manage them directly.
Every install has a single XMTP identity, created automatically on first use.

```bash
# List all identities
# Show the install's identity (0 or 1 entries)
convos identity list

# Create an identity manually
convos identity create --label "Work Chat" --profile-name "Alice"
# Create the identity manually (errors if one already exists)
convos identity create --label "My Bot" --profile-name "Alice"

# View identity details (connects to XMTP to show inbox ID)
convos identity info <identity-id>
# View identity details (registers the XMTP client if needed)
convos identity info

# Remove an identity (destroys all keys — irreversible)
convos identity remove <identity-id> --force
# Remove the identity and wipe the XMTP database (irreversible)
convos identity remove --force
```

### Conversations

```bash
# Create a conversation (auto-creates per-conversation identity)
# Create a conversation (uses the singleton identity, created on first use)
convos conversations create --name "Project Team" --profile-name "Alice"

# Create with admin-only permissions
convos conversations create --name "Announcement Channel" --permissions admin-only

# List all conversations across all identities
# List all groups in this install's inbox
convos conversations list --sync

# Sync all conversations from the network
# Include DMs too
convos conversations list --include-dms

# Sync the whole inbox from the network
convos conversations sync
```

Expand Down Expand Up @@ -371,7 +375,7 @@ This auto-selects the `convos-api` provider. Other providers (`pinata`, `s3`) ar

### Profiles

Each conversation has independent profiles — you can be a different person in each conversation.
Profiles are per-conversation — the same underlying identity can present a different display name and avatar in each conversation.

Profiles are sent as **ProfileUpdate messages** to the group. The CLI no longer writes profiles to `appData` (this was removed to fix a data corruption bug). When reading profiles, message-sourced profiles take precedence, with `appData` as a read-only fallback for profiles written by older clients.

Expand Down Expand Up @@ -421,7 +425,7 @@ convos conversation lock <id> --unlock

### Explode a Conversation

Permanently destroy a conversation and all its cryptographic keys:
Notify members and remove them from the MLS group:

```bash
# Explode immediately
Expand All @@ -431,7 +435,9 @@ convos conversation explode <id> --force
convos conversation explode <id> --scheduled "2025-03-01T00:00:00Z"
```

Exploding sends an `ExplodeSettings` notification to all members (so iOS and other clients trigger their cleanup flow), updates group metadata with the expiration timestamp, removes all members, then destroys the local identity. The conversation becomes unreadable.
Exploding sends an `ExplodeSettings` notification to all members (so iOS and other clients trigger their cleanup flow), updates group metadata with the expiration timestamp, and removes every other member from the group. Receiving clients drop the conversation locally on whichever arrives first: the `ExplodeSettings` message or the MLS remove commit.

The install's identity is **not** destroyed — matching the iOS model (ADR 011 §5 / ADR 004 C9), one identity spans every conversation on this install.

When using `--scheduled`, members are notified but not removed — clients handle cleanup when the time arrives.

Expand Down Expand Up @@ -494,23 +500,22 @@ Common flags (--json, --fields, --env, etc.) are listed once at the top level ra
Use `--verbose` to see detailed client initialization info. When combined with `--json`, verbose logs go to stderr:

```bash
convos identity info <id> --verbose
convos identity info --verbose
```

## Data Directory

```
~/.convos/
├── .env # Global config (env only)
├── identities/
│ ├── <id-1>.json # Identity: wallet key, db key, conversation link
│ └── <id-2>.json
├── .env # Global config (env only)
├── identity.json # Singleton identity: wallet key, db key, inbox ID
└── db/
└── dev/ # XMTP databases by environment
├── <id-1>.db3
└── <id-2>.db3
└── dev/ # XMTP database for the identity, by environment
└── main.db3
```

To run multiple agents on one host, give each its own directory via `--home` or `CONVOS_HOME`.

## Architecture

```
Expand All @@ -529,7 +534,7 @@ convos identity info <id> --verbose
│ ┌────────────────────────────────────┐ │
│ │ @xmtp/node-sdk │ │
│ │ │ │
│ │ Per-conversation XMTP clients │ │
│ │ One XMTP client per install │ │
│ │ Group/DM management │ │
│ │ Message encryption & delivery │ │
│ └────────────────────────────────────┘ │
Expand All @@ -543,7 +548,8 @@ convos identity info <id> --verbose
```typescript
import {
createIdentityStore,
createClientForIdentity,
getClient,
getIdentityAndClient,
createInviteSlug,
parseInvite,
verifyInvite,
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xmtp/convos-cli",
"version": "0.7.4",
"version": "0.8.0",
"description": "A command-line interface for Convos — privacy-focused messaging built on XMTP",
"keywords": [
"convos",
Expand Down Expand Up @@ -74,7 +74,7 @@
"description": "Agent mode — long-running sessions with streaming I/O"
},
"identity": {
"description": "Manage per-conversation identities (inboxes)"
"description": "Manage this install's singleton XMTP inbox identity"
},
"conversation": {
"description": "Interact with a specific conversation"
Expand Down
Loading