morpheus-cli 0.3.4 → 0.3.7

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/README.md CHANGED
@@ -1,999 +1,1010 @@
1
- <div align="center">
2
- <img src="./assets/logo.png" alt="Morpheus Logo" width="220" />
3
- </div>
4
-
5
- # Morpheus
6
-
7
- > **Morpheus is a local-first AI operator that bridges developers and machines.**
8
-
9
- Morpheus is a local AI agent for developers, running as a CLI daemon that connects to **LLMs**, **local tools**, and **MCPs**, enabling interaction via **Terminal, Telegram, and Discord**. Inspired by the character Morpheus from *The Matrix*, the project acts as an **intelligent orchestrator**, bridging the gap between the developer and complex systems.
10
-
11
- ## Installation
12
-
13
- Install Morpheus globally via npm:
14
-
15
- ```bash
16
- npm install -g morpheus-cli
17
- ```
18
-
19
- ## Quick Start
20
-
21
- ### 1. Initialize
22
-
23
- Set up your configuration (API keys, preferences):
24
-
25
- ```bash
26
- morpheus init
27
- ```
28
-
29
- ### 2. Start the Agent
30
-
31
- Run the background daemon and Web UI:
32
-
33
- ```bash
34
- morpheus start
35
- ```
36
-
37
- This will:
38
- - Start the agent process
39
- - Launch the Web UI at http://localhost:3333
40
-
41
- ### Other Commands
42
-
43
- ```bash
44
- # Check if Morpheus is running
45
- morpheus status
46
-
47
- # Stop the agent
48
- morpheus stop
49
-
50
- # Restart the agent
51
- morpheus restart
52
-
53
- # Diagnose issues
54
- morpheus doctor
55
-
56
- # Manage sessions
57
- morpheus session new # Archive current and start new
58
- morpheus session status # Check current session info
59
- ```
60
-
61
- ## Troubleshooting
62
-
63
- ### Command not found
64
-
65
- If you installed successfully but can't run the `morpheus` command:
66
-
67
- 1. **Check your PATH**: Ensure your global npm bin directory is in your system PATH.
68
- - Run `npm bin -g` to see the folder.
69
- - On Windows, this is usually `%APPDATA%\npm`.
70
- - On Linux/Mac, verify `echo $PATH`.
71
- 2. **Restart Terminal**: New installations might not be visible until you restart your shell.
72
-
73
- ## Using NPX
74
- You can run Morpheus without installing it globally using `npx`:
75
-
76
- ```bash
77
-
78
- npx morpheus-cli init
79
-
80
- npx morpheus-cli start
81
-
82
- ```
83
-
84
- ## Technical Overview
85
-
86
- Morpheus is built with **Node.js** and **TypeScript**, using **LangChain** as the orchestration engine. It runs as a background daemon process, managing connections to LLM providers (OpenAI, Anthropic, Ollama) and external channels (Telegram, Discord).
87
-
88
- ### Core Components
89
-
90
- - **Runtime (`src/runtime/`)**: The heart of the application. Manages the Oracle (agent) lifecycle, provider instantiation, and command execution.
91
- - **CLI (`src/cli/`)**: Built with `commander`, handles user interaction, configuration, and daemon control (`start`, `stop`, `status`).
92
- - **Configuration (`src/config/`)**: Singleton-based configuration manager using `zod` for validation and `js-yaml` for persistence (`~/.morpheus/zaion.yaml`).
93
- - **Channels (`src/channels/`)**: Adapters for external communication. Currently supports Telegram (`telegraf`) with strict user whitelisting.
94
-
95
- ## Features
96
-
97
- ### 🖥️ Web Dashboard
98
- Local React-based UI to manage recordings, chat history, and system status across your agent instances.
99
-
100
- **New: Interactive Web Chat**
101
- - Full-featured chat interface accessible from the browser
102
- - Session management: create, archive, delete, and rename sessions
103
- - Cross-channel visibility: view and interact with sessions started on any channel (Telegram, Web, etc.)
104
- - Real-time messaging with the Oracle agent
105
- - Responsive design with collapsible sidebar
106
- - Full support for Light and Dark (Matrix) themes
107
-
108
- #### 🔒 UI Authentication
109
- To protect your Web UI, use the `THE_ARCHITECT_PASS` environment variable. This ensures only authorized users can access the dashboard and API.
110
-
111
- Additionally, you can use environment variables for API keys instead of storing them in the configuration file:
112
-
113
- | Variable | Description | Required |
114
- |----------|-------------|----------|
115
- | `OPENAI_API_KEY` | OpenAI API key (if using GPT) | No |
116
- | `ANTHROPIC_API_KEY` | Anthropic API key (if using Claude) | No |
117
- | `GOOGLE_API_KEY` | Google AI key (for Gemini LLM/Audio) | No |
118
- | `OPENROUTER_API_KEY` | OpenRouter API key (if using OpenRouter) | No |
119
- | `THE_ARCHITECT_PASS` | Web Dashboard access password | Recommended |
120
- | `TELEGRAM_BOT_TOKEN` | Telegram BotFather token | No |
121
-
122
- If these environment variables are set, they will take precedence over values stored in the configuration file.
123
-
124
- The system also supports generic environment variables that apply to all providers:
125
-
126
- | Variable | Description | Applies To |
127
- |----------|-------------|------------|
128
- | `MORPHEUS_AGENT_NAME` | Name of the agent | agent.name |
129
- | `MORPHEUS_AGENT_PERSONALITY` | Personality of the agent | agent.personality |
130
- | `MORPHEUS_LLM_PROVIDER` | LLM provider to use | llm.provider |
131
- | `MORPHEUS_LLM_MODEL` | Model name for LLM | llm.model |
132
- | `MORPHEUS_LLM_TEMPERATURE` | Temperature setting for LLM | llm.temperature |
133
- | `MORPHEUS_LLM_MAX_TOKENS` | Maximum tokens for LLM | llm.max_tokens |
134
- | `MORPHEUS_LLM_CONTEXT_WINDOW` | Context window size for LLM | llm.context_window |
135
- | `MORPHEUS_LLM_API_KEY` | Generic API key for LLM (lower precedence than provider-specific keys) | llm.api_key |
136
- | `MORPHEUS_SATI_PROVIDER` | Sati provider to use | santi.provider |
137
- | `MORPHEUS_SATI_MODEL` | Model name for Sati | santi.model |
138
- | `MORPHEUS_SATI_TEMPERATURE` | Temperature setting for Sati | santi.temperature |
139
- | `MORPHEUS_SATI_MAX_TOKENS` | Maximum tokens for Sati | santi.max_tokens |
140
- | `MORPHEUS_SATI_CONTEXT_WINDOW` | Context window size for Sati | santi.context_window |
141
- | `MORPHEUS_SATI_API_KEY` | Generic API key for Sati (lower precedence than provider-specific keys) | santi.api_key |
142
- | `MORPHEUS_SATI_MEMORY_LIMIT` | Memory retrieval limit for Sati | santi.memory_limit |
143
- | `MORPHEUS_SATI_MEMORY_LIMIT` | Memory retrieval limit for Sati | santi.memory_limit |
144
- | `MORPHEUS_SATI_ENABLED_ARCHIVED_SESSIONS`| Enable/disable retrieval of archived sessions in Sati | santi.enableArchivedSessions |
145
- | `MORPHEUS_AUDIO_MODEL` | Model name for audio processing | audio.model |
146
- | `MORPHEUS_AUDIO_ENABLED` | Enable/disable audio processing | audio.enabled |
147
- | `MORPHEUS_AUDIO_API_KEY` | Generic API key for audio (lower precedence than provider-specific keys) | audio.apiKey |
148
- | `MORPHEUS_AUDIO_MAX_DURATION` | Max duration for audio processing | audio.maxDurationSeconds |
149
- | `MORPHEUS_TELEGRAM_ENABLED` | Enable/disable Telegram channel | channels.telegram.enabled |
150
- | `MORPHEUS_TELEGRAM_TOKEN` | Telegram bot token | channels.telegram.token |
151
- | `MORPHEUS_TELEGRAM_ALLOWED_USERS` | Comma-separated list of allowed Telegram user IDs | channels.telegram.allowedUsers |
152
- | `MORPHEUS_UI_ENABLED` | Enable/disable Web UI | ui.enabled |
153
- | `MORPHEUS_UI_PORT` | Port for Web UI | ui.port |
154
- | `MORPHEUS_LOGGING_ENABLED` | Enable/disable logging | logging.enabled |
155
- | `MORPHEUS_LOGGING_LEVEL` | Logging level | logging.level |
156
- | `MORPHEUS_LOGGING_RETENTION` | Log retention period | logging.retention |
157
-
158
- **Precedence Order**: The system follows this order of precedence when resolving configuration values:
159
- 1. Provider-specific environment variable (e.g., `OPENAI_API_KEY`) - Highest priority
160
- 2. Generic environment variable (e.g., `MORPHEUS_LLM_API_KEY`) - Medium priority
161
- 3. Configuration file value (e.g., `config.llm.api_key`) - Lower priority
162
- 4. Default value - Lowest priority
163
-
164
- > **Note**: If `THE_ARCHITECT_PASS` is not set, the system will use the default password `iamthearchitect`. This is less secure and it's recommended to set your own password in production environments.
165
-
166
- **Option 1: Using a `.env` file**
167
- Create a `.env` file in the root of your project:
168
-
169
- ```env
170
- OPENAI_API_KEY="your-openai-api-key"
171
- ANTHROPIC_API_KEY="your-anthropic-api-key"
172
- GOOGLE_API_KEY="your-google-api-key"
173
- THE_ARCHITECT_PASS="your-secure-password"
174
- TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
175
- OPENROUTER_API_KEY="your-openrouter-api-key"
176
- ```
177
-
178
- **Option 2: Using Shell export**
179
-
180
- ```bash
181
- export OPENAI_API_KEY="your-openai-api-key"
182
- export ANTHROPIC_API_KEY="your-anthropic-api-key"
183
- export GOOGLE_API_KEY="your-google-api-key"
184
- export OPENROUTER_API_KEY="your-openrouter-api-key"
185
- export THE_ARCHITECT_PASS="your-secure-password"
186
- export TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
187
- morpheus start
188
- ```
189
-
190
- When enabled:
191
- - The Web UI will redirect to a Login page.
192
- - API requests require the `x-architect-pass` header.
193
- - The session is persisted locally in your browser.
194
-
195
- ### 🧩 MCP Support (Model Context Protocol)
196
- Full integration with [Model Context Protocol](https://modelcontextprotocol.io/), allowing Morpheus to use standardized tools from any MCP-compatible server.
197
-
198
- ### 🧠 Sati (Long-Term Memory)
199
- Morpheus features a dedicated middleware system called **Sati** (Mindfulness) that provides long-term memory capabilities.
200
- - **Automated Storage**: Automatically extracts and saves preferences, project details, and facts from conversations.
201
- - **Contextual Retrieval**: Injects relevant memories into the context based on your current query.
202
- - **Data Privacy**: Stored in a local, independent SQLite database (`santi-memory.db`), ensuring sensitive data is handled securely and reducing context window usage.
203
- - **Memory Management**: View and manage your long-term memories through the Web UI or via API endpoints.
204
-
205
- ### 📊 Usage Analytics
206
- Track your token usage across different providers and models directly from the Web UI. View detailed breakdowns of input/output tokens and message counts to monitor costs and activity.
207
-
208
- ### 🎙️ Audio Transcription (Telegram)
209
- Send voice messages directly to the Telegram bot. Morpheus will:
210
- 1. Transcribe the audio using the configured provider.
211
- 2. Process the text as a standard prompt.
212
- 3. Reply with the answer.
213
-
214
- Supported audio providers:
215
-
216
- | Provider | Method | Model example |
217
- |---|---|---|
218
- | **Google Gemini** | Native audio file upload | `gemini-2.5-flash-lite` |
219
- | **OpenAI** | Whisper API (`/audio/transcriptions`) | `whisper-1` |
220
- | **OpenRouter** | `input_audio` via `@openrouter/sdk` (multimodal models) | `google/gemini-2.5-flash` |
221
- | **Ollama** | Whisper local via OpenAI-compatible endpoint | `whisper` |
222
-
223
- > Ollama requires a Whisper model loaded: `ollama pull whisper`
224
-
225
- *Configure `audio.provider` and `audio.apiKey` in Settings or `config.yaml`.*
226
-
227
- ### 🤖 Telegram Commands
228
- The Morpheus Telegram bot supports several commands for interacting with the agent:
229
-
230
- - `/start` - Show welcome message and available commands
231
- - `/status` - Check the status of the Morpheus agent
232
- - `/doctor` - Diagnose environment and configuration issues
233
- - `/stats` - Show token usage statistics
234
- - `/help` - Show available commands
235
- - `/zaion` - Show system configurations
236
- - `/sati <qnt>` - Show specific memories
237
- - `/newsession` - Archive current session and start fresh
238
- - `/sessions` - List all sessions with options to switch, archive, or delete
239
- - `/restart` - Restart the Morpheus agent
240
- - `/mcp` or `/mcps` - List registered MCP servers
241
-
242
- ## Development Setup
243
-
244
- This guide is for developers contributing to the Morpheus codebase.
245
-
246
- ### Prerequisites
247
-
248
- - **Node.js**: >= 18.x
249
- - **npm**: >= 9.x
250
- - **TypeScript**: >= 5.x
251
-
252
- ### 1. Clone & Install
253
-
254
- ```bash
255
- git clone https://github.com/your-org/morpheus.git
256
- cd morpheus
257
- npm install
258
- ```
259
-
260
- ### 2. Build
261
-
262
- Compile TypeScript source to `dist/` and build the Web UI.
263
-
264
- ```bash
265
- npm run build
266
- ```
267
-
268
- ### 3. Run the CLI
269
-
270
- You can run the CLI directly from the source using `npm start`.
271
-
272
- ```bash
273
- # Initialize configuration (creates ~/.morpheus)
274
- npm start -- init
275
-
276
- # Start the daemon
277
- npm start -- start
278
-
279
- # Check status
280
- npm start -- status
281
- ```
282
-
283
- ### 4. Configuration
284
-
285
- The configuration file is located at `~/.morpheus/zaion.yaml`. You can edit it manually or use the `morpheus config` command.
286
-
287
- ```yaml
288
- agent:
289
- name: "Morpheus"
290
- personality: "stoic, wise, and helpful"
291
- llm:
292
- provider: "openai" # options: openai, anthropic, ollama, gemini
293
- model: "gpt-4-turbo"
294
- temperature: 0.7
295
- context_window: 100 # Number of messages to load into LLM context
296
- api_key: "sk-..."
297
- santi: # Optional: Sati (Long-Term Memory) specific settings
298
- provider: "openai" # defaults to llm.provider
299
- model: "gpt-4o"
300
- memory_limit: 1000 # Number of messages/items to retrieve
301
- channels:
302
- telegram:
303
- enabled: true
304
- token: "YOUR_TELEGRAM_BOT_TOKEN"
305
- allowedUsers: ["123456789"] # Your Telegram User ID
306
- discord:
307
- enabled: false # Coming soon
308
-
309
- # Web UI Dashboard
310
- ui:
311
- enabled: true
312
- port: 3333
313
-
314
- # Audio Transcription Support
315
- audio:
316
- enabled: true
317
- provider: "google" # google | openai | openrouter | anthropic | ollama
318
- model: "gemini-2.5-flash-lite"
319
- apiKey: "YOUR_API_KEY" # Optional if using same provider as LLM
320
- base_url: "" # Required for openrouter/ollama
321
- maxDurationSeconds: 300
322
- ```
323
-
324
- ### 5. MCP Configuration
325
-
326
- Morpheus supports external tools via **MCP (Model Context Protocol)**. Configure your MCP servers in `~/.morpheus/mcps.json`:
327
-
328
- ```json
329
- {
330
- "coolify": {
331
- "transport": "stdio",
332
- "command": "npx",
333
- "args": ["-y", "@coolify/mcp-server"],
334
- "env": {
335
- "COOLIFY_URL": "https://app.coolify.io",
336
- "COOLIFY_TOKEN": "your-token"
337
- }
338
- },
339
- "coingecko": {
340
- "transport": "http",
341
- "url": "https://mcps.mnunes.xyz/coingecko/mcp"
342
- }
343
- }
344
- ```
345
-
346
- ## API Endpoints
347
-
348
- Morpheus exposes several API endpoints for programmatic access to its features:
349
-
350
- ### Health Check Endpoints
351
-
352
- #### GET `/health`
353
- Public health check endpoint without authentication.
354
-
355
- * **Response:**
356
- ```json
357
- {
358
- "status": "healthy",
359
- "timestamp": "2026-02-05T21:30:00.000Z",
360
- "uptime": 123.45
361
- }
362
- ```
363
-
364
- #### GET `/api/health`
365
- Health check endpoint for the API (requires authentication).
366
-
367
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
368
- * **Response:**
369
- ```json
370
- {
371
- "status": "healthy",
372
- "timestamp": "2026-02-05T21:30:00.000Z",
373
- "uptime": 123.45
374
- }
375
- ```
376
-
377
- ### Status Endpoint
378
-
379
- #### GET `/api/status`
380
- Get the current status of the Morpheus agent.
381
-
382
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
383
- * **Response:**
384
- ```json
385
- {
386
- "status": "online",
387
- "uptimeSeconds": 1234.56,
388
- "pid": 12345,
389
- "projectVersion": "1.0.0",
390
- "nodeVersion": "v18.17.0",
391
- "agentName": "Morpheus",
392
- "llmProvider": "openai",
393
- "llmModel": "gpt-4-turbo"
394
- }
395
- ```
396
-
397
- ### Session Endpoints
398
-
399
- #### POST `/api/session/reset`
400
- Archive the current session and start a new one.
401
-
402
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
403
- * **Response:**
404
- ```json
405
- {
406
- "success": true,
407
- "message": "New session started"
408
- }
409
- ```
410
-
411
- #### POST `/api/session/status`
412
- Get the status of the current session.
413
-
414
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
415
- * **Response:**
416
- ```json
417
- {
418
- "id": "uuid-...",
419
- "messageCount": 42,
420
- "embedding_status": "pending"
421
- }
422
- ```
423
-
424
- ### Configuration Endpoints
425
-
426
- #### GET `/api/config`
427
- Retrieve the current configuration.
428
-
429
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
430
- * **Response:**
431
- ```json
432
- {
433
- "agent": {
434
- "name": "Morpheus",
435
- "personality": "stoic, wise, and helpful"
436
- },
437
- "llm": {
438
- "provider": "openai",
439
- "model": "gpt-4-turbo",
440
- "temperature": 0.7,
441
- "context_window": 100,
442
- "api_key": "***"
443
- },
444
- "santi": {
445
- "provider": "openai",
446
- "model": "gpt-4o",
447
- "memory_limit": 1000
448
- },
449
- "channels": {
450
- "telegram": {
451
- "enabled": true,
452
- "token": "***",
453
- "allowedUsers": ["123456789"]
454
- },
455
- "discord": {
456
- "enabled": false
457
- }
458
- },
459
- "ui": {
460
- "enabled": true,
461
- "port": 3333
462
- },
463
- "audio": {
464
- "enabled": true,
465
- "apiKey": "***",
466
- "maxDurationSeconds": 300
467
- }
468
- }
469
- ```
470
-
471
- #### POST `/api/config`
472
- Update the configuration.
473
-
474
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
475
- * **Body:** Complete configuration object (same structure as GET response).
476
- * **Response:**
477
- ```json
478
- {
479
- "agent": {
480
- "name": "Morpheus",
481
- "personality": "stoic, wise, and helpful"
482
- },
483
- "llm": {
484
- "provider": "openai",
485
- "model": "gpt-4-turbo",
486
- "temperature": 0.7,
487
- "context_window": 100,
488
- "api_key": "***"
489
- },
490
- "santi": {
491
- "provider": "openai",
492
- "model": "gpt-4o",
493
- "memory_limit": 1000
494
- },
495
- "channels": {
496
- "telegram": {
497
- "enabled": true,
498
- "token": "***",
499
- "allowedUsers": ["123456789"]
500
- },
501
- "discord": {
502
- "enabled": false
503
- }
504
- },
505
- "ui": {
506
- "enabled": true,
507
- "port": 3333
508
- },
509
- "audio": {
510
- "enabled": true,
511
- "apiKey": "***",
512
- "maxDurationSeconds": 300
513
- }
514
- }
515
- ```
516
-
517
- #### GET `/api/config/sati`
518
- Retrieve the Sati (long-term memory) configuration.
519
-
520
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
521
- * **Response:**
522
- ```json
523
- {
524
- "provider": "openai",
525
- "model": "gpt-4o",
526
- "memory_limit": 1000
527
- }
528
- ```
529
-
530
- #### POST `/api/config/sati`
531
- Update the Sati (long-term memory) configuration.
532
-
533
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
534
- * **Body:**
535
- ```json
536
- {
537
- "provider": "openai",
538
- "model": "gpt-4o",
539
- "memory_limit": 1000
540
- }
541
- ```
542
- * **Response:**
543
- ```json
544
- {
545
- "success": true
546
- }
547
- ```
548
-
549
- #### DELETE `/api/config/sati`
550
- Remove the Sati (long-term memory) configuration (falls back to Oracle config).
551
-
552
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
553
- * **Response:**
554
- ```json
555
- {
556
- "success": true
557
- }
558
- ```
559
-
560
- ### Statistics Endpoints
561
-
562
- #### GET `/api/stats/usage`
563
- Get global token usage statistics.
564
-
565
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
566
- * **Response:**
567
- ```json
568
- {
569
- "totalInputTokens": 12345,
570
- "totalOutputTokens": 6789,
571
- "totalTokens": 19134
572
- }
573
- ```
574
-
575
- #### GET `/api/stats/usage/grouped`
576
- Get token usage statistics grouped by provider and model.
577
-
578
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
579
- * **Response:**
580
- ```json
581
- [
582
- {
583
- "provider": "openai",
584
- "model": "gpt-4-turbo",
585
- "totalTokens": 12345,
586
- "inputTokens": 10000,
587
- "outputTokens": 2345,
588
- "messageCount": 100
589
- },
590
- {
591
- "provider": "anthropic",
592
- "model": "claude-3-opus",
593
- "totalTokens": 6789,
594
- "inputTokens": 5000,
595
- "outputTokens": 1789,
596
- "messageCount": 50
597
- }
598
- ]
599
- ```
600
-
601
- ### Sati Memories Endpoints
602
-
603
- #### GET `/api/sati/memories`
604
- Retrieve all memories stored by the Sati agent (long-term memory).
605
-
606
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
607
- * **Response:**
608
- ```json
609
- [
610
- {
611
- "id": "unique-id",
612
- "category": "work",
613
- "importance": "high",
614
- "summary": "Memory summary",
615
- "details": "Additional details of the memory",
616
- "hash": "unique-hash",
617
- "source": "source",
618
- "created_at": "2023-01-01T00:00:00.000Z",
619
- "updated_at": "2023-01-01T00:00:00.000Z",
620
- "last_accessed_at": "2023-01-01T00:00:00.000Z",
621
- "access_count": 5,
622
- "version": 1,
623
- "archived": false
624
- }
625
- ]
626
- ```
627
-
628
- #### DELETE `/api/sati/memories/:id`
629
- Archive (soft delete) a specific memory from the Sati agent.
630
-
631
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
632
- * **Parameters:** `id` - ID of the memory to archive.
633
- * **Response:**
634
- ```json
635
- {
636
- "success": true,
637
- "message": "Memory archived successfully"
638
- }
639
- ```
640
-
641
- #### POST `/api/sati/memories/bulk-delete`
642
- Archive (soft delete) multiple memories from the Sati agent at once.
643
-
644
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
645
- * **Body:**
646
- ```json
647
- {
648
- "ids": ["id1", "id2", "id3"]
649
- }
650
- ```
651
- * **Response:**
652
- ```json
653
- {
654
- "success": true,
655
- "message": "X memories archived successfully",
656
- "deletedCount": X
657
- }
658
- ```
659
-
660
- ### MCP Server Endpoints
661
-
662
- #### GET `/api/mcp/servers`
663
- List all registered MCP servers.
664
-
665
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
666
- * **Response:**
667
- ```json
668
- {
669
- "servers": [
670
- {
671
- "name": "coolify",
672
- "config": {
673
- "transport": "stdio",
674
- "command": "npx",
675
- "args": ["-y", "@coolify/mcp-server"],
676
- "env": {
677
- "COOLIFY_URL": "https://app.coolify.io",
678
- "COOLIFY_TOKEN": "your-token"
679
- }
680
- },
681
- "enabled": true
682
- },
683
- {
684
- "name": "coingecko",
685
- "config": {
686
- "transport": "http",
687
- "url": "https://mcps.mnunes.xyz/coingecko/mcp"
688
- },
689
- "enabled": false
690
- }
691
- ]
692
- }
693
- ```
694
-
695
- #### POST `/api/mcp/servers`
696
- Add a new MCP server.
697
-
698
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
699
- * **Body:**
700
- ```json
701
- {
702
- "name": "new-server",
703
- "config": {
704
- "transport": "stdio",
705
- "command": "npx",
706
- "args": ["-y", "@new-mcp-server"],
707
- "env": {
708
- "NEW_SERVER_URL": "https://example.com",
709
- "NEW_SERVER_TOKEN": "your-token"
710
- }
711
- }
712
- }
713
- ```
714
- * **Response:**
715
- ```json
716
- {
717
- "ok": true
718
- }
719
- ```
720
-
721
- #### PUT `/api/mcp/servers/:name`
722
- Update an existing MCP server.
723
-
724
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
725
- * **Parameters:** `name` - Name of the server to update.
726
- * **Body:**
727
- ```json
728
- {
729
- "transport": "stdio",
730
- "command": "npx",
731
- "args": ["-y", "@updated-mcp-server"],
732
- "env": {
733
- "UPDATED_SERVER_URL": "https://example.com",
734
- "UPDATED_SERVER_TOKEN": "your-updated-token"
735
- }
736
- }
737
- ```
738
- * **Response:**
739
- ```json
740
- {
741
- "ok": true
742
- }
743
- ```
744
-
745
- #### DELETE `/api/mcp/servers/:name`
746
- Delete an MCP server.
747
-
748
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
749
- * **Parameters:** `name` - Name of the server to delete.
750
- * **Response:**
751
- ```json
752
- {
753
- "ok": true
754
- }
755
- ```
756
-
757
- #### PATCH `/api/mcp/servers/:name/toggle`
758
- Enable or disable an MCP server.
759
-
760
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
761
- * **Parameters:** `name` - Name of the server to toggle.
762
- * **Body:**
763
- ```json
764
- {
765
- "enabled": true
766
- }
767
- ```
768
- * **Response:**
769
- ```json
770
- {
771
- "ok": true
772
- }
773
- ```
774
-
775
- ### Logging Endpoints
776
-
777
- #### GET `/api/logs`
778
- List all log files.
779
-
780
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
781
- * **Response:**
782
- ```json
783
- [
784
- {
785
- "name": "morpheus.log",
786
- "size": 10240,
787
- "modified": "2026-02-05T21:30:00.000Z"
788
- },
789
- {
790
- "name": "morpheus-2026-02-04.log",
791
- "size": 20480,
792
- "modified": "2026-02-04T21:30:00.000Z"
793
- }
794
- ]
795
- ```
796
-
797
- #### GET `/api/logs/:filename`
798
- Get the last lines of a specific log file.
799
-
800
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
801
- * **Parameters:** `filename` - Name of the log file to read.
802
- * **Query Parameters:** `limit` - Number of lines to return (default: 50).
803
- * **Response:**
804
- ```json
805
- {
806
- "lines": [
807
- "2026-02-05T21:30:00.000Z INFO: Starting Morpheus agent...",
808
- "2026-02-05T21:30:01.000Z DEBUG: Connected to OpenAI API",
809
- "2026-02-05T21:30:02.000Z INFO: Telegram bot initialized"
810
- ]
811
- }
812
- ```
813
-
814
- ### Control Endpoints
815
-
816
- #### POST `/api/restart`
817
- Restart the Morpheus agent.
818
-
819
- * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
820
- * **Response:**
821
- ```json
822
- {
823
- "success": true,
824
- "message": "Restart initiated. Process will shut down and restart shortly."
825
- }
826
- ```
827
-
828
- ## Testing
829
-
830
- We use **Vitest** for testing.
831
-
832
- ```bash
833
- # Run unit tests
834
- npm test
835
-
836
- # Run tests in watch mode
837
- npm run test:watch
838
- ```
839
-
840
- ## Project Structure
841
-
842
- ```text
843
- .
844
- ├── assets/ # Static assets
845
- ├── bin/ # CLI entry point (morpheus.js)
846
- ├── specs/ # Technical specifications & documentation
847
- ├── src/
848
- │ ├── channels/ # Communication adapters (Telegram, etc.)
849
- │ ├── cli/ # CLI commands and logic
850
- │ ├── config/ # Configuration management
851
- │ ├── runtime/ # Core agent logic, lifecycle, and providers
852
- │ ├── types/ # Shared TypeScript definitions
853
- │ └── ui/ # React Web UI Dashboard
854
- └── package.json
855
- ```
856
-
857
- ## Roadmap
858
-
859
- - [x] **Web Dashboard**: Local UI for management and logs.
860
- - [x] **MCP Support**: Full integration with Model Context Protocol.
861
- - [ ] **Discord Adapter**: Support for Discord interactions.
862
- - [ ] **Plugin System**: Extend functionality via external modules.
863
-
864
- ## 🕵️ Privacy Protection
865
-
866
- The Web UI includes privacy protection headers to prevent indexing by search engines:
867
- - HTML meta tags: `<meta name="robots" content="noindex, nofollow">`
868
- - HTTP header: `X-Robots-Tag: noindex, nofollow`
869
-
870
- This ensures that your private agent dashboard remains private and is not discoverable by search engines.
871
-
872
- ## 🐳 Running with Docker
873
-
874
- Morpheus can be easily deployed using Docker and Docker Compose. The container supports all environment variables for configuration.
875
- The Docker image is publicly available at [Docker Hub](https://hub.docker.com/r/marcosnunesmbs/morpheus).
876
-
877
- ### Prerequisites
878
-
879
- - Docker Engine
880
- - Docker Compose
881
-
882
- ### Quick Start
883
-
884
- 1. Create a `.env` file with your configuration:
885
-
886
- ```bash
887
- cp .env.example .env
888
- # Edit .env with your actual API keys and settings
889
- ```
890
-
891
- 2. Build and start the container:
892
-
893
- ```bash
894
- docker-compose up -d
895
- ```
896
-
897
- 3. Access the Web UI at `http://localhost:3333`
898
-
899
- ### Docker Compose Example
900
-
901
- Here's a complete example of how to run Morpheus using Docker Compose:
902
-
903
- ```yaml
904
- version: '3.8'
905
-
906
- services:
907
- morpheus:
908
- image: marcosnunesmbs/morpheus:latest
909
- container_name: morpheus-agent
910
- ports:
911
- - "3333:3333"
912
- volumes:
913
- - morpheus_data:/root/.morpheus
914
- environment:
915
- # LLM Configuration
916
- - MORPHEUS_LLM_PROVIDER=openai
917
- - MORPHEUS_LLM_MODEL=gpt-4o
918
- - MORPHEUS_LLM_TEMPERATURE=0.7
919
-
920
- # API Keys
921
- - OPENAI_API_KEY=your-openai-api-key
922
- - ANTHROPIC_API_KEY=your-anthropic-api-key
923
- - GOOGLE_API_KEY=your-google-api-key
924
- - OPENROUTER_API_KEY=your-openrouter-api-key
925
-
926
- # Security
927
- - THE_ARCHITECT_PASS=your-secure-password
928
-
929
- # Agent Configuration
930
- - MORPHEUS_AGENT_NAME=morpheus
931
- - MORPHEUS_AGENT_PERSONALITY=helpful_dev
932
-
933
- # UI Configuration
934
- - MORPHEUS_UI_ENABLED=true
935
- - MORPHEUS_UI_PORT=3333
936
- restart: unless-stopped
937
- ```
938
-
939
- ### Using Docker Directly
940
-
941
- ```bash
942
- # Build the image
943
- docker build -t morpheus .
944
-
945
- # Run with environment variables
946
- docker run -d \
947
- --name morpheus-agent \
948
- -p 3333:3333 \
949
- -v morpheus_data:/root/.morpheus \
950
- -e MORPHEUS_LLM_PROVIDER=openai \
951
- -e OPENAI_API_KEY=your-api-key-here \
952
- -e THE_ARCHITECT_PASS=your-password \
953
- morpheus
954
- ```
955
-
956
- ### Environment Variables in Docker
957
-
958
- All environment variables described above work in Docker. The precedence order remains the same:
959
- 1. Container environment variables
960
- 2. Configuration file values
961
- 3. Default values
962
-
963
- ### Persistent Data
964
-
965
- The container stores configuration and data in `/root/.morpheus`. Mount a volume to persist data between container restarts:
966
-
967
- ```yaml
968
- volumes:
969
- - morpheus_data:/root/.morpheus # Recommended for persistence
970
- ```
971
-
972
- ### Health Check
973
-
974
- The container includes a health check that verifies the health endpoint is accessible. The application exposes a public `/health` endpoint that doesn't require authentication:
975
-
976
- ```bash
977
- curl http://localhost:3333/health
978
- ```
979
-
980
- Response:
981
- ```json
982
- {
983
- "status": "healthy",
984
- "timestamp": "2026-02-05T21:30:00.000Z",
985
- "uptime": 123.45
986
- }
987
- ```
988
-
989
- ## Contributing
990
-
991
- 1. Fork the repository.
992
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`).
993
- 3. Commit your changes (`git commit -m 'feat: Add amazing feature'`).
994
- 4. Push to the branch (`git push origin feature/amazing-feature`).
995
- 5. Open a Pull Request.
996
-
997
- ## License
998
-
999
- MIT
1
+ <div align="center">
2
+ <img src="./assets/logo.png" alt="Morpheus Logo" width="220" />
3
+ </div>
4
+
5
+ # Morpheus
6
+
7
+ > **Morpheus is a local-first AI operator that bridges developers and machines.**
8
+
9
+ Morpheus is a local AI agent for developers, running as a CLI daemon that connects to **LLMs**, **local tools**, and **MCPs**, enabling interaction via **Terminal, Telegram, and Discord**. Inspired by the character Morpheus from *The Matrix*, the project acts as an **intelligent orchestrator**, bridging the gap between the developer and complex systems.
10
+
11
+ ## Installation
12
+
13
+ Install Morpheus globally via npm:
14
+
15
+ ```bash
16
+ npm install -g morpheus-cli
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Initialize
22
+
23
+ Set up your configuration (API keys, preferences):
24
+
25
+ ```bash
26
+ morpheus init
27
+ ```
28
+
29
+ ### 2. Start the Agent
30
+
31
+ Run the background daemon and Web UI:
32
+
33
+ ```bash
34
+ morpheus start
35
+ ```
36
+
37
+ This will:
38
+ - Start the agent process
39
+ - Launch the Web UI at http://localhost:3333
40
+ - If an instance is already running, prompt whether to stop it and start a new one
41
+
42
+ #### Auto-approve restart
43
+
44
+ If you want to automatically stop any running instance and start a new one without prompting:
45
+
46
+ ```bash
47
+ morpheus start -y
48
+ # or
49
+ morpheus start --yes
50
+ ```
51
+
52
+ ### Other Commands
53
+
54
+ ```bash
55
+ # Check if Morpheus is running
56
+ morpheus status
57
+
58
+ # Stop the agent
59
+ morpheus stop
60
+
61
+ # Restart the agent
62
+ morpheus restart
63
+
64
+ # Diagnose issues
65
+ morpheus doctor
66
+
67
+ # Manage sessions
68
+ morpheus session new # Archive current and start new
69
+ morpheus session status # Check current session info
70
+ ```
71
+
72
+ ## Troubleshooting
73
+
74
+ ### Command not found
75
+
76
+ If you installed successfully but can't run the `morpheus` command:
77
+
78
+ 1. **Check your PATH**: Ensure your global npm bin directory is in your system PATH.
79
+ - Run `npm bin -g` to see the folder.
80
+ - On Windows, this is usually `%APPDATA%\npm`.
81
+ - On Linux/Mac, verify `echo $PATH`.
82
+ 2. **Restart Terminal**: New installations might not be visible until you restart your shell.
83
+
84
+ ## Using NPX
85
+ You can run Morpheus without installing it globally using `npx`:
86
+
87
+ ```bash
88
+
89
+ npx morpheus-cli init
90
+
91
+ npx morpheus-cli start
92
+
93
+ ```
94
+
95
+ ## Technical Overview
96
+
97
+ Morpheus is built with **Node.js** and **TypeScript**, using **LangChain** as the orchestration engine. It runs as a background daemon process, managing connections to LLM providers (OpenAI, Anthropic, Ollama) and external channels (Telegram, Discord).
98
+
99
+ ### Core Components
100
+
101
+ - **Runtime (`src/runtime/`)**: The heart of the application. Manages the Oracle (agent) lifecycle, provider instantiation, and command execution.
102
+ - **CLI (`src/cli/`)**: Built with `commander`, handles user interaction, configuration, and daemon control (`start`, `stop`, `status`).
103
+ - **Configuration (`src/config/`)**: Singleton-based configuration manager using `zod` for validation and `js-yaml` for persistence (`~/.morpheus/zaion.yaml`).
104
+ - **Channels (`src/channels/`)**: Adapters for external communication. Currently supports Telegram (`telegraf`) with strict user whitelisting.
105
+
106
+ ## Features
107
+
108
+ ### 🖥️ Web Dashboard
109
+ Local React-based UI to manage recordings, chat history, and system status across your agent instances.
110
+
111
+ **New: Interactive Web Chat**
112
+ - Full-featured chat interface accessible from the browser
113
+ - Session management: create, archive, delete, and rename sessions
114
+ - Cross-channel visibility: view and interact with sessions started on any channel (Telegram, Web, etc.)
115
+ - Real-time messaging with the Oracle agent
116
+ - Responsive design with collapsible sidebar
117
+ - Full support for Light and Dark (Matrix) themes
118
+
119
+ #### 🔒 UI Authentication
120
+ To protect your Web UI, use the `THE_ARCHITECT_PASS` environment variable. This ensures only authorized users can access the dashboard and API.
121
+
122
+ Additionally, you can use environment variables for API keys instead of storing them in the configuration file:
123
+
124
+ | Variable | Description | Required |
125
+ |----------|-------------|----------|
126
+ | `OPENAI_API_KEY` | OpenAI API key (if using GPT) | No |
127
+ | `ANTHROPIC_API_KEY` | Anthropic API key (if using Claude) | No |
128
+ | `GOOGLE_API_KEY` | Google AI key (for Gemini LLM/Audio) | No |
129
+ | `OPENROUTER_API_KEY` | OpenRouter API key (if using OpenRouter) | No |
130
+ | `THE_ARCHITECT_PASS` | Web Dashboard access password | Recommended |
131
+ | `TELEGRAM_BOT_TOKEN` | Telegram BotFather token | No |
132
+
133
+ If these environment variables are set, they will take precedence over values stored in the configuration file.
134
+
135
+ The system also supports generic environment variables that apply to all providers:
136
+
137
+ | Variable | Description | Applies To |
138
+ |----------|-------------|------------|
139
+ | `MORPHEUS_AGENT_NAME` | Name of the agent | agent.name |
140
+ | `MORPHEUS_AGENT_PERSONALITY` | Personality of the agent | agent.personality |
141
+ | `MORPHEUS_LLM_PROVIDER` | LLM provider to use | llm.provider |
142
+ | `MORPHEUS_LLM_MODEL` | Model name for LLM | llm.model |
143
+ | `MORPHEUS_LLM_TEMPERATURE` | Temperature setting for LLM | llm.temperature |
144
+ | `MORPHEUS_LLM_MAX_TOKENS` | Maximum tokens for LLM | llm.max_tokens |
145
+ | `MORPHEUS_LLM_CONTEXT_WINDOW` | Context window size for LLM | llm.context_window |
146
+ | `MORPHEUS_LLM_API_KEY` | Generic API key for LLM (lower precedence than provider-specific keys) | llm.api_key |
147
+ | `MORPHEUS_SATI_PROVIDER` | Sati provider to use | santi.provider |
148
+ | `MORPHEUS_SATI_MODEL` | Model name for Sati | santi.model |
149
+ | `MORPHEUS_SATI_TEMPERATURE` | Temperature setting for Sati | santi.temperature |
150
+ | `MORPHEUS_SATI_MAX_TOKENS` | Maximum tokens for Sati | santi.max_tokens |
151
+ | `MORPHEUS_SATI_CONTEXT_WINDOW` | Context window size for Sati | santi.context_window |
152
+ | `MORPHEUS_SATI_API_KEY` | Generic API key for Sati (lower precedence than provider-specific keys) | santi.api_key |
153
+ | `MORPHEUS_SATI_MEMORY_LIMIT` | Memory retrieval limit for Sati | santi.memory_limit |
154
+ | `MORPHEUS_SATI_MEMORY_LIMIT` | Memory retrieval limit for Sati | santi.memory_limit |
155
+ | `MORPHEUS_SATI_ENABLED_ARCHIVED_SESSIONS`| Enable/disable retrieval of archived sessions in Sati | santi.enableArchivedSessions |
156
+ | `MORPHEUS_AUDIO_MODEL` | Model name for audio processing | audio.model |
157
+ | `MORPHEUS_AUDIO_ENABLED` | Enable/disable audio processing | audio.enabled |
158
+ | `MORPHEUS_AUDIO_API_KEY` | Generic API key for audio (lower precedence than provider-specific keys) | audio.apiKey |
159
+ | `MORPHEUS_AUDIO_MAX_DURATION` | Max duration for audio processing | audio.maxDurationSeconds |
160
+ | `MORPHEUS_TELEGRAM_ENABLED` | Enable/disable Telegram channel | channels.telegram.enabled |
161
+ | `MORPHEUS_TELEGRAM_TOKEN` | Telegram bot token | channels.telegram.token |
162
+ | `MORPHEUS_TELEGRAM_ALLOWED_USERS` | Comma-separated list of allowed Telegram user IDs | channels.telegram.allowedUsers |
163
+ | `MORPHEUS_UI_ENABLED` | Enable/disable Web UI | ui.enabled |
164
+ | `MORPHEUS_UI_PORT` | Port for Web UI | ui.port |
165
+ | `MORPHEUS_LOGGING_ENABLED` | Enable/disable logging | logging.enabled |
166
+ | `MORPHEUS_LOGGING_LEVEL` | Logging level | logging.level |
167
+ | `MORPHEUS_LOGGING_RETENTION` | Log retention period | logging.retention |
168
+
169
+ **Precedence Order**: The system follows this order of precedence when resolving configuration values:
170
+ 1. Provider-specific environment variable (e.g., `OPENAI_API_KEY`) - Highest priority
171
+ 2. Generic environment variable (e.g., `MORPHEUS_LLM_API_KEY`) - Medium priority
172
+ 3. Configuration file value (e.g., `config.llm.api_key`) - Lower priority
173
+ 4. Default value - Lowest priority
174
+
175
+ > **Note**: If `THE_ARCHITECT_PASS` is not set, the system will use the default password `iamthearchitect`. This is less secure and it's recommended to set your own password in production environments.
176
+
177
+ **Option 1: Using a `.env` file**
178
+ Create a `.env` file in the root of your project:
179
+
180
+ ```env
181
+ OPENAI_API_KEY="your-openai-api-key"
182
+ ANTHROPIC_API_KEY="your-anthropic-api-key"
183
+ GOOGLE_API_KEY="your-google-api-key"
184
+ THE_ARCHITECT_PASS="your-secure-password"
185
+ TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
186
+ OPENROUTER_API_KEY="your-openrouter-api-key"
187
+ ```
188
+
189
+ **Option 2: Using Shell export**
190
+
191
+ ```bash
192
+ export OPENAI_API_KEY="your-openai-api-key"
193
+ export ANTHROPIC_API_KEY="your-anthropic-api-key"
194
+ export GOOGLE_API_KEY="your-google-api-key"
195
+ export OPENROUTER_API_KEY="your-openrouter-api-key"
196
+ export THE_ARCHITECT_PASS="your-secure-password"
197
+ export TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
198
+ morpheus start
199
+ ```
200
+
201
+ When enabled:
202
+ - The Web UI will redirect to a Login page.
203
+ - API requests require the `x-architect-pass` header.
204
+ - The session is persisted locally in your browser.
205
+
206
+ ### 🧩 MCP Support (Model Context Protocol)
207
+ Full integration with [Model Context Protocol](https://modelcontextprotocol.io/), allowing Morpheus to use standardized tools from any MCP-compatible server.
208
+
209
+ ### 🧠 Sati (Long-Term Memory)
210
+ Morpheus features a dedicated middleware system called **Sati** (Mindfulness) that provides long-term memory capabilities.
211
+ - **Automated Storage**: Automatically extracts and saves preferences, project details, and facts from conversations.
212
+ - **Contextual Retrieval**: Injects relevant memories into the context based on your current query.
213
+ - **Data Privacy**: Stored in a local, independent SQLite database (`santi-memory.db`), ensuring sensitive data is handled securely and reducing context window usage.
214
+ - **Memory Management**: View and manage your long-term memories through the Web UI or via API endpoints.
215
+
216
+ ### 📊 Usage Analytics
217
+ Track your token usage across different providers and models directly from the Web UI. View detailed breakdowns of input/output tokens and message counts to monitor costs and activity.
218
+
219
+ ### 🎙️ Audio Transcription (Telegram)
220
+ Send voice messages directly to the Telegram bot. Morpheus will:
221
+ 1. Transcribe the audio using the configured provider.
222
+ 2. Process the text as a standard prompt.
223
+ 3. Reply with the answer.
224
+
225
+ Supported audio providers:
226
+
227
+ | Provider | Method | Model example |
228
+ |---|---|---|
229
+ | **Google Gemini** | Native audio file upload | `gemini-2.5-flash-lite` |
230
+ | **OpenAI** | Whisper API (`/audio/transcriptions`) | `whisper-1` |
231
+ | **OpenRouter** | `input_audio` via `@openrouter/sdk` (multimodal models) | `google/gemini-2.5-flash` |
232
+ | **Ollama** | Whisper local via OpenAI-compatible endpoint | `whisper` |
233
+
234
+ > Ollama requires a Whisper model loaded: `ollama pull whisper`
235
+
236
+ *Configure `audio.provider` and `audio.apiKey` in Settings or `config.yaml`.*
237
+
238
+ ### 🤖 Telegram Commands
239
+ The Morpheus Telegram bot supports several commands for interacting with the agent:
240
+
241
+ - `/start` - Show welcome message and available commands
242
+ - `/status` - Check the status of the Morpheus agent
243
+ - `/doctor` - Diagnose environment and configuration issues
244
+ - `/stats` - Show token usage statistics
245
+ - `/help` - Show available commands
246
+ - `/zaion` - Show system configurations
247
+ - `/sati <qnt>` - Show specific memories
248
+ - `/newsession` - Archive current session and start fresh
249
+ - `/sessions` - List all sessions with options to switch, archive, or delete
250
+ - `/restart` - Restart the Morpheus agent
251
+ - `/mcp` or `/mcps` - List registered MCP servers
252
+
253
+ ## Development Setup
254
+
255
+ This guide is for developers contributing to the Morpheus codebase.
256
+
257
+ ### Prerequisites
258
+
259
+ - **Node.js**: >= 18.x
260
+ - **npm**: >= 9.x
261
+ - **TypeScript**: >= 5.x
262
+
263
+ ### 1. Clone & Install
264
+
265
+ ```bash
266
+ git clone https://github.com/your-org/morpheus.git
267
+ cd morpheus
268
+ npm install
269
+ ```
270
+
271
+ ### 2. Build
272
+
273
+ Compile TypeScript source to `dist/` and build the Web UI.
274
+
275
+ ```bash
276
+ npm run build
277
+ ```
278
+
279
+ ### 3. Run the CLI
280
+
281
+ You can run the CLI directly from the source using `npm start`.
282
+
283
+ ```bash
284
+ # Initialize configuration (creates ~/.morpheus)
285
+ npm start -- init
286
+
287
+ # Start the daemon
288
+ npm start -- start
289
+
290
+ # Check status
291
+ npm start -- status
292
+ ```
293
+
294
+ ### 4. Configuration
295
+
296
+ The configuration file is located at `~/.morpheus/zaion.yaml`. You can edit it manually or use the `morpheus config` command.
297
+
298
+ ```yaml
299
+ agent:
300
+ name: "Morpheus"
301
+ personality: "stoic, wise, and helpful"
302
+ llm:
303
+ provider: "openai" # options: openai, anthropic, ollama, gemini
304
+ model: "gpt-4-turbo"
305
+ temperature: 0.7
306
+ context_window: 100 # Number of messages to load into LLM context
307
+ api_key: "sk-..."
308
+ santi: # Optional: Sati (Long-Term Memory) specific settings
309
+ provider: "openai" # defaults to llm.provider
310
+ model: "gpt-4o"
311
+ memory_limit: 1000 # Number of messages/items to retrieve
312
+ channels:
313
+ telegram:
314
+ enabled: true
315
+ token: "YOUR_TELEGRAM_BOT_TOKEN"
316
+ allowedUsers: ["123456789"] # Your Telegram User ID
317
+ discord:
318
+ enabled: false # Coming soon
319
+
320
+ # Web UI Dashboard
321
+ ui:
322
+ enabled: true
323
+ port: 3333
324
+
325
+ # Audio Transcription Support
326
+ audio:
327
+ enabled: true
328
+ provider: "google" # google | openai | openrouter | anthropic | ollama
329
+ model: "gemini-2.5-flash-lite"
330
+ apiKey: "YOUR_API_KEY" # Optional if using same provider as LLM
331
+ base_url: "" # Required for openrouter/ollama
332
+ maxDurationSeconds: 300
333
+ ```
334
+
335
+ ### 5. MCP Configuration
336
+
337
+ Morpheus supports external tools via **MCP (Model Context Protocol)**. Configure your MCP servers in `~/.morpheus/mcps.json`:
338
+
339
+ ```json
340
+ {
341
+ "coolify": {
342
+ "transport": "stdio",
343
+ "command": "npx",
344
+ "args": ["-y", "@coolify/mcp-server"],
345
+ "env": {
346
+ "COOLIFY_URL": "https://app.coolify.io",
347
+ "COOLIFY_TOKEN": "your-token"
348
+ }
349
+ },
350
+ "coingecko": {
351
+ "transport": "http",
352
+ "url": "https://mcps.mnunes.xyz/coingecko/mcp"
353
+ }
354
+ }
355
+ ```
356
+
357
+ ## API Endpoints
358
+
359
+ Morpheus exposes several API endpoints for programmatic access to its features:
360
+
361
+ ### Health Check Endpoints
362
+
363
+ #### GET `/health`
364
+ Public health check endpoint without authentication.
365
+
366
+ * **Response:**
367
+ ```json
368
+ {
369
+ "status": "healthy",
370
+ "timestamp": "2026-02-05T21:30:00.000Z",
371
+ "uptime": 123.45
372
+ }
373
+ ```
374
+
375
+ #### GET `/api/health`
376
+ Health check endpoint for the API (requires authentication).
377
+
378
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
379
+ * **Response:**
380
+ ```json
381
+ {
382
+ "status": "healthy",
383
+ "timestamp": "2026-02-05T21:30:00.000Z",
384
+ "uptime": 123.45
385
+ }
386
+ ```
387
+
388
+ ### Status Endpoint
389
+
390
+ #### GET `/api/status`
391
+ Get the current status of the Morpheus agent.
392
+
393
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
394
+ * **Response:**
395
+ ```json
396
+ {
397
+ "status": "online",
398
+ "uptimeSeconds": 1234.56,
399
+ "pid": 12345,
400
+ "projectVersion": "1.0.0",
401
+ "nodeVersion": "v18.17.0",
402
+ "agentName": "Morpheus",
403
+ "llmProvider": "openai",
404
+ "llmModel": "gpt-4-turbo"
405
+ }
406
+ ```
407
+
408
+ ### Session Endpoints
409
+
410
+ #### POST `/api/session/reset`
411
+ Archive the current session and start a new one.
412
+
413
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
414
+ * **Response:**
415
+ ```json
416
+ {
417
+ "success": true,
418
+ "message": "New session started"
419
+ }
420
+ ```
421
+
422
+ #### POST `/api/session/status`
423
+ Get the status of the current session.
424
+
425
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
426
+ * **Response:**
427
+ ```json
428
+ {
429
+ "id": "uuid-...",
430
+ "messageCount": 42,
431
+ "embedding_status": "pending"
432
+ }
433
+ ```
434
+
435
+ ### Configuration Endpoints
436
+
437
+ #### GET `/api/config`
438
+ Retrieve the current configuration.
439
+
440
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
441
+ * **Response:**
442
+ ```json
443
+ {
444
+ "agent": {
445
+ "name": "Morpheus",
446
+ "personality": "stoic, wise, and helpful"
447
+ },
448
+ "llm": {
449
+ "provider": "openai",
450
+ "model": "gpt-4-turbo",
451
+ "temperature": 0.7,
452
+ "context_window": 100,
453
+ "api_key": "***"
454
+ },
455
+ "santi": {
456
+ "provider": "openai",
457
+ "model": "gpt-4o",
458
+ "memory_limit": 1000
459
+ },
460
+ "channels": {
461
+ "telegram": {
462
+ "enabled": true,
463
+ "token": "***",
464
+ "allowedUsers": ["123456789"]
465
+ },
466
+ "discord": {
467
+ "enabled": false
468
+ }
469
+ },
470
+ "ui": {
471
+ "enabled": true,
472
+ "port": 3333
473
+ },
474
+ "audio": {
475
+ "enabled": true,
476
+ "apiKey": "***",
477
+ "maxDurationSeconds": 300
478
+ }
479
+ }
480
+ ```
481
+
482
+ #### POST `/api/config`
483
+ Update the configuration.
484
+
485
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
486
+ * **Body:** Complete configuration object (same structure as GET response).
487
+ * **Response:**
488
+ ```json
489
+ {
490
+ "agent": {
491
+ "name": "Morpheus",
492
+ "personality": "stoic, wise, and helpful"
493
+ },
494
+ "llm": {
495
+ "provider": "openai",
496
+ "model": "gpt-4-turbo",
497
+ "temperature": 0.7,
498
+ "context_window": 100,
499
+ "api_key": "***"
500
+ },
501
+ "santi": {
502
+ "provider": "openai",
503
+ "model": "gpt-4o",
504
+ "memory_limit": 1000
505
+ },
506
+ "channels": {
507
+ "telegram": {
508
+ "enabled": true,
509
+ "token": "***",
510
+ "allowedUsers": ["123456789"]
511
+ },
512
+ "discord": {
513
+ "enabled": false
514
+ }
515
+ },
516
+ "ui": {
517
+ "enabled": true,
518
+ "port": 3333
519
+ },
520
+ "audio": {
521
+ "enabled": true,
522
+ "apiKey": "***",
523
+ "maxDurationSeconds": 300
524
+ }
525
+ }
526
+ ```
527
+
528
+ #### GET `/api/config/sati`
529
+ Retrieve the Sati (long-term memory) configuration.
530
+
531
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
532
+ * **Response:**
533
+ ```json
534
+ {
535
+ "provider": "openai",
536
+ "model": "gpt-4o",
537
+ "memory_limit": 1000
538
+ }
539
+ ```
540
+
541
+ #### POST `/api/config/sati`
542
+ Update the Sati (long-term memory) configuration.
543
+
544
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
545
+ * **Body:**
546
+ ```json
547
+ {
548
+ "provider": "openai",
549
+ "model": "gpt-4o",
550
+ "memory_limit": 1000
551
+ }
552
+ ```
553
+ * **Response:**
554
+ ```json
555
+ {
556
+ "success": true
557
+ }
558
+ ```
559
+
560
+ #### DELETE `/api/config/sati`
561
+ Remove the Sati (long-term memory) configuration (falls back to Oracle config).
562
+
563
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
564
+ * **Response:**
565
+ ```json
566
+ {
567
+ "success": true
568
+ }
569
+ ```
570
+
571
+ ### Statistics Endpoints
572
+
573
+ #### GET `/api/stats/usage`
574
+ Get global token usage statistics.
575
+
576
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
577
+ * **Response:**
578
+ ```json
579
+ {
580
+ "totalInputTokens": 12345,
581
+ "totalOutputTokens": 6789,
582
+ "totalTokens": 19134
583
+ }
584
+ ```
585
+
586
+ #### GET `/api/stats/usage/grouped`
587
+ Get token usage statistics grouped by provider and model.
588
+
589
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
590
+ * **Response:**
591
+ ```json
592
+ [
593
+ {
594
+ "provider": "openai",
595
+ "model": "gpt-4-turbo",
596
+ "totalTokens": 12345,
597
+ "inputTokens": 10000,
598
+ "outputTokens": 2345,
599
+ "messageCount": 100
600
+ },
601
+ {
602
+ "provider": "anthropic",
603
+ "model": "claude-3-opus",
604
+ "totalTokens": 6789,
605
+ "inputTokens": 5000,
606
+ "outputTokens": 1789,
607
+ "messageCount": 50
608
+ }
609
+ ]
610
+ ```
611
+
612
+ ### Sati Memories Endpoints
613
+
614
+ #### GET `/api/sati/memories`
615
+ Retrieve all memories stored by the Sati agent (long-term memory).
616
+
617
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
618
+ * **Response:**
619
+ ```json
620
+ [
621
+ {
622
+ "id": "unique-id",
623
+ "category": "work",
624
+ "importance": "high",
625
+ "summary": "Memory summary",
626
+ "details": "Additional details of the memory",
627
+ "hash": "unique-hash",
628
+ "source": "source",
629
+ "created_at": "2023-01-01T00:00:00.000Z",
630
+ "updated_at": "2023-01-01T00:00:00.000Z",
631
+ "last_accessed_at": "2023-01-01T00:00:00.000Z",
632
+ "access_count": 5,
633
+ "version": 1,
634
+ "archived": false
635
+ }
636
+ ]
637
+ ```
638
+
639
+ #### DELETE `/api/sati/memories/:id`
640
+ Archive (soft delete) a specific memory from the Sati agent.
641
+
642
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
643
+ * **Parameters:** `id` - ID of the memory to archive.
644
+ * **Response:**
645
+ ```json
646
+ {
647
+ "success": true,
648
+ "message": "Memory archived successfully"
649
+ }
650
+ ```
651
+
652
+ #### POST `/api/sati/memories/bulk-delete`
653
+ Archive (soft delete) multiple memories from the Sati agent at once.
654
+
655
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
656
+ * **Body:**
657
+ ```json
658
+ {
659
+ "ids": ["id1", "id2", "id3"]
660
+ }
661
+ ```
662
+ * **Response:**
663
+ ```json
664
+ {
665
+ "success": true,
666
+ "message": "X memories archived successfully",
667
+ "deletedCount": X
668
+ }
669
+ ```
670
+
671
+ ### MCP Server Endpoints
672
+
673
+ #### GET `/api/mcp/servers`
674
+ List all registered MCP servers.
675
+
676
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
677
+ * **Response:**
678
+ ```json
679
+ {
680
+ "servers": [
681
+ {
682
+ "name": "coolify",
683
+ "config": {
684
+ "transport": "stdio",
685
+ "command": "npx",
686
+ "args": ["-y", "@coolify/mcp-server"],
687
+ "env": {
688
+ "COOLIFY_URL": "https://app.coolify.io",
689
+ "COOLIFY_TOKEN": "your-token"
690
+ }
691
+ },
692
+ "enabled": true
693
+ },
694
+ {
695
+ "name": "coingecko",
696
+ "config": {
697
+ "transport": "http",
698
+ "url": "https://mcps.mnunes.xyz/coingecko/mcp"
699
+ },
700
+ "enabled": false
701
+ }
702
+ ]
703
+ }
704
+ ```
705
+
706
+ #### POST `/api/mcp/servers`
707
+ Add a new MCP server.
708
+
709
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
710
+ * **Body:**
711
+ ```json
712
+ {
713
+ "name": "new-server",
714
+ "config": {
715
+ "transport": "stdio",
716
+ "command": "npx",
717
+ "args": ["-y", "@new-mcp-server"],
718
+ "env": {
719
+ "NEW_SERVER_URL": "https://example.com",
720
+ "NEW_SERVER_TOKEN": "your-token"
721
+ }
722
+ }
723
+ }
724
+ ```
725
+ * **Response:**
726
+ ```json
727
+ {
728
+ "ok": true
729
+ }
730
+ ```
731
+
732
+ #### PUT `/api/mcp/servers/:name`
733
+ Update an existing MCP server.
734
+
735
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
736
+ * **Parameters:** `name` - Name of the server to update.
737
+ * **Body:**
738
+ ```json
739
+ {
740
+ "transport": "stdio",
741
+ "command": "npx",
742
+ "args": ["-y", "@updated-mcp-server"],
743
+ "env": {
744
+ "UPDATED_SERVER_URL": "https://example.com",
745
+ "UPDATED_SERVER_TOKEN": "your-updated-token"
746
+ }
747
+ }
748
+ ```
749
+ * **Response:**
750
+ ```json
751
+ {
752
+ "ok": true
753
+ }
754
+ ```
755
+
756
+ #### DELETE `/api/mcp/servers/:name`
757
+ Delete an MCP server.
758
+
759
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
760
+ * **Parameters:** `name` - Name of the server to delete.
761
+ * **Response:**
762
+ ```json
763
+ {
764
+ "ok": true
765
+ }
766
+ ```
767
+
768
+ #### PATCH `/api/mcp/servers/:name/toggle`
769
+ Enable or disable an MCP server.
770
+
771
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
772
+ * **Parameters:** `name` - Name of the server to toggle.
773
+ * **Body:**
774
+ ```json
775
+ {
776
+ "enabled": true
777
+ }
778
+ ```
779
+ * **Response:**
780
+ ```json
781
+ {
782
+ "ok": true
783
+ }
784
+ ```
785
+
786
+ ### Logging Endpoints
787
+
788
+ #### GET `/api/logs`
789
+ List all log files.
790
+
791
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
792
+ * **Response:**
793
+ ```json
794
+ [
795
+ {
796
+ "name": "morpheus.log",
797
+ "size": 10240,
798
+ "modified": "2026-02-05T21:30:00.000Z"
799
+ },
800
+ {
801
+ "name": "morpheus-2026-02-04.log",
802
+ "size": 20480,
803
+ "modified": "2026-02-04T21:30:00.000Z"
804
+ }
805
+ ]
806
+ ```
807
+
808
+ #### GET `/api/logs/:filename`
809
+ Get the last lines of a specific log file.
810
+
811
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
812
+ * **Parameters:** `filename` - Name of the log file to read.
813
+ * **Query Parameters:** `limit` - Number of lines to return (default: 50).
814
+ * **Response:**
815
+ ```json
816
+ {
817
+ "lines": [
818
+ "2026-02-05T21:30:00.000Z INFO: Starting Morpheus agent...",
819
+ "2026-02-05T21:30:01.000Z DEBUG: Connected to OpenAI API",
820
+ "2026-02-05T21:30:02.000Z INFO: Telegram bot initialized"
821
+ ]
822
+ }
823
+ ```
824
+
825
+ ### Control Endpoints
826
+
827
+ #### POST `/api/restart`
828
+ Restart the Morpheus agent.
829
+
830
+ * **Authentication:** Requires `Authorization` header with the password set in `THE_ARCHITECT_PASS`.
831
+ * **Response:**
832
+ ```json
833
+ {
834
+ "success": true,
835
+ "message": "Restart initiated. Process will shut down and restart shortly."
836
+ }
837
+ ```
838
+
839
+ ## Testing
840
+
841
+ We use **Vitest** for testing.
842
+
843
+ ```bash
844
+ # Run unit tests
845
+ npm test
846
+
847
+ # Run tests in watch mode
848
+ npm run test:watch
849
+ ```
850
+
851
+ ## Project Structure
852
+
853
+ ```text
854
+ .
855
+ ├── assets/ # Static assets
856
+ ├── bin/ # CLI entry point (morpheus.js)
857
+ ├── specs/ # Technical specifications & documentation
858
+ ├── src/
859
+ │ ├── channels/ # Communication adapters (Telegram, etc.)
860
+ │ ├── cli/ # CLI commands and logic
861
+ │ ├── config/ # Configuration management
862
+ │ ├── runtime/ # Core agent logic, lifecycle, and providers
863
+ │ ├── types/ # Shared TypeScript definitions
864
+ │ └── ui/ # React Web UI Dashboard
865
+ └── package.json
866
+ ```
867
+
868
+ ## Roadmap
869
+
870
+ - [x] **Web Dashboard**: Local UI for management and logs.
871
+ - [x] **MCP Support**: Full integration with Model Context Protocol.
872
+ - [ ] **Discord Adapter**: Support for Discord interactions.
873
+ - [ ] **Plugin System**: Extend functionality via external modules.
874
+
875
+ ## 🕵️ Privacy Protection
876
+
877
+ The Web UI includes privacy protection headers to prevent indexing by search engines:
878
+ - HTML meta tags: `<meta name="robots" content="noindex, nofollow">`
879
+ - HTTP header: `X-Robots-Tag: noindex, nofollow`
880
+
881
+ This ensures that your private agent dashboard remains private and is not discoverable by search engines.
882
+
883
+ ## 🐳 Running with Docker
884
+
885
+ Morpheus can be easily deployed using Docker and Docker Compose. The container supports all environment variables for configuration.
886
+ The Docker image is publicly available at [Docker Hub](https://hub.docker.com/r/marcosnunesmbs/morpheus).
887
+
888
+ ### Prerequisites
889
+
890
+ - Docker Engine
891
+ - Docker Compose
892
+
893
+ ### Quick Start
894
+
895
+ 1. Create a `.env` file with your configuration:
896
+
897
+ ```bash
898
+ cp .env.example .env
899
+ # Edit .env with your actual API keys and settings
900
+ ```
901
+
902
+ 2. Build and start the container:
903
+
904
+ ```bash
905
+ docker-compose up -d
906
+ ```
907
+
908
+ 3. Access the Web UI at `http://localhost:3333`
909
+
910
+ ### Docker Compose Example
911
+
912
+ Here's a complete example of how to run Morpheus using Docker Compose:
913
+
914
+ ```yaml
915
+ version: '3.8'
916
+
917
+ services:
918
+ morpheus:
919
+ image: marcosnunesmbs/morpheus:latest
920
+ container_name: morpheus-agent
921
+ ports:
922
+ - "3333:3333"
923
+ volumes:
924
+ - morpheus_data:/root/.morpheus
925
+ environment:
926
+ # LLM Configuration
927
+ - MORPHEUS_LLM_PROVIDER=openai
928
+ - MORPHEUS_LLM_MODEL=gpt-4o
929
+ - MORPHEUS_LLM_TEMPERATURE=0.7
930
+
931
+ # API Keys
932
+ - OPENAI_API_KEY=your-openai-api-key
933
+ - ANTHROPIC_API_KEY=your-anthropic-api-key
934
+ - GOOGLE_API_KEY=your-google-api-key
935
+ - OPENROUTER_API_KEY=your-openrouter-api-key
936
+
937
+ # Security
938
+ - THE_ARCHITECT_PASS=your-secure-password
939
+
940
+ # Agent Configuration
941
+ - MORPHEUS_AGENT_NAME=morpheus
942
+ - MORPHEUS_AGENT_PERSONALITY=helpful_dev
943
+
944
+ # UI Configuration
945
+ - MORPHEUS_UI_ENABLED=true
946
+ - MORPHEUS_UI_PORT=3333
947
+ restart: unless-stopped
948
+ ```
949
+
950
+ ### Using Docker Directly
951
+
952
+ ```bash
953
+ # Build the image
954
+ docker build -t morpheus .
955
+
956
+ # Run with environment variables
957
+ docker run -d \
958
+ --name morpheus-agent \
959
+ -p 3333:3333 \
960
+ -v morpheus_data:/root/.morpheus \
961
+ -e MORPHEUS_LLM_PROVIDER=openai \
962
+ -e OPENAI_API_KEY=your-api-key-here \
963
+ -e THE_ARCHITECT_PASS=your-password \
964
+ morpheus
965
+ ```
966
+
967
+ ### Environment Variables in Docker
968
+
969
+ All environment variables described above work in Docker. The precedence order remains the same:
970
+ 1. Container environment variables
971
+ 2. Configuration file values
972
+ 3. Default values
973
+
974
+ ### Persistent Data
975
+
976
+ The container stores configuration and data in `/root/.morpheus`. Mount a volume to persist data between container restarts:
977
+
978
+ ```yaml
979
+ volumes:
980
+ - morpheus_data:/root/.morpheus # Recommended for persistence
981
+ ```
982
+
983
+ ### Health Check
984
+
985
+ The container includes a health check that verifies the health endpoint is accessible. The application exposes a public `/health` endpoint that doesn't require authentication:
986
+
987
+ ```bash
988
+ curl http://localhost:3333/health
989
+ ```
990
+
991
+ Response:
992
+ ```json
993
+ {
994
+ "status": "healthy",
995
+ "timestamp": "2026-02-05T21:30:00.000Z",
996
+ "uptime": 123.45
997
+ }
998
+ ```
999
+
1000
+ ## Contributing
1001
+
1002
+ 1. Fork the repository.
1003
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`).
1004
+ 3. Commit your changes (`git commit -m 'feat: Add amazing feature'`).
1005
+ 4. Push to the branch (`git push origin feature/amazing-feature`).
1006
+ 5. Open a Pull Request.
1007
+
1008
+ ## License
1009
+
1010
+ MIT