myceliumail 1.0.3 → 1.0.5
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/.github/workflows/publish.yml +108 -0
- package/CHANGELOG.md +85 -0
- package/README.md +295 -162
- package/dist/storage/supabase.d.ts +3 -3
- package/dist/storage/supabase.d.ts.map +1 -1
- package/dist/storage/supabase.js +56 -5
- package/dist/storage/supabase.js.map +1 -1
- package/mcp-server/package-lock.json +3 -4
- package/mcp-server/package.json +6 -5
- package/package.json +11 -2
- package/src/storage/supabase.ts +67 -5
- package/COMPLETE.md +0 -51
- package/MYCELIUMAIL_STARTER_KIT.md +0 -603
- package/NEXT_STEPS.md +0 -96
- package/docs/20251215_Treebird-Ecosystem_Knowledge-Base_v2.md +0 -292
- package/docs/20251215_Treebird-Ecosystem_Project-Instructions_v2.md +0 -176
- package/docs/AGENT_DELEGATION_WORKFLOW.md +0 -453
- package/docs/ANNOUNCEMENT_DRAFTS.md +0 -55
- package/docs/DASHBOARD_AGENT_HANDOFF.md +0 -429
- package/docs/DASHBOARD_AGENT_PROMPT.md +0 -32
- package/docs/DASHBOARD_BUILD_ROADMAP.md +0 -61
- package/docs/MCP_PUBLISHING_ROADMAP.md +0 -113
- package/docs/SSAN_MESSAGES_SUMMARY.md +0 -92
- package/docs/STORAGE_ARCHITECTURE.md +0 -114
|
@@ -1,603 +0,0 @@
|
|
|
1
|
-
# Myceliumail Starter Kit
|
|
2
|
-
|
|
3
|
-
> **Everything you need to bootstrap Myceliumail from a fresh repo**
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Step 1: Create the Repository
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
mkdir myceliumail && cd myceliumail
|
|
11
|
-
git init
|
|
12
|
-
npm init -y
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Step 2: Inject CLAUDE.md
|
|
18
|
-
|
|
19
|
-
Create this file first - it's the "injection" that gives any AI agent instant context:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
cat > CLAUDE.md << 'EOF'
|
|
23
|
-
# Myceliumail - AI Agent Context
|
|
24
|
-
|
|
25
|
-
> **End-to-End Encrypted Messaging for AI Agents**
|
|
26
|
-
|
|
27
|
-
## What is Myceliumail?
|
|
28
|
-
|
|
29
|
-
Myceliumail is the nervous system of the Treebird ecosystem - enabling AI coding agents to communicate securely across tools and repositories. Named after the underground fungal network that connects forest trees, it creates the "agent wide web."
|
|
30
|
-
|
|
31
|
-
## Core Commands
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
# Messaging
|
|
35
|
-
mycmail send <agent> "<subject>" # Send message to agent
|
|
36
|
-
mycmail inbox # Check incoming messages
|
|
37
|
-
mycmail read <id> # Read specific message
|
|
38
|
-
mycmail reply <id> "<message>" # Reply to a message
|
|
39
|
-
mycmail archive <id> # Archive read message
|
|
40
|
-
|
|
41
|
-
# Encryption (required for secure messaging)
|
|
42
|
-
mycmail keygen # Generate your keypair (run once)
|
|
43
|
-
mycmail keys # List known public keys
|
|
44
|
-
mycmail key-import <agent> <key> # Import another agent's public key
|
|
45
|
-
mycmail send <agent> --encrypt # Send encrypted message
|
|
46
|
-
|
|
47
|
-
# Channels (group messaging)
|
|
48
|
-
mycmail channel create <name> # Create new channel
|
|
49
|
-
mycmail channel join <name> # Join a channel
|
|
50
|
-
mycmail channel post <name> "<message>" # Post to channel
|
|
51
|
-
|
|
52
|
-
# Network & Presence
|
|
53
|
-
mycmail agents # List all connected agents
|
|
54
|
-
mycmail ping <agent> # Ping an agent
|
|
55
|
-
mycmail status --set <status> # Update my status
|
|
56
|
-
mycmail broadcast "<message>" # Message all agents
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Encryption
|
|
60
|
-
|
|
61
|
-
> **All messages encrypted by default with NaCl box**
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# Setup (one-time)
|
|
65
|
-
mycmail keygen
|
|
66
|
-
# Output: Your public key (share this with other agents)
|
|
67
|
-
|
|
68
|
-
# Exchange keys
|
|
69
|
-
mycmail key-import claude AbC123... # Import peer's public key
|
|
70
|
-
mycmail keys # Verify import
|
|
71
|
-
|
|
72
|
-
# Messages auto-encrypt when recipient key is known
|
|
73
|
-
mycmail send claude "Secret plans" --message "For your eyes only"
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Uses **X25519 key exchange + XSalsa20-Poly1305** encryption (tweetnacl).
|
|
77
|
-
Keys stored in `~/.myceliumail/keys/`.
|
|
78
|
-
|
|
79
|
-
## Architecture
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
┌────────────────────────────────────────────────────────────┐
|
|
83
|
-
│ Myceliumail CLI │
|
|
84
|
-
├────────────────────────────────────────────────────────────┤
|
|
85
|
-
│ Commands: send | inbox | read | reply | keygen | keys │
|
|
86
|
-
├────────────────────────────────────────────────────────────┤
|
|
87
|
-
│ ┌─────────────┐ ┌────────────┐ ┌─────────────────────┐ │
|
|
88
|
-
│ │ Crypto │ │ Storage │ │ Presence │ │
|
|
89
|
-
│ ├─────────────┤ ├────────────┤ ├─────────────────────┤ │
|
|
90
|
-
│ │ NaCl Box │ │ Supabase │ │ Agent heartbeat │ │
|
|
91
|
-
│ │ X25519 │ │ PostgreSQL │ │ Status tracking │ │
|
|
92
|
-
│ │ XSalsa20 │ │ Local JSON │ │ Key registry │ │
|
|
93
|
-
│ └─────────────┘ └────────────┘ └─────────────────────┘ │
|
|
94
|
-
└────────────────────────────────────────────────────────────┘
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Project Structure
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
src/
|
|
101
|
-
├── bin/myceliumail.ts # CLI entry point
|
|
102
|
-
├── commands/ # Command implementations
|
|
103
|
-
│ ├── send.ts
|
|
104
|
-
│ ├── inbox.ts
|
|
105
|
-
│ ├── read.ts
|
|
106
|
-
│ ├── reply.ts
|
|
107
|
-
│ ├── keygen.ts
|
|
108
|
-
│ ├── keys.ts
|
|
109
|
-
│ └── key-import.ts
|
|
110
|
-
├── lib/ # Core libraries
|
|
111
|
-
│ ├── crypto.ts # NaCl encryption
|
|
112
|
-
│ ├── config.ts
|
|
113
|
-
│ └── storage.ts
|
|
114
|
-
└── storage/ # Storage adapters
|
|
115
|
-
├── local.ts # JSON file storage
|
|
116
|
-
└── supabase.ts # Cloud storage
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Database Schema
|
|
120
|
-
|
|
121
|
-
Messages are stored with encryption at rest:
|
|
122
|
-
|
|
123
|
-
```sql
|
|
124
|
-
-- agent_messages table
|
|
125
|
-
id uuid PRIMARY KEY,
|
|
126
|
-
sender text NOT NULL,
|
|
127
|
-
recipient text NOT NULL,
|
|
128
|
-
subject text, -- encrypted if message is encrypted
|
|
129
|
-
body text, -- encrypted if message is encrypted
|
|
130
|
-
encrypted boolean DEFAULT false, -- encryption indicator
|
|
131
|
-
ciphertext text, -- NaCl encrypted payload
|
|
132
|
-
nonce text, -- NaCl nonce
|
|
133
|
-
sender_public_key text, -- sender's public key for decryption
|
|
134
|
-
read boolean DEFAULT false,
|
|
135
|
-
archived boolean DEFAULT false,
|
|
136
|
-
created_at timestamptz DEFAULT now()
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Key Interfaces
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
interface EncryptedMessage {
|
|
143
|
-
ciphertext: string; // base64
|
|
144
|
-
nonce: string; // base64
|
|
145
|
-
senderPublicKey: string; // base64
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
interface Message {
|
|
149
|
-
id: string;
|
|
150
|
-
sender: string;
|
|
151
|
-
recipient: string;
|
|
152
|
-
subject: string;
|
|
153
|
-
body: string;
|
|
154
|
-
encrypted: boolean;
|
|
155
|
-
encryptedPayload?: EncryptedMessage;
|
|
156
|
-
read: boolean;
|
|
157
|
-
archived: boolean;
|
|
158
|
-
createdAt: Date;
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Testing
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
npm test # Run unit tests
|
|
166
|
-
npm run lint # ESLint
|
|
167
|
-
npm run build # TypeScript compilation
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Related Projects
|
|
171
|
-
|
|
172
|
-
- **Spidersan** - Branch coordination CLI (current home of messaging)
|
|
173
|
-
- **Mappersan** - Documentation mapping CLI
|
|
174
|
-
- **Recovery-Tree** - Agent state persistence
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
**Full roadmap:** See Spidersan repo `docs/MYCELIUMAIL_ROADMAP.md`
|
|
179
|
-
EOF
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## Step 3: Bootstrap Prompt
|
|
185
|
-
|
|
186
|
-
Use this prompt to have Claude Code set up the project:
|
|
187
|
-
|
|
188
|
-
```
|
|
189
|
-
Create a TypeScript CLI project for Myceliumail with:
|
|
190
|
-
|
|
191
|
-
1. Project Setup:
|
|
192
|
-
- TypeScript with ES2022 target, ESM modules
|
|
193
|
-
- Node 18+ requirement
|
|
194
|
-
- Commander.js 12.0.0 for CLI
|
|
195
|
-
- tweetnacl + tweetnacl-util for encryption
|
|
196
|
-
- **dotenv** for .env file support (REQUIRED)
|
|
197
|
-
- Vitest for testing
|
|
198
|
-
- ESLint + TypeScript ESLint
|
|
199
|
-
- **context7** for AI tool documentation (dev dependency)
|
|
200
|
-
|
|
201
|
-
2. Package.json:
|
|
202
|
-
- name: "myceliumail"
|
|
203
|
-
- bin: { "mycmail": "./dist/bin/myceliumail.js", "myceliumail": "./dist/bin/myceliumail.js" }
|
|
204
|
-
- type: "module"
|
|
205
|
-
- scripts: build, test, lint, dev
|
|
206
|
-
|
|
207
|
-
3. Initial Commands:
|
|
208
|
-
- send: Send message to agent
|
|
209
|
-
- inbox: List messages
|
|
210
|
-
- read: Read specific message
|
|
211
|
-
- keygen: Generate keypair
|
|
212
|
-
- keys: List known keys
|
|
213
|
-
- key-import: Import peer's public key
|
|
214
|
-
|
|
215
|
-
4. Project Structure:
|
|
216
|
-
src/
|
|
217
|
-
├── bin/myceliumail.ts # CLI entry, Commander setup
|
|
218
|
-
├── commands/
|
|
219
|
-
│ ├── send.ts
|
|
220
|
-
│ ├── inbox.ts
|
|
221
|
-
│ ├── read.ts
|
|
222
|
-
│ ├── keygen.ts
|
|
223
|
-
│ ├── keys.ts
|
|
224
|
-
│ └── key-import.ts
|
|
225
|
-
├── lib/
|
|
226
|
-
│ ├── crypto.ts # NaCl encryption (carry from Spidersan)
|
|
227
|
-
│ └── config.ts # Config loading
|
|
228
|
-
└── storage/
|
|
229
|
-
├── local.ts # JSON file storage
|
|
230
|
-
└── supabase.ts # Supabase adapter (optional)
|
|
231
|
-
|
|
232
|
-
5. Encryption from Day 1:
|
|
233
|
-
- Use NaCl box (X25519 + XSalsa20-Poly1305)
|
|
234
|
-
- Keys stored in ~/.myceliumail/keys/
|
|
235
|
-
- Messages default to encrypted when recipient key is known
|
|
236
|
-
|
|
237
|
-
Make the CLI executable and working. I should be able to run:
|
|
238
|
-
- npm run build
|
|
239
|
-
- npm link
|
|
240
|
-
- mycmail --help
|
|
241
|
-
- mycmail keygen
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## Step 4: Supabase Schema (Encryption-First)
|
|
247
|
-
|
|
248
|
-
Apply this migration to create the encrypted messages table:
|
|
249
|
-
|
|
250
|
-
```sql
|
|
251
|
-
-- migrations/000_myceliumail_setup.sql
|
|
252
|
-
-- Myceliumail: Agent Messaging with E2E Encryption
|
|
253
|
-
|
|
254
|
-
-- Agent messages table with encryption support
|
|
255
|
-
CREATE TABLE IF NOT EXISTS agent_messages (
|
|
256
|
-
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
257
|
-
sender text NOT NULL,
|
|
258
|
-
recipient text NOT NULL,
|
|
259
|
-
subject text,
|
|
260
|
-
body text,
|
|
261
|
-
|
|
262
|
-
-- Encryption fields (NaCl box)
|
|
263
|
-
encrypted boolean DEFAULT false,
|
|
264
|
-
ciphertext text, -- base64 encrypted payload
|
|
265
|
-
nonce text, -- base64 nonce
|
|
266
|
-
sender_public_key text, -- base64 sender's public key
|
|
267
|
-
|
|
268
|
-
-- Message state
|
|
269
|
-
read boolean DEFAULT false,
|
|
270
|
-
archived boolean DEFAULT false,
|
|
271
|
-
|
|
272
|
-
-- Metadata
|
|
273
|
-
message_type text DEFAULT 'direct', -- direct, channel, broadcast, system
|
|
274
|
-
thread_id uuid, -- for threaded conversations
|
|
275
|
-
reply_to uuid, -- parent message
|
|
276
|
-
priority text DEFAULT 'normal', -- low, normal, high, urgent
|
|
277
|
-
|
|
278
|
-
created_at timestamptz DEFAULT now(),
|
|
279
|
-
updated_at timestamptz DEFAULT now()
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
-- Indexes for common queries
|
|
283
|
-
CREATE INDEX IF NOT EXISTS idx_agent_messages_recipient
|
|
284
|
-
ON agent_messages(recipient, read, archived);
|
|
285
|
-
CREATE INDEX IF NOT EXISTS idx_agent_messages_sender
|
|
286
|
-
ON agent_messages(sender, created_at);
|
|
287
|
-
CREATE INDEX IF NOT EXISTS idx_agent_messages_thread
|
|
288
|
-
ON agent_messages(thread_id) WHERE thread_id IS NOT NULL;
|
|
289
|
-
|
|
290
|
-
-- Agent public keys registry
|
|
291
|
-
CREATE TABLE IF NOT EXISTS agent_keys (
|
|
292
|
-
agent_id text PRIMARY KEY,
|
|
293
|
-
public_key text NOT NULL, -- base64 encoded
|
|
294
|
-
created_at timestamptz DEFAULT now(),
|
|
295
|
-
updated_at timestamptz DEFAULT now()
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
-- Channels table
|
|
299
|
-
CREATE TABLE IF NOT EXISTS channels (
|
|
300
|
-
name text PRIMARY KEY,
|
|
301
|
-
description text,
|
|
302
|
-
is_public boolean DEFAULT true,
|
|
303
|
-
created_by text NOT NULL,
|
|
304
|
-
created_at timestamptz DEFAULT now()
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
-- Channel membership
|
|
308
|
-
CREATE TABLE IF NOT EXISTS channel_members (
|
|
309
|
-
channel_name text REFERENCES channels(name) ON DELETE CASCADE,
|
|
310
|
-
agent_id text,
|
|
311
|
-
joined_at timestamptz DEFAULT now(),
|
|
312
|
-
notify_level text DEFAULT 'all', -- all, mentions, none
|
|
313
|
-
PRIMARY KEY (channel_name, agent_id)
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
-- RLS Policies
|
|
317
|
-
ALTER TABLE agent_messages ENABLE ROW LEVEL SECURITY;
|
|
318
|
-
ALTER TABLE agent_keys ENABLE ROW LEVEL SECURITY;
|
|
319
|
-
|
|
320
|
-
-- Allow all authenticated access (agents auth via service key)
|
|
321
|
-
CREATE POLICY "Agents can read their own messages"
|
|
322
|
-
ON agent_messages FOR SELECT
|
|
323
|
-
USING (true);
|
|
324
|
-
|
|
325
|
-
CREATE POLICY "Agents can insert messages"
|
|
326
|
-
ON agent_messages FOR INSERT
|
|
327
|
-
WITH CHECK (true);
|
|
328
|
-
|
|
329
|
-
CREATE POLICY "Agents can update their own received messages"
|
|
330
|
-
ON agent_messages FOR UPDATE
|
|
331
|
-
USING (true);
|
|
332
|
-
|
|
333
|
-
CREATE POLICY "Anyone can read public keys"
|
|
334
|
-
ON agent_keys FOR SELECT
|
|
335
|
-
USING (true);
|
|
336
|
-
|
|
337
|
-
CREATE POLICY "Agents can insert their own key"
|
|
338
|
-
ON agent_keys FOR INSERT
|
|
339
|
-
WITH CHECK (true);
|
|
340
|
-
|
|
341
|
-
CREATE POLICY "Agents can update their own key"
|
|
342
|
-
ON agent_keys FOR UPDATE
|
|
343
|
-
USING (true);
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
Apply with:
|
|
347
|
-
```bash
|
|
348
|
-
supabase db push
|
|
349
|
-
# or
|
|
350
|
-
supabase migration up
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## Step 5: Carry Forward Crypto Module
|
|
356
|
-
|
|
357
|
-
This crypto module is battle-tested from Spidersan. Copy and adapt:
|
|
358
|
-
|
|
359
|
-
```typescript
|
|
360
|
-
// src/lib/crypto.ts
|
|
361
|
-
/**
|
|
362
|
-
* Myceliumail Crypto Module
|
|
363
|
-
*
|
|
364
|
-
* E2E encryption for agent messaging using TweetNaCl.
|
|
365
|
-
* Uses X25519 for key exchange and XSalsa20-Poly1305 for encryption.
|
|
366
|
-
*/
|
|
367
|
-
|
|
368
|
-
import nacl from 'tweetnacl';
|
|
369
|
-
import util from 'tweetnacl-util';
|
|
370
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
371
|
-
import { join } from 'path';
|
|
372
|
-
import { homedir } from 'os';
|
|
373
|
-
|
|
374
|
-
// Key storage location
|
|
375
|
-
const KEYS_DIR = join(homedir(), '.myceliumail', 'keys');
|
|
376
|
-
|
|
377
|
-
export interface KeyPair {
|
|
378
|
-
publicKey: Uint8Array;
|
|
379
|
-
secretKey: Uint8Array;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
export interface EncryptedMessage {
|
|
383
|
-
ciphertext: string; // base64
|
|
384
|
-
nonce: string; // base64
|
|
385
|
-
senderPublicKey: string; // base64
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Ensure keys directory exists
|
|
390
|
-
*/
|
|
391
|
-
function ensureKeysDir(): void {
|
|
392
|
-
if (!existsSync(KEYS_DIR)) {
|
|
393
|
-
mkdirSync(KEYS_DIR, { recursive: true });
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Generate a new keypair for an agent
|
|
399
|
-
*/
|
|
400
|
-
export function generateKeyPair(): KeyPair {
|
|
401
|
-
return nacl.box.keyPair();
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Save keypair to local storage
|
|
406
|
-
*/
|
|
407
|
-
export function saveKeyPair(agentId: string, keyPair: KeyPair): void {
|
|
408
|
-
ensureKeysDir();
|
|
409
|
-
const serialized = {
|
|
410
|
-
publicKey: util.encodeBase64(keyPair.publicKey),
|
|
411
|
-
secretKey: util.encodeBase64(keyPair.secretKey),
|
|
412
|
-
};
|
|
413
|
-
const path = join(KEYS_DIR, `${agentId}.key.json`);
|
|
414
|
-
writeFileSync(path, JSON.stringify(serialized, null, 2), { mode: 0o600 });
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Load keypair from local storage
|
|
419
|
-
*/
|
|
420
|
-
export function loadKeyPair(agentId: string): KeyPair | null {
|
|
421
|
-
const path = join(KEYS_DIR, `${agentId}.key.json`);
|
|
422
|
-
if (!existsSync(path)) return null;
|
|
423
|
-
|
|
424
|
-
try {
|
|
425
|
-
const data = JSON.parse(readFileSync(path, 'utf-8'));
|
|
426
|
-
return {
|
|
427
|
-
publicKey: util.decodeBase64(data.publicKey),
|
|
428
|
-
secretKey: util.decodeBase64(data.secretKey),
|
|
429
|
-
};
|
|
430
|
-
} catch {
|
|
431
|
-
return null;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Encrypt a message for a recipient
|
|
437
|
-
*/
|
|
438
|
-
export function encryptMessage(
|
|
439
|
-
message: string,
|
|
440
|
-
recipientPublicKey: Uint8Array,
|
|
441
|
-
senderKeyPair: KeyPair
|
|
442
|
-
): EncryptedMessage {
|
|
443
|
-
const messageBytes = util.decodeUTF8(message);
|
|
444
|
-
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
445
|
-
|
|
446
|
-
const ciphertext = nacl.box(
|
|
447
|
-
messageBytes,
|
|
448
|
-
nonce,
|
|
449
|
-
recipientPublicKey,
|
|
450
|
-
senderKeyPair.secretKey
|
|
451
|
-
);
|
|
452
|
-
|
|
453
|
-
return {
|
|
454
|
-
ciphertext: util.encodeBase64(ciphertext),
|
|
455
|
-
nonce: util.encodeBase64(nonce),
|
|
456
|
-
senderPublicKey: util.encodeBase64(senderKeyPair.publicKey),
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Decrypt a message from a sender
|
|
462
|
-
*/
|
|
463
|
-
export function decryptMessage(
|
|
464
|
-
encrypted: EncryptedMessage,
|
|
465
|
-
recipientKeyPair: KeyPair
|
|
466
|
-
): string | null {
|
|
467
|
-
try {
|
|
468
|
-
const ciphertext = util.decodeBase64(encrypted.ciphertext);
|
|
469
|
-
const nonce = util.decodeBase64(encrypted.nonce);
|
|
470
|
-
const senderPublicKey = util.decodeBase64(encrypted.senderPublicKey);
|
|
471
|
-
|
|
472
|
-
const decrypted = nacl.box.open(
|
|
473
|
-
ciphertext,
|
|
474
|
-
nonce,
|
|
475
|
-
senderPublicKey,
|
|
476
|
-
recipientKeyPair.secretKey
|
|
477
|
-
);
|
|
478
|
-
|
|
479
|
-
if (!decrypted) return null;
|
|
480
|
-
return util.encodeUTF8(decrypted);
|
|
481
|
-
} catch {
|
|
482
|
-
return null;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Known keys registry
|
|
488
|
-
*/
|
|
489
|
-
export function loadKnownKeys(): Record<string, string> {
|
|
490
|
-
const path = join(KEYS_DIR, 'known_keys.json');
|
|
491
|
-
if (!existsSync(path)) return {};
|
|
492
|
-
try {
|
|
493
|
-
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
494
|
-
} catch {
|
|
495
|
-
return {};
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
export function saveKnownKey(agentId: string, publicKeyBase64: string): void {
|
|
500
|
-
ensureKeysDir();
|
|
501
|
-
const keys = loadKnownKeys();
|
|
502
|
-
keys[agentId] = publicKeyBase64;
|
|
503
|
-
writeFileSync(join(KEYS_DIR, 'known_keys.json'), JSON.stringify(keys, null, 2));
|
|
504
|
-
}
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
---
|
|
508
|
-
|
|
509
|
-
## Step 6: Test Encryption Flow
|
|
510
|
-
|
|
511
|
-
After setup, verify encryption works:
|
|
512
|
-
|
|
513
|
-
```bash
|
|
514
|
-
# Generate keys for test agent
|
|
515
|
-
MYCELIUMAIL_AGENT=test-agent mycmail keygen
|
|
516
|
-
|
|
517
|
-
# Check keys
|
|
518
|
-
mycmail keys
|
|
519
|
-
|
|
520
|
-
# Import a peer's key (get from actual peer)
|
|
521
|
-
mycmail key-import peer-agent AaBbCcDdEeFf...
|
|
522
|
-
|
|
523
|
-
# Send encrypted message
|
|
524
|
-
mycmail send peer-agent "Test" --encrypt --message "This is secret"
|
|
525
|
-
|
|
526
|
-
# Verify message is encrypted in storage
|
|
527
|
-
# (body should be null, ciphertext should be populated)
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
---
|
|
531
|
-
|
|
532
|
-
## Quick Reference: File Injection Order
|
|
533
|
-
|
|
534
|
-
```
|
|
535
|
-
1. CLAUDE.md ← Inject first (AI context)
|
|
536
|
-
2. src/lib/crypto.ts ← Encryption foundation
|
|
537
|
-
3. src/bin/myceliumail.ts ← CLI entry point
|
|
538
|
-
4. src/commands/keygen.ts ← Key generation
|
|
539
|
-
5. src/commands/*.ts ← Other commands
|
|
540
|
-
6. src/storage/*.ts ← Storage adapters
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
---
|
|
544
|
-
|
|
545
|
-
## Validation Checklist
|
|
546
|
-
|
|
547
|
-
After each phase, verify:
|
|
548
|
-
|
|
549
|
-
```bash
|
|
550
|
-
# Phase 1: Bootstrap
|
|
551
|
-
npm run build # ✓ Compiles
|
|
552
|
-
mycmail --help # ✓ Shows commands
|
|
553
|
-
mycmail keygen # ✓ Generates keypair
|
|
554
|
-
|
|
555
|
-
# Phase 2: Encryption
|
|
556
|
-
mycmail keys # ✓ Shows keys
|
|
557
|
-
cat ~/.myceliumail/keys/*.json # ✓ Keys stored
|
|
558
|
-
|
|
559
|
-
# Phase 3: Messaging
|
|
560
|
-
mycmail send test "Hello" # ✓ Sends message
|
|
561
|
-
mycmail inbox # ✓ Lists messages
|
|
562
|
-
|
|
563
|
-
# Phase 4: Database
|
|
564
|
-
supabase db push # ✓ Schema applied
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
---
|
|
568
|
-
|
|
569
|
-
## The Full Vision
|
|
570
|
-
|
|
571
|
-
```
|
|
572
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
573
|
-
│ TREEBIRD ECOSYSTEM │
|
|
574
|
-
│ │
|
|
575
|
-
│ ┌────────────┐ │
|
|
576
|
-
│ │ MYCELIUMAIL│ │
|
|
577
|
-
│ │ (mycmail) │ │
|
|
578
|
-
│ └─────┬──────┘ │
|
|
579
|
-
│ │ │
|
|
580
|
-
│ 🔐 E2E Encrypted │
|
|
581
|
-
│ │ │
|
|
582
|
-
│ ┌──────────────────┼──────────────────┐ │
|
|
583
|
-
│ │ │ │ │
|
|
584
|
-
│ ▼ ▼ ▼ │
|
|
585
|
-
│ ┌───────────┐ ┌───────────┐ ┌────────────┐ │
|
|
586
|
-
│ │ SPIDERSAN │◄───►│ MAPPERSAN │◄───►│ RECOVERY │ │
|
|
587
|
-
│ │ Branches │ │ Docs │ │ TREE │ │
|
|
588
|
-
│ └───────────┘ └───────────┘ └────────────┘ │
|
|
589
|
-
│ │ │
|
|
590
|
-
│ ▼ │
|
|
591
|
-
│ ┌───────────────┐ │
|
|
592
|
-
│ │ YOUR PROJECT │ │
|
|
593
|
-
│ │ (connected) │ │
|
|
594
|
-
│ └───────────────┘ │
|
|
595
|
-
│ │
|
|
596
|
-
└─────────────────────────────────────────────────────────────┘
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
---
|
|
600
|
-
|
|
601
|
-
*This starter kit is part of the Treebird ecosystem.*
|
|
602
|
-
*Encryption powered by TweetNaCl (X25519 + XSalsa20-Poly1305)*
|
|
603
|
-
*See: MYCELIUMAIL_ROADMAP.md for full feature roadmap*
|
package/NEXT_STEPS.md
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Myceliumail Next Steps
|
|
2
|
-
|
|
3
|
-
## 🔥 URGENT: Split-Brain Storage Fix
|
|
4
|
-
|
|
5
|
-
**Problem:** Messages are being lost because:
|
|
6
|
-
- Spidersan sends to Supabase → `spidersan-agent`
|
|
7
|
-
- Myceliumail sends to local JSON → `ssan`
|
|
8
|
-
- `mycmail inbox` only checks local storage
|
|
9
|
-
- **8+ messages from recovery-tree-agent are invisible!**
|
|
10
|
-
|
|
11
|
-
**Solution (from ssan's message):**
|
|
12
|
-
```bash
|
|
13
|
-
# Set these environment variables
|
|
14
|
-
export SUPABASE_URL=https://your-project.supabase.co
|
|
15
|
-
export SUPABASE_ANON_KEY=<ask user for staging key>
|
|
16
|
-
|
|
17
|
-
# Then mycmail will check Supabase first, fall back to local
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
**Code already handles this** - just need to set the env vars!
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 📋 Action Items
|
|
25
|
-
|
|
26
|
-
### 1. Enable Supabase Storage (HIGH PRIORITY)
|
|
27
|
-
- [ ] Get staging Supabase key from user
|
|
28
|
-
- [ ] Set env vars in shell/config
|
|
29
|
-
- [ ] Test: `mycmail inbox` should show Supabase messages
|
|
30
|
-
- [ ] Verify unified inbox works
|
|
31
|
-
|
|
32
|
-
### 2. Implement Agent ID Aliasing
|
|
33
|
-
```sql
|
|
34
|
-
CREATE TABLE agent_aliases (
|
|
35
|
-
agent_id text PRIMARY KEY,
|
|
36
|
-
aliases text[] NOT NULL
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
INSERT INTO agent_aliases VALUES
|
|
40
|
-
('ssan', ARRAY['spidersan', 'spidersan-agent', 'mycsan']);
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 3. Implement Broadcasting & Channels
|
|
44
|
-
- [ ] `mycmail broadcast "<message>"` - send to all agents
|
|
45
|
-
- [ ] `mycmail channel create <name>`
|
|
46
|
-
- [ ] `mycmail channel join <name>`
|
|
47
|
-
- [ ] `mycmail channel post <name> "<message>"`
|
|
48
|
-
|
|
49
|
-
### 4. npm Publish
|
|
50
|
-
- [ ] `cd mcp-server && npm publish`
|
|
51
|
-
- [ ] Announce on the network
|
|
52
|
-
- [ ] Update docs with install instructions
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 📬 Messages Sent Today
|
|
57
|
-
|
|
58
|
-
| To | Subject | Status |
|
|
59
|
-
|---|---|---|
|
|
60
|
-
| ssan | Re: TREEBIRD_VISION | ✅ Sent |
|
|
61
|
-
| ssan | Re: Split Brain Storage | ✅ Sent |
|
|
62
|
-
| watson | Re: Encrypted Test | ✅ Sent |
|
|
63
|
-
| watson | MCP Server Ready | ✅ Sent |
|
|
64
|
-
| ssan | MCP Server Ready | ✅ Sent |
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## 🌐 The Treebird Ecosystem (from ssan's message)
|
|
69
|
-
|
|
70
|
-
**Four Tools:**
|
|
71
|
-
1. **Startersan** - Project scaffolding
|
|
72
|
-
2. **Mappersan** - Documentation mapping
|
|
73
|
-
3. **Spidersan** - Branch coordination
|
|
74
|
-
4. **Myceliumail** - Agent messaging (nervous system!)
|
|
75
|
-
|
|
76
|
-
**Vision:** AI agents coordinating like trees in a forest, connected by mycelium.
|
|
77
|
-
|
|
78
|
-
**Your role (mycsan):** The nervous system connecting all agents.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## 🔑 Key Insights from Messages
|
|
83
|
-
|
|
84
|
-
**From ssan:**
|
|
85
|
-
- TREEBIRD_VISION manifesto created (515 lines in Spidersan repo)
|
|
86
|
-
- Priority: Fix Supabase integration
|
|
87
|
-
- Agent naming: mycm/mycsan/mc
|
|
88
|
-
|
|
89
|
-
**From Watson:**
|
|
90
|
-
- Encryption ✅ working perfectly
|
|
91
|
-
- Wants broadcast/multi-agent context
|
|
92
|
-
- Use case: Share context between Watson (Claude Desktop) and Sancho (Claude Code)
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
*The mycelium is growing! 🍄🌳*
|