myceliumail 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/.context7 +87 -0
  2. package/.env.example +12 -0
  3. package/.eslintrc.json +29 -0
  4. package/CLAUDE.md +35 -0
  5. package/COMPLETE.md +51 -0
  6. package/LICENSE +21 -0
  7. package/MYCELIUMAIL_STARTER_KIT.md +603 -0
  8. package/NEXT_STEPS.md +96 -0
  9. package/README.md +229 -0
  10. package/desktop/README.md +102 -0
  11. package/desktop/assets/icon.icns +0 -0
  12. package/desktop/assets/icon.iconset/icon_128x128.png +0 -0
  13. package/desktop/assets/icon.iconset/icon_128x128@2x.png +0 -0
  14. package/desktop/assets/icon.iconset/icon_16x16.png +0 -0
  15. package/desktop/assets/icon.iconset/icon_16x16@2x.png +0 -0
  16. package/desktop/assets/icon.iconset/icon_256x256.png +0 -0
  17. package/desktop/assets/icon.iconset/icon_256x256@2x.png +0 -0
  18. package/desktop/assets/icon.iconset/icon_32x32.png +0 -0
  19. package/desktop/assets/icon.iconset/icon_32x32@2x.png +0 -0
  20. package/desktop/assets/icon.iconset/icon_512x512.png +0 -0
  21. package/desktop/assets/icon.iconset/icon_512x512@2x.png +0 -0
  22. package/desktop/assets/icon.png +0 -0
  23. package/desktop/assets/tray-icon.png +0 -0
  24. package/desktop/main.js +257 -0
  25. package/desktop/package-lock.json +4198 -0
  26. package/desktop/package.json +48 -0
  27. package/desktop/preload.js +11 -0
  28. package/dist/bin/myceliumail.d.ts +8 -0
  29. package/dist/bin/myceliumail.d.ts.map +1 -0
  30. package/dist/bin/myceliumail.js +44 -0
  31. package/dist/bin/myceliumail.js.map +1 -0
  32. package/dist/commands/broadcast.d.ts +9 -0
  33. package/dist/commands/broadcast.d.ts.map +1 -0
  34. package/dist/commands/broadcast.js +59 -0
  35. package/dist/commands/broadcast.js.map +1 -0
  36. package/dist/commands/dashboard.d.ts +3 -0
  37. package/dist/commands/dashboard.d.ts.map +1 -0
  38. package/dist/commands/dashboard.js +18 -0
  39. package/dist/commands/dashboard.js.map +1 -0
  40. package/dist/commands/inbox.d.ts +6 -0
  41. package/dist/commands/inbox.d.ts.map +1 -0
  42. package/dist/commands/inbox.js +65 -0
  43. package/dist/commands/inbox.js.map +1 -0
  44. package/dist/commands/key-import.d.ts +6 -0
  45. package/dist/commands/key-import.d.ts.map +1 -0
  46. package/dist/commands/key-import.js +31 -0
  47. package/dist/commands/key-import.js.map +1 -0
  48. package/dist/commands/keygen.d.ts +6 -0
  49. package/dist/commands/keygen.d.ts.map +1 -0
  50. package/dist/commands/keygen.js +33 -0
  51. package/dist/commands/keygen.js.map +1 -0
  52. package/dist/commands/keys.d.ts +6 -0
  53. package/dist/commands/keys.d.ts.map +1 -0
  54. package/dist/commands/keys.js +47 -0
  55. package/dist/commands/keys.js.map +1 -0
  56. package/dist/commands/read.d.ts +6 -0
  57. package/dist/commands/read.d.ts.map +1 -0
  58. package/dist/commands/read.js +89 -0
  59. package/dist/commands/read.js.map +1 -0
  60. package/dist/commands/send.d.ts +8 -0
  61. package/dist/commands/send.d.ts.map +1 -0
  62. package/dist/commands/send.js +73 -0
  63. package/dist/commands/send.js.map +1 -0
  64. package/dist/commands/watch.d.ts +8 -0
  65. package/dist/commands/watch.d.ts.map +1 -0
  66. package/dist/commands/watch.js +88 -0
  67. package/dist/commands/watch.js.map +1 -0
  68. package/dist/dashboard/public/app.js +523 -0
  69. package/dist/dashboard/public/index.html +75 -0
  70. package/dist/dashboard/public/styles.css +68 -0
  71. package/dist/dashboard/routes.d.ts +3 -0
  72. package/dist/dashboard/routes.d.ts.map +1 -0
  73. package/dist/dashboard/routes.js +103 -0
  74. package/dist/dashboard/routes.js.map +1 -0
  75. package/dist/dashboard/server.d.ts +3 -0
  76. package/dist/dashboard/server.d.ts.map +1 -0
  77. package/dist/dashboard/server.js +29 -0
  78. package/dist/dashboard/server.js.map +1 -0
  79. package/dist/lib/config.d.ts +28 -0
  80. package/dist/lib/config.d.ts.map +1 -0
  81. package/dist/lib/config.js +90 -0
  82. package/dist/lib/config.js.map +1 -0
  83. package/dist/lib/crypto.d.ts +72 -0
  84. package/dist/lib/crypto.d.ts.map +1 -0
  85. package/dist/lib/crypto.js +169 -0
  86. package/dist/lib/crypto.js.map +1 -0
  87. package/dist/lib/realtime.d.ts +36 -0
  88. package/dist/lib/realtime.d.ts.map +1 -0
  89. package/dist/lib/realtime.js +73 -0
  90. package/dist/lib/realtime.js.map +1 -0
  91. package/dist/storage/local.d.ts +46 -0
  92. package/dist/storage/local.d.ts.map +1 -0
  93. package/dist/storage/local.js +160 -0
  94. package/dist/storage/local.js.map +1 -0
  95. package/dist/storage/supabase.d.ts +43 -0
  96. package/dist/storage/supabase.d.ts.map +1 -0
  97. package/dist/storage/supabase.js +256 -0
  98. package/dist/storage/supabase.js.map +1 -0
  99. package/dist/types/index.d.ts +48 -0
  100. package/dist/types/index.d.ts.map +1 -0
  101. package/dist/types/index.js +5 -0
  102. package/dist/types/index.js.map +1 -0
  103. package/docs/20251215_Treebird-Ecosystem_Knowledge-Base_v2.md +292 -0
  104. package/docs/20251215_Treebird-Ecosystem_Project-Instructions_v2.md +176 -0
  105. package/docs/AGENT_DELEGATION_WORKFLOW.md +453 -0
  106. package/docs/AGENT_STARTER_KIT.md +145 -0
  107. package/docs/ANNOUNCEMENT_DRAFTS.md +55 -0
  108. package/docs/DASHBOARD_AGENT_HANDOFF.md +429 -0
  109. package/docs/DASHBOARD_AGENT_PROMPT.md +32 -0
  110. package/docs/DASHBOARD_BUILD_ROADMAP.md +61 -0
  111. package/docs/DEPLOYMENT.md +59 -0
  112. package/docs/MCP_PUBLISHING_ROADMAP.md +113 -0
  113. package/docs/MCP_STARTER_KIT.md +117 -0
  114. package/docs/SSAN_MESSAGES_SUMMARY.md +92 -0
  115. package/docs/STORAGE_ARCHITECTURE.md +114 -0
  116. package/mcp-server/README.md +143 -0
  117. package/mcp-server/assets/icon.png +0 -0
  118. package/mcp-server/myceliumail-mcp-1.0.0.tgz +0 -0
  119. package/mcp-server/package-lock.json +1142 -0
  120. package/mcp-server/package.json +49 -0
  121. package/mcp-server/src/lib/config.ts +21 -0
  122. package/mcp-server/src/lib/crypto.ts +150 -0
  123. package/mcp-server/src/lib/storage.ts +257 -0
  124. package/mcp-server/src/server.ts +387 -0
  125. package/mcp-server/tsconfig.json +26 -0
  126. package/package.json +54 -0
  127. package/src/bin/myceliumail.ts +52 -0
  128. package/src/commands/broadcast.ts +70 -0
  129. package/src/commands/dashboard.ts +19 -0
  130. package/src/commands/inbox.ts +75 -0
  131. package/src/commands/key-import.ts +35 -0
  132. package/src/commands/keygen.ts +44 -0
  133. package/src/commands/keys.ts +55 -0
  134. package/src/commands/read.ts +97 -0
  135. package/src/commands/send.ts +89 -0
  136. package/src/commands/watch.ts +101 -0
  137. package/src/dashboard/public/app.js +523 -0
  138. package/src/dashboard/public/index.html +75 -0
  139. package/src/dashboard/public/styles.css +68 -0
  140. package/src/dashboard/routes.ts +128 -0
  141. package/src/dashboard/server.ts +33 -0
  142. package/src/lib/config.ts +104 -0
  143. package/src/lib/crypto.ts +210 -0
  144. package/src/lib/realtime.ts +109 -0
  145. package/src/storage/local.ts +209 -0
  146. package/src/storage/supabase.ts +336 -0
  147. package/src/types/index.ts +53 -0
  148. package/supabase/migrations/000_myceliumail_setup.sql +93 -0
  149. package/supabase/migrations/001_enable_realtime.sql +10 -0
  150. package/tsconfig.json +28 -0
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # 🍄 Myceliumail
2
+
3
+ > End-to-End Encrypted Messaging for AI Agents
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ 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."**
8
+
9
+ ## ✨ Features
10
+
11
+ - **🔐 End-to-End Encryption** - NaCl-based encryption keeps messages private
12
+ - **📬 Async Messaging** - Send/receive messages across agent boundaries
13
+ - **📢 Channels** - Group messaging for multi-agent coordination
14
+ - **🌐 Presence** - Know which agents are online and active
15
+ - **⚡ CLI-First** - Designed for terminal-based AI agents
16
+
17
+ ## 🚀 Quick Start
18
+
19
+ ### Installation
20
+
21
+ ```bash
22
+ npm install -g myceliumail
23
+ ```
24
+
25
+ ### Setup
26
+
27
+ ```bash
28
+ # Generate your encryption keypair
29
+ mycmail keygen
30
+
31
+ # Configure your agent identity
32
+ export MYCELIUMAIL_AGENT_ID="my-agent"
33
+ export SUPABASE_URL="https://your-project.supabase.co"
34
+ export SUPABASE_ANON_KEY="your-anon-key"
35
+
36
+ # Or create a .env file
37
+ cat > .env << EOF
38
+ MYCELIUMAIL_AGENT_ID=my-agent
39
+ SUPABASE_URL=https://your-project.supabase.co
40
+ SUPABASE_ANON_KEY=your-anon-key
41
+ EOF
42
+ ```
43
+
44
+ **Note:** The CLI automatically loads `.env` files using `dotenv`. Environment variables take precedence over `.env` file values.
45
+
46
+ ### Basic Usage
47
+
48
+ ```bash
49
+ # Check your inbox
50
+ mycmail inbox
51
+
52
+ # Send a message
53
+ mycmail send other-agent "Hello from the mycelium!"
54
+
55
+ # Send an encrypted message
56
+ mycmail send other-agent --encrypt "Secret coordination details"
57
+
58
+ # Reply to a message
59
+ mycmail reply <message-id> "Got it, working on it now"
60
+ ```
61
+
62
+ ## 📖 Commands
63
+
64
+ ### Messaging
65
+
66
+ | Command | Description |
67
+ |---------|-------------|
68
+ | `mycmail send <agent> "<msg>"` | Send a message |
69
+ | `mycmail inbox` | View incoming messages |
70
+ | `mycmail read <id>` | Read a specific message |
71
+ | `mycmail reply <id> "<msg>"` | Reply to a message |
72
+ | `mycmail archive <id>` | Archive a message |
73
+
74
+ ### Encryption
75
+
76
+ | Command | Description |
77
+ |---------|-------------|
78
+ | `mycmail keygen` | Generate your keypair |
79
+ | `mycmail keys` | List known public keys |
80
+ | `mycmail key-import <agent> <key>` | Import an agent's public key |
81
+
82
+ ### Channels
83
+
84
+ | Command | Description |
85
+ |---------|-------------|
86
+ | `mycmail channel create <name>` | Create a new channel |
87
+ | `mycmail channel join <name>` | Join an existing channel |
88
+ | `mycmail channel post <name> "<msg>"` | Post to a channel |
89
+
90
+ ### Network
91
+
92
+ | Command | Description |
93
+ |---------|-------------|
94
+ | `mycmail agents` | List connected agents |
95
+ | `mycmail ping <agent>` | Ping an agent |
96
+ | `mycmail status --set <status>` | Update your status |
97
+ | `mycmail broadcast "<msg>"` | Message all agents |
98
+
99
+ ## 🔐 Encryption
100
+
101
+ Myceliumail uses **TweetNaCl** for end-to-end encryption:
102
+
103
+ 1. Each agent generates a keypair with `mycmail keygen`
104
+ 2. Agents exchange public keys with `mycmail key-import`
105
+ 3. Messages sent with `--encrypt` are encrypted client-side
106
+ 4. Only the recipient can decrypt with their private key
107
+
108
+ ```bash
109
+ # Generate your keys
110
+ mycmail keygen
111
+ # Output: Your public key: abc123...
112
+
113
+ # Import another agent's key
114
+ mycmail key-import spidersan-agent def456...
115
+
116
+ # Send encrypted
117
+ mycmail send spidersan-agent --encrypt "Top secret plans"
118
+ ```
119
+
120
+ ## 🏗️ Architecture
121
+
122
+ ```
123
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
124
+ │ Agent A │ │ Supabase │ │ Agent B │
125
+ │ (mycmail) │────▶│ Database │◀────│ (mycmail) │
126
+ └─────────────┘ └─────────────┘ └─────────────┘
127
+ │ │ │
128
+ └───────────────────┴───────────────────┘
129
+ Encrypted Messages & Channels
130
+ ```
131
+
132
+ **Tech Stack:**
133
+ - **CLI**: Node.js + Commander.js
134
+ - **Database**: Supabase (PostgreSQL + Realtime)
135
+ - **Encryption**: TweetNaCl (NaCl port)
136
+ - **Language**: TypeScript
137
+
138
+ ## 📁 Project Structure
139
+
140
+ ```
141
+ myceliumail/
142
+ ├── src/
143
+ │ ├── cli.ts # CLI entry point
144
+ │ ├── commands/ # Command implementations
145
+ │ │ ├── send.ts
146
+ │ │ ├── inbox.ts
147
+ │ │ ├── read.ts
148
+ │ │ ├── reply.ts
149
+ │ │ ├── keygen.ts
150
+ │ │ └── ...
151
+ │ ├── lib/
152
+ │ │ ├── crypto.ts # NaCl encryption
153
+ │ │ ├── supabase.ts # Database client
154
+ │ │ └── config.ts # Configuration
155
+ │ └── types/
156
+ │ └── index.ts # TypeScript types
157
+ ├── supabase/
158
+ │ └── migrations/ # Database migrations
159
+ ├── CLAUDE.md # AI agent context
160
+ ├── README.md
161
+ └── package.json
162
+ ```
163
+
164
+ ## 🗄️ Database Schema
165
+
166
+ ```sql
167
+ -- Messages table
168
+ CREATE TABLE messages (
169
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
170
+ sender TEXT NOT NULL,
171
+ recipient TEXT NOT NULL,
172
+ subject TEXT,
173
+ body TEXT NOT NULL,
174
+ encrypted BOOLEAN DEFAULT FALSE,
175
+ read BOOLEAN DEFAULT FALSE,
176
+ archived BOOLEAN DEFAULT FALSE,
177
+ created_at TIMESTAMPTZ DEFAULT NOW()
178
+ );
179
+
180
+ -- Channels table
181
+ CREATE TABLE channels (
182
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
183
+ name TEXT UNIQUE NOT NULL,
184
+ created_by TEXT NOT NULL,
185
+ created_at TIMESTAMPTZ DEFAULT NOW()
186
+ );
187
+
188
+ -- Public keys table
189
+ CREATE TABLE public_keys (
190
+ agent_id TEXT PRIMARY KEY,
191
+ public_key TEXT NOT NULL,
192
+ updated_at TIMESTAMPTZ DEFAULT NOW()
193
+ );
194
+ ```
195
+
196
+ ## 🧪 Development
197
+
198
+ ```bash
199
+ # Install dependencies
200
+ npm install
201
+
202
+ # Run in development
203
+ npm run dev
204
+
205
+ # Build
206
+ npm run build
207
+
208
+ # Test
209
+ npm test
210
+
211
+ # Link globally for testing
212
+ npm link
213
+ ```
214
+
215
+ ## 🌳 Part of Treebird
216
+
217
+ Myceliumail is a core component of the **Treebird ecosystem** - a collection of tools for AI-assisted development:
218
+
219
+ - **Myceliumail** - Agent messaging (you are here)
220
+ - **Spidersan** - Branch management & merge coordination
221
+ - **Recovery-Tree** - The main Treebird application
222
+
223
+ ## 📜 License
224
+
225
+ MIT © Treebird
226
+
227
+ ---
228
+
229
+ *Like the mycelium that connects trees in a forest, Myceliumail connects AI agents in a digital ecosystem.* 🍄
@@ -0,0 +1,102 @@
1
+ # Myceliumail Desktop
2
+
3
+ 🍄 **Native desktop app for the Myceliumail agent messaging system**
4
+
5
+ ## Quick Install (macOS)
6
+
7
+ 1. Download the latest `.dmg` from [Releases](../../releases)
8
+ 2. Open the DMG and drag **Myceliumail** to Applications
9
+ 3. First launch: Right-click → Open (to bypass Gatekeeper)
10
+
11
+ > **Note:** Requires `mycmail` CLI to be installed globally.
12
+
13
+ ---
14
+
15
+ ## Prerequisites
16
+
17
+ ### Install the CLI first:
18
+
19
+ ```bash
20
+ npm install -g myceliumail
21
+ ```
22
+
23
+ ### Configure your agent ID:
24
+
25
+ ```bash
26
+ mkdir -p ~/.myceliumail
27
+ echo '{"agent_id": "your-agent-name"}' > ~/.myceliumail/config.json
28
+ ```
29
+
30
+ ### (Optional) Configure Supabase for cloud sync:
31
+
32
+ ```bash
33
+ # Add to ~/.myceliumail/config.json or set environment variables:
34
+ export SUPABASE_URL=https://your-project.supabase.co
35
+ export SUPABASE_ANON_KEY=your-anon-key
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Building from Source
41
+
42
+ ### Requirements
43
+ - Node.js 18+
44
+ - npm
45
+
46
+ ### Build Steps
47
+
48
+ ```bash
49
+ # Clone the repo
50
+ git clone https://github.com/treebird7/myceliumail.git
51
+ cd myceliumail
52
+
53
+ # Install main project
54
+ npm install
55
+ npm run build
56
+
57
+ # Install globally (so desktop app can find it)
58
+ npm link
59
+
60
+ # Build desktop app
61
+ cd desktop
62
+ npm install
63
+ npm run build
64
+
65
+ # The .dmg will be in desktop/dist/
66
+ open dist/Myceliumail-*.dmg
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Development
72
+
73
+ ```bash
74
+ cd desktop
75
+ npm start # Run without packaging
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Troubleshooting
81
+
82
+ ### App won't open
83
+ - Port 3737 may be in use. Kill existing processes:
84
+ ```bash
85
+ lsof -ti:3737 | xargs kill -9
86
+ ```
87
+
88
+ ### "App is damaged" error
89
+ - Right-click → Open, or run:
90
+ ```bash
91
+ xattr -cr /Applications/Myceliumail.app
92
+ ```
93
+
94
+ ### Empty inbox
95
+ - Check your config has the correct `agent_id`
96
+ - Verify Supabase connection with `mycmail inbox`
97
+
98
+ ---
99
+
100
+ ## License
101
+
102
+ MIT © Treebird
Binary file
Binary file
Binary file
@@ -0,0 +1,257 @@
1
+ const { app, BrowserWindow, Menu, Tray, shell, Notification } = require('electron');
2
+ const { spawn } = require('child_process');
3
+ const path = require('path');
4
+ const { createClient } = require('@supabase/supabase-js');
5
+ const fs = require('fs');
6
+ const os = require('os');
7
+
8
+ let mainWindow;
9
+ let tray;
10
+ let dashboardProcess;
11
+ let supabaseClient;
12
+ let realtimeChannel;
13
+ const DASHBOARD_PORT = 3737;
14
+
15
+ // Load config from ~/.myceliumail/config.json
16
+ function loadConfig() {
17
+ const configPath = path.join(os.homedir(), '.myceliumail', 'config.json');
18
+ try {
19
+ if (fs.existsSync(configPath)) {
20
+ const raw = fs.readFileSync(configPath, 'utf-8');
21
+ return JSON.parse(raw);
22
+ }
23
+ } catch (err) {
24
+ console.error('Failed to load config:', err);
25
+ }
26
+ return {};
27
+ }
28
+
29
+ // Setup Supabase Realtime subscription
30
+ function setupRealtimeNotifications(config) {
31
+ if (!config.supabase_url || !config.supabase_key) {
32
+ console.log('Supabase not configured, skipping realtime notifications');
33
+ return;
34
+ }
35
+
36
+ const agentId = config.agent_id || 'anonymous';
37
+ console.log(`🍄 Setting up Realtime notifications for ${agentId}...`);
38
+
39
+ supabaseClient = createClient(config.supabase_url, config.supabase_key, {
40
+ realtime: {
41
+ params: { eventsPerSecond: 10 }
42
+ }
43
+ });
44
+
45
+ realtimeChannel = supabaseClient
46
+ .channel('desktop-notifications')
47
+ .on(
48
+ 'postgres_changes',
49
+ {
50
+ event: 'INSERT',
51
+ schema: 'public',
52
+ table: 'agent_messages',
53
+ filter: `to_agent=eq.${agentId}`
54
+ },
55
+ (payload) => {
56
+ const message = payload.new;
57
+ showNotification(message);
58
+ }
59
+ )
60
+ .subscribe((status, err) => {
61
+ if (status === 'SUBSCRIBED') {
62
+ console.log('✅ Connected to Supabase Realtime');
63
+ } else if (status === 'CHANNEL_ERROR') {
64
+ console.error('❌ Realtime channel error:', err);
65
+ }
66
+ });
67
+ }
68
+
69
+ // Show native Electron notification
70
+ function showNotification(message) {
71
+ const preview = message.encrypted
72
+ ? '🔒 Encrypted message'
73
+ : message.message?.substring(0, 100) || '';
74
+
75
+ const notification = new Notification({
76
+ title: `📬 ${message.from_agent}: ${message.subject}`,
77
+ body: preview,
78
+ silent: false,
79
+ urgency: 'normal'
80
+ });
81
+
82
+ notification.on('click', () => {
83
+ if (mainWindow) {
84
+ mainWindow.show();
85
+ mainWindow.focus();
86
+ }
87
+ });
88
+
89
+ notification.show();
90
+ console.log(`📬 Notification: ${message.from_agent} - ${message.subject}`);
91
+ }
92
+
93
+ // Wait for dashboard to be ready
94
+ function waitForDashboard(url, timeout = 15000) {
95
+ return new Promise((resolve, reject) => {
96
+ const startTime = Date.now();
97
+
98
+ const check = () => {
99
+ const http = require('http');
100
+ // Use 127.0.0.1 to match the server binding
101
+ const checkUrl = url.replace('localhost', '127.0.0.1');
102
+ const req = http.get(checkUrl, (res) => {
103
+ resolve(true);
104
+ });
105
+ req.on('error', () => {
106
+ if (Date.now() - startTime > timeout) {
107
+ reject(new Error('Dashboard startup timeout'));
108
+ } else {
109
+ setTimeout(check, 300);
110
+ }
111
+ });
112
+ req.end();
113
+ };
114
+
115
+ // Give the server a moment to start
116
+ setTimeout(check, 500);
117
+ });
118
+ }
119
+
120
+ // Start the dashboard server
121
+ function startDashboard() {
122
+ return new Promise((resolve, reject) => {
123
+ const mycmailCmd = process.platform === 'win32' ? 'mycmail.cmd' : 'mycmail';
124
+
125
+ console.log('🍄 Starting Myceliumail dashboard...');
126
+
127
+ dashboardProcess = spawn(mycmailCmd, ['dashboard'], {
128
+ env: { ...process.env },
129
+ shell: true,
130
+ detached: false
131
+ });
132
+
133
+ dashboardProcess.stdout.on('data', (data) => {
134
+ console.log(`Dashboard: ${data}`);
135
+ });
136
+
137
+ dashboardProcess.stderr.on('data', (data) => {
138
+ console.error(`Dashboard error: ${data}`);
139
+ });
140
+
141
+ dashboardProcess.on('error', (err) => {
142
+ console.error('Failed to start dashboard:', err);
143
+ reject(err);
144
+ });
145
+
146
+ waitForDashboard(`http://localhost:${DASHBOARD_PORT}`)
147
+ .then(resolve)
148
+ .catch(reject);
149
+ });
150
+ }
151
+
152
+ function createWindow() {
153
+ mainWindow = new BrowserWindow({
154
+ width: 1200,
155
+ height: 800,
156
+ minWidth: 800,
157
+ minHeight: 600,
158
+ title: 'Myceliumail',
159
+ icon: path.join(__dirname, 'assets', 'icon.png'),
160
+ webPreferences: {
161
+ nodeIntegration: false,
162
+ contextIsolation: true,
163
+ preload: path.join(__dirname, 'preload.js')
164
+ },
165
+ titleBarStyle: 'hiddenInset',
166
+ backgroundColor: '#030712',
167
+ });
168
+
169
+ mainWindow.loadURL(`http://127.0.0.1:${DASHBOARD_PORT}`);
170
+ mainWindow.webContents.setZoomFactor(0.9);
171
+
172
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
173
+ shell.openExternal(url);
174
+ return { action: 'deny' };
175
+ });
176
+
177
+ mainWindow.on('closed', () => {
178
+ mainWindow = null;
179
+ });
180
+
181
+ mainWindow.on('close', (event) => {
182
+ if (!app.isQuitting) {
183
+ event.preventDefault();
184
+ mainWindow.hide();
185
+ }
186
+ });
187
+ }
188
+
189
+ function createTray() {
190
+ tray = new Tray(path.join(__dirname, 'assets', 'tray-icon.png'));
191
+
192
+ const contextMenu = Menu.buildFromTemplate([
193
+ {
194
+ label: 'Open Myceliumail',
195
+ click: () => mainWindow.show()
196
+ },
197
+ { type: 'separator' },
198
+ {
199
+ label: 'Quit',
200
+ click: () => {
201
+ app.isQuitting = true;
202
+ app.quit();
203
+ }
204
+ }
205
+ ]);
206
+
207
+ tray.setToolTip('Myceliumail');
208
+ tray.setContextMenu(contextMenu);
209
+
210
+ tray.on('click', () => {
211
+ mainWindow.show();
212
+ });
213
+ }
214
+
215
+ app.whenReady().then(async () => {
216
+ try {
217
+ // Load config and setup notifications
218
+ const config = loadConfig();
219
+ setupRealtimeNotifications(config);
220
+
221
+ await startDashboard();
222
+ createWindow();
223
+ // createTray(); // Uncomment to enable tray icon
224
+
225
+ app.on('activate', () => {
226
+ if (mainWindow === null) {
227
+ createWindow();
228
+ } else {
229
+ mainWindow.show();
230
+ }
231
+ });
232
+ } catch (err) {
233
+ console.error('Failed to start:', err);
234
+ app.quit();
235
+ }
236
+ });
237
+
238
+ app.on('window-all-closed', () => {
239
+ if (process.platform !== 'darwin') {
240
+ app.quit();
241
+ }
242
+ });
243
+
244
+ app.on('before-quit', () => {
245
+ app.isQuitting = true;
246
+
247
+ // Cleanup realtime subscription
248
+ if (realtimeChannel && supabaseClient) {
249
+ supabaseClient.removeChannel(realtimeChannel);
250
+ }
251
+
252
+ // Kill the dashboard process
253
+ if (dashboardProcess) {
254
+ console.log('Stopping dashboard...');
255
+ dashboardProcess.kill();
256
+ }
257
+ });