daemora 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +666 -0
- package/SOUL.md +104 -0
- package/config/hooks.json +14 -0
- package/config/mcp.json +145 -0
- package/package.json +86 -0
- package/skills/.gitkeep +0 -0
- package/skills/apple-notes.md +193 -0
- package/skills/apple-reminders.md +189 -0
- package/skills/camsnap.md +162 -0
- package/skills/coding.md +14 -0
- package/skills/documents.md +13 -0
- package/skills/email.md +13 -0
- package/skills/gif-search.md +196 -0
- package/skills/healthcheck.md +225 -0
- package/skills/image-gen.md +147 -0
- package/skills/model-usage.md +182 -0
- package/skills/obsidian.md +207 -0
- package/skills/pdf.md +211 -0
- package/skills/research.md +13 -0
- package/skills/skill-creator.md +142 -0
- package/skills/spotify.md +149 -0
- package/skills/summarize.md +230 -0
- package/skills/things.md +199 -0
- package/skills/tmux.md +204 -0
- package/skills/trello.md +183 -0
- package/skills/video-frames.md +202 -0
- package/skills/weather.md +127 -0
- package/src/a2a/A2AClient.js +136 -0
- package/src/a2a/A2AServer.js +316 -0
- package/src/a2a/AgentCard.js +79 -0
- package/src/agents/SubAgentManager.js +369 -0
- package/src/agents/Supervisor.js +192 -0
- package/src/channels/BaseChannel.js +104 -0
- package/src/channels/DiscordChannel.js +288 -0
- package/src/channels/EmailChannel.js +172 -0
- package/src/channels/GoogleChatChannel.js +316 -0
- package/src/channels/HttpChannel.js +26 -0
- package/src/channels/LineChannel.js +168 -0
- package/src/channels/SignalChannel.js +186 -0
- package/src/channels/SlackChannel.js +329 -0
- package/src/channels/TeamsChannel.js +272 -0
- package/src/channels/TelegramChannel.js +347 -0
- package/src/channels/WhatsAppChannel.js +219 -0
- package/src/channels/index.js +198 -0
- package/src/cli.js +1267 -0
- package/src/config/agentProfiles.js +120 -0
- package/src/config/channels.js +32 -0
- package/src/config/default.js +206 -0
- package/src/config/models.js +123 -0
- package/src/config/permissions.js +167 -0
- package/src/core/AgentLoop.js +446 -0
- package/src/core/Compaction.js +143 -0
- package/src/core/CostTracker.js +116 -0
- package/src/core/EventBus.js +46 -0
- package/src/core/Task.js +67 -0
- package/src/core/TaskQueue.js +206 -0
- package/src/core/TaskRunner.js +226 -0
- package/src/daemon/DaemonManager.js +301 -0
- package/src/hooks/HookRunner.js +230 -0
- package/src/index.js +482 -0
- package/src/mcp/MCPAgentRunner.js +112 -0
- package/src/mcp/MCPClient.js +186 -0
- package/src/mcp/MCPManager.js +412 -0
- package/src/models/ModelRouter.js +180 -0
- package/src/safety/AuditLog.js +135 -0
- package/src/safety/CircuitBreaker.js +126 -0
- package/src/safety/FilesystemGuard.js +169 -0
- package/src/safety/GitRollback.js +139 -0
- package/src/safety/HumanApproval.js +156 -0
- package/src/safety/InputSanitizer.js +72 -0
- package/src/safety/PermissionGuard.js +83 -0
- package/src/safety/Sandbox.js +70 -0
- package/src/safety/SecretScanner.js +100 -0
- package/src/safety/SecretVault.js +250 -0
- package/src/scheduler/Heartbeat.js +115 -0
- package/src/scheduler/Scheduler.js +228 -0
- package/src/services/models/outputSchema.js +15 -0
- package/src/services/openai.js +25 -0
- package/src/services/sessions.js +65 -0
- package/src/setup/theme.js +110 -0
- package/src/setup/wizard.js +788 -0
- package/src/skills/SkillLoader.js +168 -0
- package/src/storage/TaskStore.js +69 -0
- package/src/systemPrompt.js +526 -0
- package/src/tenants/TenantContext.js +19 -0
- package/src/tenants/TenantManager.js +379 -0
- package/src/tools/ToolRegistry.js +141 -0
- package/src/tools/applyPatch.js +144 -0
- package/src/tools/browserAutomation.js +223 -0
- package/src/tools/createDocument.js +265 -0
- package/src/tools/cronTool.js +105 -0
- package/src/tools/editFile.js +139 -0
- package/src/tools/executeCommand.js +123 -0
- package/src/tools/glob.js +67 -0
- package/src/tools/grep.js +121 -0
- package/src/tools/imageAnalysis.js +120 -0
- package/src/tools/index.js +173 -0
- package/src/tools/listDirectory.js +47 -0
- package/src/tools/manageAgents.js +47 -0
- package/src/tools/manageMCP.js +159 -0
- package/src/tools/memory.js +478 -0
- package/src/tools/messageChannel.js +45 -0
- package/src/tools/projectTracker.js +259 -0
- package/src/tools/readFile.js +52 -0
- package/src/tools/screenCapture.js +112 -0
- package/src/tools/searchContent.js +76 -0
- package/src/tools/searchFiles.js +75 -0
- package/src/tools/sendEmail.js +118 -0
- package/src/tools/sendFile.js +63 -0
- package/src/tools/textToSpeech.js +161 -0
- package/src/tools/transcribeAudio.js +82 -0
- package/src/tools/useMCP.js +29 -0
- package/src/tools/webFetch.js +150 -0
- package/src/tools/webSearch.js +134 -0
- package/src/tools/writeFile.js +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
# Daemora
|
|
2
|
+
|
|
3
|
+
**A fully autonomous, self-hosted AI agent — production-secure, multi-tenant, multi-channel.**
|
|
4
|
+
|
|
5
|
+
[](https://npmjs.com/package/daemora)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](#)
|
|
9
|
+
|
|
10
|
+
Daemora runs on your own machine. It connects to your messaging apps, accepts tasks in plain language, executes them autonomously with 36 built-in tools, and reports back — without you watching over it.
|
|
11
|
+
|
|
12
|
+
Unlike cloud AI assistants, nothing leaves your infrastructure except the tokens you intentionally send to model APIs. You own the data, the keys, and the security boundary.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## What Daemora Can Do
|
|
17
|
+
|
|
18
|
+
| Capability | Description |
|
|
19
|
+
|---|---|
|
|
20
|
+
| **Code** | Write, edit, run, test, and debug code across multiple files. Takes screenshots of UIs to verify output. Fixes failing tests. Ships working software. |
|
|
21
|
+
| **Research** | Search the web, read pages, analyse images, cross-reference sources, write reports. Spawns parallel sub-agents for speed. |
|
|
22
|
+
| **Automation** | Schedule recurring tasks via cron. Monitor repos, inboxes, or APIs. React to events. Runs while you sleep. |
|
|
23
|
+
| **Communicate** | Send emails, Telegram messages, Slack posts, Discord messages — autonomously, when the task calls for it. |
|
|
24
|
+
| **Tools** | Connect to any MCP server — create Notion pages, open GitHub issues, update Linear tasks, manage Shopify products, query databases. |
|
|
25
|
+
| **Multi-Agent** | Spawn parallel sub-agents (researcher + coder + writer working simultaneously). Each inherits the parent's model and API keys. |
|
|
26
|
+
| **Multi-Tenant** | Run one instance for your whole team. Per-user memory, cost caps, tool allowlists, filesystem isolation, and encrypted API keys. |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
34
|
+
│ INPUT CHANNELS │
|
|
35
|
+
│ Telegram · WhatsApp · Discord · Slack · Email · LINE · │
|
|
36
|
+
│ Signal · Microsoft Teams · Google Chat │
|
|
37
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
38
|
+
│
|
|
39
|
+
▼
|
|
40
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
41
|
+
│ MULTI-TENANT LAYER │
|
|
42
|
+
│ TenantManager + TenantContext (AsyncLocalStorage) │
|
|
43
|
+
│ Per-user: model, tools, MCP servers, filesystem, cost caps, │
|
|
44
|
+
│ encrypted API keys, isolated memory │
|
|
45
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
46
|
+
│
|
|
47
|
+
▼
|
|
48
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
49
|
+
│ TASK QUEUE │
|
|
50
|
+
│ Priority queue · Per-session serialisation │
|
|
51
|
+
│ Steer/inject: follow-up messages injected into running loop │
|
|
52
|
+
│ Cost budget check · Tenant suspension check │
|
|
53
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
54
|
+
│
|
|
55
|
+
▼
|
|
56
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
57
|
+
│ AGENT LOOP │
|
|
58
|
+
│ Vercel AI SDK (generateText + tool_use) │
|
|
59
|
+
│ System prompt: SOUL.md + memory + daily log + task context │
|
|
60
|
+
│ Model: OpenAI · Anthropic · Google · Ollama (local) │
|
|
61
|
+
│ Context compaction when approaching model limits │
|
|
62
|
+
└──────────────┬─────────────────────────────────┬────────────────┘
|
|
63
|
+
│ │
|
|
64
|
+
▼ ▼
|
|
65
|
+
┌──────────────────────────┐ ┌──────────────────────────────┐
|
|
66
|
+
│ BUILT-IN TOOLS │ │ SUB-AGENTS │
|
|
67
|
+
│ File I/O · Shell │ │ spawnAgent · parallelAgents │
|
|
68
|
+
│ Web · Browser │ │ delegateToAgent │
|
|
69
|
+
│ Email · Messaging │ │ Profiles: coder / researcher│
|
|
70
|
+
│ Vision · TTS │ │ / writer / analyst │
|
|
71
|
+
│ Memory · Documents │ │ Inherit model + API keys │
|
|
72
|
+
│ Cron · Agents · MCP │ │ Max depth: 3 Max: 7 agents │
|
|
73
|
+
└──────────────────────────┘ └──────────────┬───────────────┘
|
|
74
|
+
│
|
|
75
|
+
▼
|
|
76
|
+
┌──────────────────────────────┐
|
|
77
|
+
│ MCP SERVERS │
|
|
78
|
+
│ Per-server specialist agent │
|
|
79
|
+
│ GitHub · Notion · Linear │
|
|
80
|
+
│ Slack · Postgres · Puppeteer│
|
|
81
|
+
│ stdio / HTTP / SSE │
|
|
82
|
+
└──────────────────────────────┘
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Security Architecture (10 Layers)
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
LAYER 1 Permission Tiers ───── minimal / standard / full
|
|
89
|
+
LAYER 2 Filesystem Sandbox ─── ALLOWED_PATHS · BLOCKED_PATHS · hardcoded blocks
|
|
90
|
+
LAYER 3 Secret Vault ────────── AES-256-GCM · scrypt key derivation · passphrase on start
|
|
91
|
+
LAYER 4 Channel Allowlists ─── per-channel user ID whitelist
|
|
92
|
+
LAYER 5 A2A Security ────────── bearer token · agent allowlist · rate limiting
|
|
93
|
+
LAYER 6 Audit Trail ─────────── append-only JSONL · secrets redacted · tenantId tagged
|
|
94
|
+
LAYER 7 Supervisor Agent ────── runaway loop detection · cost overruns · dangerous patterns
|
|
95
|
+
LAYER 8 Input Sanitisation ─── untrusted-input wrapping · prompt injection detection
|
|
96
|
+
LAYER 9 Multi-Tenant Isolation ─ AsyncLocalStorage · no cross-tenant data leakage
|
|
97
|
+
LAYER 10 Security Audit CLI ─── daemora doctor · 8 checks · scored output
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Sequence Diagrams
|
|
103
|
+
|
|
104
|
+
### Task Lifecycle — from message to response
|
|
105
|
+
|
|
106
|
+
```mermaid
|
|
107
|
+
sequenceDiagram
|
|
108
|
+
actor User as User (Telegram)
|
|
109
|
+
participant Ch as Channel
|
|
110
|
+
participant TQ as TaskQueue
|
|
111
|
+
participant TC as TenantContext
|
|
112
|
+
participant AL as AgentLoop
|
|
113
|
+
participant T as Tools
|
|
114
|
+
participant MC as MCP Server
|
|
115
|
+
|
|
116
|
+
User->>Ch: "Fix the auth bug and open a PR"
|
|
117
|
+
Ch->>TQ: enqueue(task, sessionId)
|
|
118
|
+
Ch-->>User: ⏳ reaction
|
|
119
|
+
|
|
120
|
+
TQ->>TC: run({ tenant, model, apiKeys })
|
|
121
|
+
TC->>AL: runAgentLoop(systemPrompt, messages)
|
|
122
|
+
|
|
123
|
+
AL->>T: readFile("src/auth.js")
|
|
124
|
+
T-->>AL: file contents
|
|
125
|
+
|
|
126
|
+
AL->>T: editFile("src/auth.js", patch)
|
|
127
|
+
T-->>AL: success
|
|
128
|
+
|
|
129
|
+
AL->>T: executeCommand("npm test")
|
|
130
|
+
T-->>AL: all tests passing
|
|
131
|
+
|
|
132
|
+
AL->>MC: useMCP("github", "open a PR for this fix")
|
|
133
|
+
MC-->>AL: PR #42 created
|
|
134
|
+
|
|
135
|
+
AL-->>TC: "Fixed auth bug, opened PR #42"
|
|
136
|
+
TC-->>Ch: task complete
|
|
137
|
+
Ch->>User: "Fixed. PR #42 is open ✅"
|
|
138
|
+
Ch-->>User: ✅ reaction
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### Multi-Agent — parallel sub-agents
|
|
144
|
+
|
|
145
|
+
```mermaid
|
|
146
|
+
sequenceDiagram
|
|
147
|
+
actor User
|
|
148
|
+
participant AL as AgentLoop (Main)
|
|
149
|
+
participant SM as SubAgentManager
|
|
150
|
+
participant R as Researcher Agent
|
|
151
|
+
participant W as Writer Agent
|
|
152
|
+
participant C as Coder Agent
|
|
153
|
+
|
|
154
|
+
User->>AL: "Research top 5 competitors, write a report, save it to docs/"
|
|
155
|
+
|
|
156
|
+
AL->>SM: parallelAgents([researcher × 5, writer])
|
|
157
|
+
|
|
158
|
+
par Concurrent execution
|
|
159
|
+
SM->>R: spawn(profile=researcher, "Competitor A")
|
|
160
|
+
R->>R: webSearch + webFetch
|
|
161
|
+
R-->>AL: notes on Competitor A
|
|
162
|
+
and
|
|
163
|
+
SM->>R: spawn(profile=researcher, "Competitor B")
|
|
164
|
+
R->>R: webSearch + webFetch
|
|
165
|
+
R-->>AL: notes on Competitor B
|
|
166
|
+
and
|
|
167
|
+
SM->>W: spawn(profile=writer, "draft outline")
|
|
168
|
+
W->>W: structure + draft
|
|
169
|
+
W-->>AL: draft report
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
AL->>C: spawnAgent(profile=coder, "save report to docs/competitors.md")
|
|
173
|
+
C->>C: writeFile("docs/competitors.md")
|
|
174
|
+
C-->>AL: done
|
|
175
|
+
|
|
176
|
+
AL->>User: "Report saved → docs/competitors.md"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### Steer/Inject — follow-up message mid-task
|
|
182
|
+
|
|
183
|
+
```mermaid
|
|
184
|
+
sequenceDiagram
|
|
185
|
+
actor User
|
|
186
|
+
participant TQ as TaskQueue
|
|
187
|
+
participant TR as TaskRunner
|
|
188
|
+
participant AL as AgentLoop
|
|
189
|
+
|
|
190
|
+
User->>TQ: "Fix the login bug"
|
|
191
|
+
TQ->>TR: dequeue task-1
|
|
192
|
+
TR->>AL: runAgentLoop(task-1)
|
|
193
|
+
Note over AL: tool call: readFile("auth.js") ...
|
|
194
|
+
|
|
195
|
+
User->>TQ: "Also fix the signup form while you're at it"
|
|
196
|
+
Note over TR: Session already active — inject, don't queue
|
|
197
|
+
TR->>AL: steerQueue.push(user message)
|
|
198
|
+
TR->>TQ: merge(task-2) — silent complete, no duplicate reply
|
|
199
|
+
|
|
200
|
+
Note over AL: drains steerQueue between tool calls
|
|
201
|
+
AL->>AL: both tasks now in context
|
|
202
|
+
|
|
203
|
+
AL-->>User: "Fixed login bug AND signup form validation ✅"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Quick Start
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
npm install -g daemora
|
|
212
|
+
daemora setup # interactive wizard — models, channels, vault, MCP
|
|
213
|
+
daemora start # start the agent
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Then message your bot. That's it.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Installation
|
|
221
|
+
|
|
222
|
+
### npm (recommended)
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npm install -g daemora
|
|
226
|
+
daemora setup
|
|
227
|
+
daemora start
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Clone from source
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
git clone https://github.com/umarfarooq/daemora-agent.git
|
|
234
|
+
cd daemora-agent
|
|
235
|
+
npm install
|
|
236
|
+
cp .env.example .env
|
|
237
|
+
# Add your API keys to .env
|
|
238
|
+
daemora setup
|
|
239
|
+
daemora start
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Run as a system daemon (always on)
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
daemora daemon install # Register as a system service (launchctl / systemd / Task Scheduler)
|
|
246
|
+
daemora daemon start # Start in background
|
|
247
|
+
daemora daemon status # Check status
|
|
248
|
+
daemora daemon logs # View logs
|
|
249
|
+
daemora daemon stop # Stop
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Configuration
|
|
255
|
+
|
|
256
|
+
Copy `.env.example` to `.env` and fill in what you need.
|
|
257
|
+
|
|
258
|
+
### AI Models
|
|
259
|
+
|
|
260
|
+
At least one provider is required:
|
|
261
|
+
|
|
262
|
+
```env
|
|
263
|
+
OPENAI_API_KEY=sk-...
|
|
264
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
265
|
+
GOOGLE_AI_API_KEY=...
|
|
266
|
+
|
|
267
|
+
# Default model (used when no model is specified)
|
|
268
|
+
DEFAULT_MODEL=openai:gpt-4.1-mini
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Supported models:**
|
|
272
|
+
|
|
273
|
+
| Model ID | Description |
|
|
274
|
+
|---|---|
|
|
275
|
+
| `openai:gpt-4.1` | Most capable OpenAI model |
|
|
276
|
+
| `openai:gpt-4.1-mini` | Fast and cheap — good default |
|
|
277
|
+
| `anthropic:claude-opus-4-6` | Best for complex reasoning |
|
|
278
|
+
| `anthropic:claude-sonnet-4-6` | Balanced — great for code |
|
|
279
|
+
| `google:gemini-2.5-pro` | Best for long context |
|
|
280
|
+
| `google:gemini-2.0-flash` | Fastest Google model |
|
|
281
|
+
| `ollama:llama3.2` | Local — no API key needed |
|
|
282
|
+
|
|
283
|
+
### Task-Type Model Routing (optional)
|
|
284
|
+
|
|
285
|
+
Route different task types to the best model automatically:
|
|
286
|
+
|
|
287
|
+
```env
|
|
288
|
+
CODE_MODEL=anthropic:claude-sonnet-4-6
|
|
289
|
+
RESEARCH_MODEL=google:gemini-2.0-flash
|
|
290
|
+
WRITER_MODEL=openai:gpt-4.1
|
|
291
|
+
ANALYST_MODEL=openai:gpt-4.1
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
When a sub-agent is spawned with `profile: "coder"`, it automatically uses `CODE_MODEL`. Sub-agents without an explicit model inherit from their parent.
|
|
295
|
+
|
|
296
|
+
### Channels
|
|
297
|
+
|
|
298
|
+
Enable only what you need:
|
|
299
|
+
|
|
300
|
+
```env
|
|
301
|
+
# Telegram
|
|
302
|
+
TELEGRAM_BOT_TOKEN=...
|
|
303
|
+
TELEGRAM_ALLOWLIST=123456789,987654321 # optional: restrict to specific users
|
|
304
|
+
|
|
305
|
+
# WhatsApp (via Twilio)
|
|
306
|
+
TWILIO_ACCOUNT_SID=...
|
|
307
|
+
TWILIO_AUTH_TOKEN=...
|
|
308
|
+
TWILIO_WHATSAPP_FROM=whatsapp:+14155238886
|
|
309
|
+
|
|
310
|
+
# Discord
|
|
311
|
+
DISCORD_BOT_TOKEN=...
|
|
312
|
+
|
|
313
|
+
# Slack
|
|
314
|
+
SLACK_BOT_TOKEN=xoxb-...
|
|
315
|
+
SLACK_APP_TOKEN=xapp-...
|
|
316
|
+
|
|
317
|
+
# Email (IMAP + SMTP)
|
|
318
|
+
EMAIL_USER=you@gmail.com
|
|
319
|
+
EMAIL_PASSWORD=your-app-password
|
|
320
|
+
EMAIL_IMAP_HOST=imap.gmail.com
|
|
321
|
+
EMAIL_SMTP_HOST=smtp.gmail.com
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Each channel supports an `{CHANNEL}_ALLOWLIST` and `{CHANNEL}_MODEL` override.
|
|
325
|
+
|
|
326
|
+
### Cost Limits
|
|
327
|
+
|
|
328
|
+
```env
|
|
329
|
+
MAX_COST_PER_TASK=0.50 # Max $ per task (agent stops mid-task if exceeded)
|
|
330
|
+
MAX_DAILY_COST=10.00 # Max $ per day across all tasks
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Security
|
|
334
|
+
|
|
335
|
+
```env
|
|
336
|
+
PERMISSION_TIER=standard # minimal | standard | full
|
|
337
|
+
ALLOWED_PATHS=/home/user/work # Sandbox: restrict file access to these directories
|
|
338
|
+
BLOCKED_PATHS=/home/user/.secrets # Always block these, even inside allowed paths
|
|
339
|
+
RESTRICT_COMMANDS=true # Block shell commands referencing paths outside sandbox
|
|
340
|
+
|
|
341
|
+
# Per-tenant API key encryption (required for production multi-tenant mode)
|
|
342
|
+
# Generate: openssl rand -hex 32
|
|
343
|
+
DAEMORA_TENANT_KEY=
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## MCP Servers
|
|
349
|
+
|
|
350
|
+
MCP (Model Context Protocol) lets Daemora control external tools. Each connected server gets a specialist sub-agent with focused context.
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
# Add a server (interactive)
|
|
354
|
+
daemora mcp add
|
|
355
|
+
|
|
356
|
+
# Add a server (command line)
|
|
357
|
+
daemora mcp add github npx -y @modelcontextprotocol/server-github
|
|
358
|
+
daemora mcp add notion npx -y @notionhq/notion-mcp-server
|
|
359
|
+
daemora mcp add myserver https://api.example.com/mcp # HTTP
|
|
360
|
+
daemora mcp add myserver https://api.example.com/sse --sse # SSE
|
|
361
|
+
|
|
362
|
+
# Manage servers
|
|
363
|
+
daemora mcp list # Show all configured servers
|
|
364
|
+
daemora mcp enable github # Enable a server
|
|
365
|
+
daemora mcp disable github # Disable without removing
|
|
366
|
+
daemora mcp reload github # Reconnect after config changes
|
|
367
|
+
daemora mcp remove github # Remove permanently
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Popular MCP servers:**
|
|
371
|
+
|
|
372
|
+
| Service | Install Command |
|
|
373
|
+
|---|---|
|
|
374
|
+
| GitHub | `npx -y @modelcontextprotocol/server-github` |
|
|
375
|
+
| Notion | `npx -y @notionhq/notion-mcp-server` |
|
|
376
|
+
| Linear | `npx -y @linear/mcp-server` |
|
|
377
|
+
| Slack | `npx -y @modelcontextprotocol/server-slack` |
|
|
378
|
+
| PostgreSQL | `npx -y @modelcontextprotocol/server-postgres` |
|
|
379
|
+
| Filesystem | `npx -y @modelcontextprotocol/server-filesystem` |
|
|
380
|
+
| Brave Search | `npx -y @anthropic-ai/brave-search-mcp-server` |
|
|
381
|
+
| Puppeteer | `npx -y @modelcontextprotocol/server-puppeteer` |
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Built-in Tools
|
|
386
|
+
|
|
387
|
+
36 tools the agent uses autonomously:
|
|
388
|
+
|
|
389
|
+
| Category | Tools |
|
|
390
|
+
|---|---|
|
|
391
|
+
| **Files** | readFile, writeFile, editFile, listDirectory, applyPatch |
|
|
392
|
+
| **Search** | searchFiles, searchContent, glob, grep |
|
|
393
|
+
| **Shell** | executeCommand (foreground + background) |
|
|
394
|
+
| **Web** | webFetch, webSearch, browserAction (navigate, click, fill, screenshot) |
|
|
395
|
+
| **Vision** | imageAnalysis, screenCapture |
|
|
396
|
+
| **Communication** | sendEmail, messageChannel, sendFile, transcribeAudio, textToSpeech |
|
|
397
|
+
| **Documents** | createDocument (Markdown, PDF, DOCX) |
|
|
398
|
+
| **Memory** | readMemory, writeMemory, searchMemory, pruneMemory, readDailyLog, writeDailyLog |
|
|
399
|
+
| **Agents** | spawnAgent, parallelAgents, delegateToAgent, manageAgents |
|
|
400
|
+
| **MCP** | useMCP, manageMCP |
|
|
401
|
+
| **Scheduling** | cron (add, list, run, update, delete) |
|
|
402
|
+
| **Tracking** | projectTracker |
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Skills
|
|
407
|
+
|
|
408
|
+
Skills inject behaviour instructions when a task matches certain keywords. Create a `.md` file in `skills/` with a YAML frontmatter:
|
|
409
|
+
|
|
410
|
+
```yaml
|
|
411
|
+
---
|
|
412
|
+
name: deploy
|
|
413
|
+
description: Handle deployment tasks for web apps and APIs
|
|
414
|
+
triggers: deploy, release, ship, production, go live
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
# Deployment Checklist
|
|
418
|
+
|
|
419
|
+
Always follow this order when deploying:
|
|
420
|
+
|
|
421
|
+
1. Run the full test suite — never deploy broken code
|
|
422
|
+
2. Check for .env differences between dev and prod
|
|
423
|
+
3. Build the production bundle
|
|
424
|
+
4. Use zero-downtime deployment if possible (blue/green, rolling)
|
|
425
|
+
5. Verify the deployment is healthy before reporting done
|
|
426
|
+
6. Notify the user with the live URL
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**21 built-in skills** cover: coding, research, email, weather, Spotify, Obsidian, Apple Notes, Apple Reminders, Things, Trello, Tmux, PDF, image generation, video frames, health checks, GIF search, webcam capture, and more.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Multi-Tenant Mode
|
|
434
|
+
|
|
435
|
+
Run Daemora as a shared agent serving multiple users. Each user gets isolated memory, filesystem, API keys, cost limits, and optionally their own model tier.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
# List all tenants (auto-created on first message per user)
|
|
439
|
+
daemora tenant list
|
|
440
|
+
|
|
441
|
+
# Set a per-user daily cost cap
|
|
442
|
+
daemora tenant set telegram:123 maxDailyCost 2.00
|
|
443
|
+
|
|
444
|
+
# Restrict which tools a tenant can use
|
|
445
|
+
daemora tenant set telegram:123 tools readFile,webSearch,sendEmail
|
|
446
|
+
|
|
447
|
+
# Restrict which MCP servers a tenant can access
|
|
448
|
+
daemora tenant set telegram:123 mcpServers github,notion
|
|
449
|
+
|
|
450
|
+
# Assign a model tier
|
|
451
|
+
daemora tenant plan telegram:123 pro
|
|
452
|
+
|
|
453
|
+
# Store a tenant's own OpenAI key (AES-256-GCM encrypted at rest)
|
|
454
|
+
daemora tenant apikey set telegram:123 OPENAI_API_KEY sk-their-key
|
|
455
|
+
|
|
456
|
+
# Suspend a user
|
|
457
|
+
daemora tenant suspend telegram:123 "Exceeded usage policy"
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Per-tenant isolation:
|
|
461
|
+
|
|
462
|
+
| Isolation | Mechanism |
|
|
463
|
+
|---|---|
|
|
464
|
+
| Memory | `data/tenants/{id}/MEMORY.md` — never shared across users |
|
|
465
|
+
| Filesystem | `allowedPaths` and `blockedPaths` scoped per user |
|
|
466
|
+
| API keys | AES-256-GCM encrypted; passed through call stack, never via `process.env` |
|
|
467
|
+
| Cost tracking | Per-tenant daily cost recorded in audit log |
|
|
468
|
+
| MCP servers | `mcpServers` field restricts which servers a tenant can call |
|
|
469
|
+
| Tools | `tools` allowlist limits which tools the agent can use for this user |
|
|
470
|
+
|
|
471
|
+
All isolation runs via `AsyncLocalStorage` — concurrent tasks from different users cannot read each other's context.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Security
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Run a full security audit
|
|
479
|
+
daemora doctor
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
| Feature | Description |
|
|
483
|
+
|---|---|
|
|
484
|
+
| **Permission tiers** | `minimal` / `standard` / `full` — controls which tools the agent can call |
|
|
485
|
+
| **Filesystem sandbox** | Directory scoping via `ALLOWED_PATHS`, hardcoded blocks for `.ssh`, `.env`, `.aws` |
|
|
486
|
+
| **Secret vault** | AES-256-GCM encrypted secrets, passphrase required on start |
|
|
487
|
+
| **Channel allowlists** | Per-channel user ID whitelist — blocks unknown senders |
|
|
488
|
+
| **Secret scanning** | Redacts API keys and tokens from tool output before the model sees them |
|
|
489
|
+
| **Dynamic redaction** | Per-tenant API keys are also redacted from all tool outputs |
|
|
490
|
+
| **Supervisor agent** | Detects runaway loops, cost overruns, `rm -rf`, `curl | bash` patterns |
|
|
491
|
+
| **Audit log** | Every tool call logged to `data/audit/` — append-only JSONL, secrets stripped |
|
|
492
|
+
| **Input sanitisation** | User messages wrapped in `<untrusted-input>` tags; prompt injection patterns flagged |
|
|
493
|
+
| **A2A security** | Agent-to-agent protocol: bearer token, agent allowlist, rate limiting |
|
|
494
|
+
| **Tenant isolation** | AsyncLocalStorage — no cross-tenant data leakage in concurrent requests |
|
|
495
|
+
| **Per-tenant API key isolation** | Keys never touch `process.env` — passed through call stack only |
|
|
496
|
+
| **Git rollback** | Snapshot before write operations — undo with `git stash pop` |
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## CLI Reference
|
|
501
|
+
|
|
502
|
+
```
|
|
503
|
+
daemora start Start the agent server
|
|
504
|
+
daemora setup Interactive setup wizard
|
|
505
|
+
daemora doctor Security audit — 8-check scored report
|
|
506
|
+
|
|
507
|
+
daemora mcp list List all MCP servers
|
|
508
|
+
daemora mcp add Add an MCP server (interactive)
|
|
509
|
+
daemora mcp add <name> <cmd> Add an MCP server (non-interactive)
|
|
510
|
+
daemora mcp remove <name> Remove an MCP server
|
|
511
|
+
daemora mcp enable <name> Enable a disabled server
|
|
512
|
+
daemora mcp disable <name> Disable without removing
|
|
513
|
+
daemora mcp reload <name> Reconnect a server
|
|
514
|
+
|
|
515
|
+
daemora daemon install Install as a system daemon
|
|
516
|
+
daemora daemon start Start the daemon
|
|
517
|
+
daemora daemon stop Stop the daemon
|
|
518
|
+
daemora daemon status Check daemon status
|
|
519
|
+
daemora daemon logs View daemon logs
|
|
520
|
+
|
|
521
|
+
daemora vault set <key> Store an encrypted secret
|
|
522
|
+
daemora vault get <key> Retrieve a secret
|
|
523
|
+
daemora vault list List all secret keys
|
|
524
|
+
daemora vault unlock Unlock the vault
|
|
525
|
+
|
|
526
|
+
daemora sandbox show Show current sandbox rules
|
|
527
|
+
daemora sandbox add <path> Allow a directory (activates scoped mode)
|
|
528
|
+
daemora sandbox remove <path> Remove from allowed list
|
|
529
|
+
daemora sandbox block <path> Always block a path
|
|
530
|
+
daemora sandbox restrict Enable command restriction
|
|
531
|
+
daemora sandbox clear Back to unrestricted mode
|
|
532
|
+
|
|
533
|
+
daemora tenant list List all tenants
|
|
534
|
+
daemora tenant show <id> Show tenant config
|
|
535
|
+
daemora tenant set <id> <k> <v> Set a tenant config value
|
|
536
|
+
daemora tenant plan <id> <plan> Set tenant plan (free/pro/admin)
|
|
537
|
+
daemora tenant suspend <id> Suspend a tenant
|
|
538
|
+
daemora tenant unsuspend <id> Unsuspend a tenant
|
|
539
|
+
daemora tenant apikey set <id> <KEY> <value> Store per-tenant API key (encrypted)
|
|
540
|
+
daemora tenant apikey delete <id> <KEY> Remove a per-tenant API key
|
|
541
|
+
daemora tenant apikey list <id> List stored key names (values never shown)
|
|
542
|
+
|
|
543
|
+
daemora help Show full help
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## HTTP API
|
|
549
|
+
|
|
550
|
+
The agent exposes a REST API on `http://localhost:8081`.
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
# System health
|
|
554
|
+
curl http://localhost:8081/health
|
|
555
|
+
|
|
556
|
+
# List recent tasks
|
|
557
|
+
curl http://localhost:8081/tasks
|
|
558
|
+
|
|
559
|
+
# Get task status
|
|
560
|
+
curl http://localhost:8081/tasks/{taskId}
|
|
561
|
+
|
|
562
|
+
# Today's API costs
|
|
563
|
+
curl http://localhost:8081/costs/today
|
|
564
|
+
|
|
565
|
+
# List tenants
|
|
566
|
+
curl http://localhost:8081/tenants
|
|
567
|
+
|
|
568
|
+
# List MCP servers
|
|
569
|
+
curl http://localhost:8081/mcp
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
> POST /chat and POST /tasks (unauthenticated task submission) are disabled by default — use a channel (Telegram, Slack, etc.) instead.
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## Self-Hosting
|
|
577
|
+
|
|
578
|
+
Daemora runs entirely on your own machine. Nothing is sent to any third party beyond the AI model APIs you configure.
|
|
579
|
+
|
|
580
|
+
**Requirements:**
|
|
581
|
+
- Node.js 20+
|
|
582
|
+
- 512 MB RAM minimum
|
|
583
|
+
- macOS, Linux, or Windows WSL
|
|
584
|
+
|
|
585
|
+
**Production setup:**
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
npm install -g daemora
|
|
589
|
+
daemora setup
|
|
590
|
+
daemora daemon install
|
|
591
|
+
daemora daemon start
|
|
592
|
+
daemora doctor # verify security configuration
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Use nginx or Caddy as a reverse proxy for HTTPS if exposing the API port.
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## Tech Stack
|
|
600
|
+
|
|
601
|
+
| Layer | Technology |
|
|
602
|
+
|---|---|
|
|
603
|
+
| Runtime | Node.js 20+ — ES modules, no build step |
|
|
604
|
+
| AI SDK | Vercel AI SDK (`ai`) — model-agnostic, 25+ providers |
|
|
605
|
+
| Models | OpenAI, Anthropic, Google Gemini, Ollama (local) |
|
|
606
|
+
| MCP | `@modelcontextprotocol/sdk` — stdio, HTTP, SSE |
|
|
607
|
+
| Channels | grammy, twilio, discord.js, @slack/bolt, nodemailer/imap, botbuilder, google-auth-library |
|
|
608
|
+
| Scheduling | node-cron |
|
|
609
|
+
| Vault | Node.js `crypto` built-in — AES-256-GCM + scrypt, no binary deps |
|
|
610
|
+
| Sandbox | Node.js tool-level path enforcement — no Docker required |
|
|
611
|
+
| Storage | File-based (Markdown + JSON) — no database |
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## vs OpenClaw
|
|
616
|
+
|
|
617
|
+
Daemora was built in response to OpenClaw's security weaknesses. Key differences:
|
|
618
|
+
|
|
619
|
+
| Feature | Daemora | OpenClaw |
|
|
620
|
+
|---|---|---|
|
|
621
|
+
| Multi-tenant isolation | Full (AsyncLocalStorage) | None |
|
|
622
|
+
| Per-tenant memory | Isolated per user | Shared — User A sees User B's memories |
|
|
623
|
+
| Per-tenant API keys | AES-256-GCM, call stack only | None |
|
|
624
|
+
| Filesystem sandbox | Directory scoping + blocklist | None |
|
|
625
|
+
| Secret vault | AES-256-GCM encrypted | Plaintext `.env` only |
|
|
626
|
+
| Audit log | Full, per-tenant, secrets stripped | Partial |
|
|
627
|
+
| Security audit | `daemora doctor` (8 checks, scored) | None |
|
|
628
|
+
| A2A protocol | Auth + allowlist + rate limiting | None |
|
|
629
|
+
| Supervisor agent | Built-in | Manual |
|
|
630
|
+
| Task-type model routing | CODE_MODEL / RESEARCH_MODEL / etc. | None |
|
|
631
|
+
| Sub-agent model inheritance | Inherits parent model | Falls back to default |
|
|
632
|
+
| Setup | `npm install -g daemora && daemora start` | Complex multi-step with Docker/WSL |
|
|
633
|
+
| Codebase size | ~5k LOC, no build | 80k+ LOC, TypeScript build |
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
## Contributing
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
git clone https://github.com/umarfarooq/daemora-agent.git
|
|
641
|
+
cd daemora-agent
|
|
642
|
+
npm install
|
|
643
|
+
cp .env.example .env
|
|
644
|
+
# Add your API keys to .env
|
|
645
|
+
daemora setup
|
|
646
|
+
daemora start
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Contributions are welcome. Please open an issue before submitting large PRs.
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## License
|
|
654
|
+
|
|
655
|
+
**AGPL-3.0** — Daemora is open source. If you modify Daemora and distribute it, or run it as a network service, you must open-source your changes under AGPL-3.0.
|
|
656
|
+
|
|
657
|
+
See [LICENSE](LICENSE) for the full text.
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
## Links
|
|
662
|
+
|
|
663
|
+
- **Website:** https://daemora.com
|
|
664
|
+
- **npm:** https://npmjs.com/package/daemora
|
|
665
|
+
- **GitHub:** https://github.com/umarfarooq/daemora-agent
|
|
666
|
+
- **Issues:** https://github.com/umarfarooq/daemora-agent/issues
|