alvin-bot 4.5.0 → 4.6.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/README.md +25 -2
  3. package/alvin-bot-4.5.1.tgz +0 -0
  4. package/bin/cli.js +246 -0
  5. package/dist/handlers/commands.js +461 -63
  6. package/dist/handlers/message.js +209 -14
  7. package/dist/i18n.js +470 -13
  8. package/dist/index.js +44 -5
  9. package/dist/providers/claude-sdk-provider.js +106 -14
  10. package/dist/providers/ollama-provider.js +32 -0
  11. package/dist/providers/openai-compatible.js +10 -1
  12. package/dist/providers/registry.js +112 -17
  13. package/dist/providers/types.js +25 -3
  14. package/dist/services/compaction.js +2 -0
  15. package/dist/services/cron.js +53 -42
  16. package/dist/services/heartbeat.js +41 -7
  17. package/dist/services/language-detect.js +12 -2
  18. package/dist/services/ollama-manager.js +339 -0
  19. package/dist/services/personality.js +20 -14
  20. package/dist/services/session.js +21 -3
  21. package/dist/services/subagent-delivery.js +111 -0
  22. package/dist/services/subagents.js +341 -27
  23. package/dist/services/telegram.js +28 -1
  24. package/dist/services/updater.js +158 -0
  25. package/dist/services/usage-tracker.js +11 -4
  26. package/dist/services/users.js +2 -1
  27. package/dist/tui/index.js +36 -30
  28. package/docs/HANDBOOK.md +819 -0
  29. package/package.json +7 -2
  30. package/test/claude-sdk-provider.test.ts +69 -0
  31. package/test/i18n.test.ts +108 -0
  32. package/test/registry.test.ts +201 -0
  33. package/test/subagent-delivery.test.ts +169 -0
  34. package/test/subagents-commands.test.ts +64 -0
  35. package/test/subagents-config.test.ts +108 -0
  36. package/test/subagents-depth.test.ts +58 -0
  37. package/test/subagents-inheritance.test.ts +67 -0
  38. package/test/subagents-name-resolver.test.ts +122 -0
  39. package/test/subagents-priority-reject.test.ts +60 -0
  40. package/test/subagents-shutdown.test.ts +126 -0
  41. package/test/subagents-toolset.test.ts +51 -0
  42. package/vitest.config.ts +17 -0
@@ -0,0 +1,819 @@
1
+ # Alvin Bot Handbook
2
+
3
+ > A complete, standalone reference for everything Alvin Bot can do — installation, architecture, providers, sub-agents, cron jobs, plugins, MCP, platforms, security, and troubleshooting. Written for users who want to understand the whole system, not just the quick-start.
4
+
5
+ ---
6
+
7
+ ## Table of contents
8
+
9
+ 1. [What Alvin Bot is](#1-what-alvin-bot-is)
10
+ 2. [Installation](#2-installation)
11
+ 3. [First run: the setup wizard](#3-first-run-the-setup-wizard)
12
+ 4. [Architecture at a glance](#4-architecture-at-a-glance)
13
+ 5. [AI providers](#5-ai-providers)
14
+ 6. [The chat session model](#6-the-chat-session-model)
15
+ 7. [Sub-agents](#7-sub-agents)
16
+ 8. [Cron jobs](#8-cron-jobs)
17
+ 9. [Commands reference](#9-commands-reference)
18
+ 10. [Platforms: Telegram, WhatsApp, Discord, Signal, Web, TUI](#10-platforms)
19
+ 11. [Plugins and MCP servers](#11-plugins-and-mcp-servers)
20
+ 12. [Skills](#12-skills)
21
+ 13. [Security](#13-security)
22
+ 14. [Running in production](#14-running-in-production)
23
+ 15. [Troubleshooting](#15-troubleshooting)
24
+ 16. [Upgrading](#16-upgrading)
25
+
26
+ ---
27
+
28
+ ## 1. What Alvin Bot is
29
+
30
+ Alvin Bot is a self-hosted AI agent that lives where you chat. Instead of being a single-purpose chatbot, it connects a multi-model engine (Claude, OpenAI, Gemini, Groq, NVIDIA NIM, Ollama, OpenRouter, or any OpenAI-compatible endpoint) to every messaging platform you care about (Telegram, WhatsApp, Discord, Signal, Web UI, terminal), plus a set of superpowers: persistent memory, cron jobs, file access, skill files, MCP tool use, sub-agents for parallel work, and a comprehensive security audit.
31
+
32
+ The design goal is **"the assistant that actually lives on your machine"**: it has real tool access (not a sandboxed chat), it remembers across sessions, it runs scheduled tasks, and you talk to it through whatever app you already have open.
33
+
34
+ **Alvin Bot is the bot process.** Your identity — what it calls you, your preferences, long-running context — lives in `~/.alvin-bot/memory/` and is independent of the bot version.
35
+
36
+ ---
37
+
38
+ ## 2. Installation
39
+
40
+ ### 2.1 Quickest path — npm
41
+
42
+ ```bash
43
+ npm install -g alvin-bot
44
+ alvin-bot setup
45
+ alvin-bot start
46
+ ```
47
+
48
+ Requirements:
49
+ - Node.js 18 or newer
50
+ - A Telegram bot token (free from [@BotFather](https://t.me/BotFather))
51
+ - Your Telegram user ID (from [@userinfobot](https://t.me/userinfobot))
52
+
53
+ Everything else — an AI provider key — the setup wizard walks you through.
54
+
55
+ ### 2.2 From source
56
+
57
+ ```bash
58
+ git clone https://github.com/alvbln/Alvin-Bot.git
59
+ cd Alvin-Bot
60
+ npm install
61
+ npm run build
62
+ node bin/cli.js setup
63
+ node bin/cli.js start
64
+ ```
65
+
66
+ This is the path if you want to track `main` or apply local patches.
67
+
68
+ ### 2.3 One-line install script
69
+
70
+ ```bash
71
+ curl -fsSL https://raw.githubusercontent.com/alvbln/Alvin-Bot/main/install.sh | bash
72
+ ```
73
+
74
+ Downloads, builds, and runs the setup wizard in one shot. Linux and macOS only.
75
+
76
+ ### 2.4 Desktop app (macOS)
77
+
78
+ Download the latest `.dmg` from [GitHub Releases](https://github.com/alvbln/Alvin-Bot/releases). The desktop app wraps the bot in an Electron shell with a system tray icon, auto-updater, and the embedded web UI.
79
+
80
+ Current build: Apple Silicon (arm64). Windows and Linux desktop builds are on the roadmap.
81
+
82
+ ### 2.5 Docker
83
+
84
+ ```bash
85
+ docker compose up -d
86
+ ```
87
+
88
+ Use this for headless servers. See `docker-compose.yml` for the expected environment variables.
89
+
90
+ ### 2.6 The data directory
91
+
92
+ Alvin Bot stores all user data under `~/.alvin-bot/` (overridable via the `ALVIN_DATA_DIR` environment variable):
93
+
94
+ ```
95
+ ~/.alvin-bot/
96
+ ├── .env # bot token, API keys, config
97
+ ├── memory/ # long-term memory (vector-indexed)
98
+ ├── sessions/ # session transcripts
99
+ ├── cron-jobs.json # scheduled jobs
100
+ ├── sub-agents.json # sub-agent config (maxParallel, visibility)
101
+ ├── delivery-queue.json # pending outgoing messages with retry
102
+ ├── logs/ # stdout/stderr if running under launchd
103
+ ├── custom-models.json # user-added OpenAI-compatible providers
104
+ ├── users/ # multi-user approval + preferences
105
+ └── whatsapp-groups.json # WhatsApp group allowlist
106
+ ```
107
+
108
+ The bot code itself lives wherever you installed it (`/usr/local/lib/node_modules/alvin-bot` for npm-global, or your git clone directory). The data directory is portable: copy it between machines and the bot comes up with the same memories, jobs, and settings.
109
+
110
+ ---
111
+
112
+ ## 3. First run: the setup wizard
113
+
114
+ Running `alvin-bot setup` walks you through four screens:
115
+
116
+ 1. **AI provider** — pick one of the supported providers. Free options first (Groq, Gemini, NVIDIA NIM, Ollama, Claude Max via the CLI). The wizard validates the API key with a test call before saving.
117
+ 2. **Telegram bot token** — paste the token from BotFather. The wizard calls `getMe` to confirm it's valid and shows you the bot's handle.
118
+ 3. **Authorized user ID** — paste your Telegram user ID. Only users listed in `ALLOWED_USERS` can chat with the bot; everyone else gets a silent deny.
119
+ 4. **Optional platforms** — Slack, WhatsApp, Discord, Signal. Each is configured independently; skip any you don't use.
120
+
121
+ All values land in `~/.alvin-bot/.env` so you can edit them later.
122
+
123
+ ---
124
+
125
+ ## 4. Architecture at a glance
126
+
127
+ ```
128
+ ┌─────────────────────────────────────────────────────────────┐
129
+ │ Platform layer │
130
+ │ Telegram · WhatsApp · Discord · Signal · Slack · TUI · Web │
131
+ └──────────────────────────┬──────────────────────────────────┘
132
+
133
+ platform-message
134
+
135
+ ┌──────────────────────────▼──────────────────────────────────┐
136
+ │ Handler layer │
137
+ │ handleMessage · handleVoice · handlePhoto · handleDocument │
138
+ └──────────────────────────┬──────────────────────────────────┘
139
+
140
+ Engine.query()
141
+
142
+ ┌──────────────────────────▼──────────────────────────────────┐
143
+ │ Provider registry │
144
+ │ Claude SDK · OpenAI-compat · Codex CLI · Ollama · custom... │
145
+ │ Heartbeat monitor · fallback chain · retry on transient │
146
+ └──────────────────────────┬──────────────────────────────────┘
147
+
148
+ ┌──────────────────────────▼──────────────────────────────────┐
149
+ │ Services │
150
+ │ Memory · Sub-agents · Cron · Skills · MCP · Plugins · Queue │
151
+ └─────────────────────────────────────────────────────────────┘
152
+ ```
153
+
154
+ Everything is wired together in `src/index.ts`. The process boots by:
155
+
156
+ 1. Creating `~/.alvin-bot/` and migrating any legacy data
157
+ 2. Validating the `.env` against the chosen provider
158
+ 3. Initializing the provider registry
159
+ 4. Loading plugins and MCP servers
160
+ 5. Creating the grammy bot instance and attaching the sub-agent delivery router
161
+ 6. Starting the web server, cron scheduler, delivery queue, and heartbeat
162
+ 7. Starting optional platform adapters
163
+ 8. Beginning Telegram polling
164
+
165
+ A `shutdown()` function in the same file runs in reverse: cancel all running sub-agents (with Telegram notifications), stop the scheduler, drain the delivery queue, unload plugins, disconnect MCP, tear down provider lifecycles (Ollama, LM Studio), then exit cleanly.
166
+
167
+ ---
168
+
169
+ ## 5. AI providers
170
+
171
+ Alvin Bot supports a multi-provider registry with a fallback chain. You pick a primary, optionally define fallbacks, and the bot picks the best available provider per request.
172
+
173
+ ### 5.1 Built-in providers
174
+
175
+ | Registry key | Source | Auth | Cost | Notes |
176
+ |---|---|---|---|---|
177
+ | `claude-sdk` | Anthropic Claude Code SDK | OAuth (Claude Max) or API key | Max plan or per-token | Full tool use: Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, Task. Needs the `claude` CLI installed. |
178
+ | `codex-cli` | OpenAI Codex CLI | Local CLI | Per-token | Needs the `codex` CLI installed. |
179
+ | `google` | Google Gemini 2.5 Flash | `GOOGLE_API_KEY` | Free tier available | Vision + embeddings. |
180
+ | `ollama` | Local Ollama daemon | none | Free | Auto-detected. Bot can start/stop the Ollama daemon on demand. |
181
+
182
+ ### 5.2 Custom providers
183
+
184
+ Any OpenAI-compatible endpoint (Groq, NVIDIA NIM, OpenRouter, LM Studio, vLLM, any self-hosted LLM server) goes into `~/.alvin-bot/custom-models.json`:
185
+
186
+ ```json
187
+ [
188
+ {
189
+ "key": "groq",
190
+ "name": "Groq (Llama 3.3 70B)",
191
+ "model": "llama-3.3-70b-versatile",
192
+ "baseUrl": "https://api.groq.com/openai/v1",
193
+ "apiKeyEnv": "GROQ_API_KEY",
194
+ "supportsVision": false,
195
+ "supportsStreaming": true,
196
+ "maxTokens": 32768
197
+ }
198
+ ]
199
+ ```
200
+
201
+ Set `PRIMARY_PROVIDER=groq` in `.env` and add `GROQ_API_KEY`. The setup wizard writes this for you for the common providers.
202
+
203
+ ### 5.3 The fallback chain
204
+
205
+ `.env` can define a fallback order:
206
+
207
+ ```
208
+ PRIMARY_PROVIDER=claude-sdk
209
+ FALLBACK_PROVIDERS=google,groq
210
+ ```
211
+
212
+ On every query, the registry tries the primary first. If it's unavailable (auth fails, rate-limited, service down), it cascades through the fallback list in order. The registry also learns — a provider that fails twice in a row gets temporarily deprioritized until the heartbeat monitor confirms it's healthy again.
213
+
214
+ ### 5.4 The heartbeat monitor
215
+
216
+ Every 5 minutes, the heartbeat monitor pings each configured provider with a tiny probe. Providers that fail twice in a row are marked unhealthy and get skipped until they recover. You see the current state in `/status` and in the web UI's Dashboard.
217
+
218
+ ### 5.5 Model switching from chat
219
+
220
+ `/model` — pick a different provider as your current primary.
221
+ `/fallback` — rearrange the fallback chain from Telegram.
222
+ `/effort low|medium|high|max` — adjust reasoning depth (where supported).
223
+
224
+ Switches are session-scoped by default; persist via `/model save` or the web UI.
225
+
226
+ ---
227
+
228
+ ## 6. The chat session model
229
+
230
+ Alvin Bot separates **sessions** from **users**. Every platform identity maps to a session, and sessions carry:
231
+
232
+ - Current provider and fallback chain
233
+ - Conversation history (bounded — older messages age out)
234
+ - Active skills and personality flags
235
+ - Working directory (from `/dir`)
236
+ - Locale (`/language`)
237
+
238
+ Session isolation is configurable via the `SESSION_MODE` env var:
239
+
240
+ - `per-user` (default) — one shared session per authorized user across all their platform identities. `/new` on Telegram wipes the history for the TUI too.
241
+ - `per-channel` — each platform gets its own session. `/new` on Telegram leaves the TUI untouched.
242
+ - `per-channel-peer` — each platform × user combo gets its own session. Useful when you share a bot between family members.
243
+
244
+ Memory (the long-term knowledge base at `~/.alvin-bot/memory/`) is **always** per-user, regardless of session mode.
245
+
246
+ ### 6.1 Long-running sessions
247
+
248
+ Alvin Bot's defining feature is that **he can think for as long as he needs**. There is no absolute timeout on a query — the only cap is an adaptive "stuck" detector that fires if there's no progress (no text, no tool calls) for `ALVIN_STUCK_TIMEOUT_MINUTES` (default: 10). A legitimate 40-minute reasoning run with continuous tool use never gets killed.
249
+
250
+ This is deliberate and different from most AI chat wrappers. It means Alvin can work overnight on a research task and deliver the answer when you wake up.
251
+
252
+ ### 6.2 Mid-stream abort and resume
253
+
254
+ If a provider drops the connection mid-stream (network blip, provider restart), the registry silently retries the **same** provider once. If visible text was already streamed to the user, mid-stream failover is disabled — we don't fail over to a different provider mid-answer because that would jumble the response.
255
+
256
+ ---
257
+
258
+ ## 7. Sub-agents
259
+
260
+ **Sub-agents are parallel isolated workers that run in the background.** Use them when you have multiple independent tasks, when you need to keep a long-running task from blocking your main chat, or when you want to dispatch work from a cron job.
261
+
262
+ The system distinguishes three sources:
263
+
264
+ | Source | Origin | Delivery |
265
+ |---|---|---|
266
+ | `implicit` | Main Claude calls the SDK `Task` tool | Parent stream (no separate delivery) |
267
+ | `user` | You ask the bot to spawn a sub-agent | Banner + final to your chat |
268
+ | `cron` | Scheduled job uses `ai-query` | Banner + final to `chatId` in the cron job's target |
269
+
270
+ ### 7.1 Spawning
271
+
272
+ From chat, the easiest way is to ask Main Claude to spawn one:
273
+
274
+ > *spawne einen sub-agent der mir in einem Wort 'pong' zurückgibt*
275
+
276
+ Claude invokes the SDK `Task` tool, which runs as `source: "implicit"`. The result streams back into the parent message.
277
+
278
+ From a cron job of type `ai-query`, the scheduler calls `spawnSubAgent({ source: "cron" })` internally. The cron job's `target.chatId` becomes the `parentChatId` so the delivery lands in the right chat.
279
+
280
+ ### 7.2 The `/subagents` command
281
+
282
+ | Command | Effect |
283
+ |---|---|
284
+ | `/subagents` | Show status: max parallel, visibility mode, running list |
285
+ | `/subagents max <n>` | Set max parallel (0 = auto = min(cpu, 16)) |
286
+ | `/subagents visibility auto\|banner\|silent` | Default delivery mode for new spawns |
287
+ | `/subagents list` | Tree view with depth indent and source badges |
288
+ | `/subagents cancel <name\|id>` | Cancel a running sub-agent |
289
+ | `/subagents result <name\|id>` | Show a completed sub-agent's stored result |
290
+
291
+ ### 7.3 Name-first addressing
292
+
293
+ Sub-agents are addressable by name, not just UUID. If you spawn three agents called `code-review` in quick succession, they appear as `code-review`, `code-review#2`, `code-review#3` in `/subagents list`. The name-resolver handles collisions automatically.
294
+
295
+ `/subagents cancel code-review#2` cancels the second one specifically. `/subagents cancel code-review` on an unambiguous base name cancels that one. On an ambiguous base name, the bot replies with a disambiguation list.
296
+
297
+ ### 7.4 Depth cap (F2)
298
+
299
+ Nested spawning is allowed up to depth 2:
300
+
301
+ - depth 0 = root (spawned by main thread)
302
+ - depth 1 = spawned by a depth-0 agent
303
+ - depth 2 = spawned by a depth-1 agent
304
+ - depth 3 = rejected
305
+
306
+ This allows the "scatter-gather" pattern (main → orchestrator → 10 workers) without runaway recursion.
307
+
308
+ ### 7.5 Visibility modes
309
+
310
+ - `auto` (default) — source-based routing: implicit stays in the parent stream, user and cron get a banner+final delivery.
311
+ - `banner` — always send a banner+final, even for implicit spawns.
312
+ - `silent` — never send. The result is still stored in the activeAgents map for 30 minutes and pullable via `/subagents result <name>`.
313
+
314
+ ### 7.6 Inheritance
315
+
316
+ Sub-agents inherit from the spawning context:
317
+
318
+ - **Working directory** — the parent's `cwd` (from `/dir`). Opt out with `inheritCwd: false`.
319
+ - **CLAUDE.md** — via the Claude SDK's `settingSources: ["project"]`. Loads automatically if the cwd is inside a project with a CLAUDE.md.
320
+ - **Model and tools** — inherited via the provider registry.
321
+ - **Conversation history** — **not inherited.** Sub-agents receive only their own prompt. This forces clean, self-describing spawn requests.
322
+
323
+ ### 7.7 Shutdown notifications
324
+
325
+ When you restart the bot (SIGTERM), any still-running sub-agents get a cancellation delivery before the process exits:
326
+
327
+ > ⚠️ `<name>` cancelled · `<duration>` · 0 in / 0 out
328
+ > ⚠️ Agent wurde durch Bot-Restart unterbrochen. Bitte neu triggern.
329
+
330
+ The shutdown phase is capped at 5 seconds total so a hanging Telegram send can't block the restart.
331
+
332
+ ---
333
+
334
+ ## 8. Cron jobs
335
+
336
+ Scheduled tasks that run regardless of whether you're chatting with the bot. Use them for daily news digests, weekly reports, periodic health checks, or any recurring automation.
337
+
338
+ ### 8.1 Job types
339
+
340
+ | Type | Payload | Execution |
341
+ |---|---|---|
342
+ | `reminder` | `text` | Sends the text to the target chat at the scheduled time |
343
+ | `message` | `text` | Same as reminder |
344
+ | `shell` | `command` | Runs the shell command, sends the output |
345
+ | `http` | `url`, `method`, `headers`, `body` | Fires an HTTP request, sends the response |
346
+ | `ai-query` | `prompt` | Spawns a sub-agent with `source: "cron"`, result delivered via I3 |
347
+
348
+ ### 8.2 Scheduling syntax
349
+
350
+ Supports two formats:
351
+
352
+ - **Interval** — `30s`, `5m`, `1h`, `6h`, `1d`
353
+ - **Cron** — standard 5-field (`MIN HOUR DAY MONTH WEEKDAY`, 0 = Sunday)
354
+
355
+ ### 8.3 Managing jobs
356
+
357
+ From Telegram:
358
+
359
+ ```
360
+ /cron — list all jobs
361
+ /cron add — create a new one (interactive)
362
+ /cron delete <id> — remove a job
363
+ /cron toggle <id> — enable/disable
364
+ /cron run <id> — trigger a job immediately, outside its schedule
365
+ ```
366
+
367
+ From the command line (useful for scripts):
368
+
369
+ ```
370
+ node scripts/cron-manage.js add \
371
+ --name "Daily email summary" \
372
+ --type ai-query \
373
+ --schedule "0 8 * * *" \
374
+ --prompt "Check my inbox and summarize unread messages" \
375
+ --chatId <your-telegram-id>
376
+
377
+ node scripts/cron-manage.js list
378
+ node scripts/cron-manage.js delete --id <job-id>
379
+ ```
380
+
381
+ The scheduler polls `~/.alvin-bot/cron-jobs.json` every 30 seconds, so hand-edited jobs come into effect at the next tick without a bot restart.
382
+
383
+ ### 8.4 Delivery
384
+
385
+ ai-query jobs route through the sub-agent delivery router (see §7). Other job types (reminder, shell, http, message) use the legacy delivery-queue path with retry and exponential backoff. Both paths respect the job's `target.platform` and `target.chatId`.
386
+
387
+ ---
388
+
389
+ ## 9. Commands reference
390
+
391
+ All commands are triggered from any platform that supports commands (Telegram, Discord).
392
+
393
+ ### 9.1 Core
394
+
395
+ | Command | Purpose |
396
+ |---|---|
397
+ | `/start` | Show the bot intro |
398
+ | `/help` | List all commands |
399
+ | `/new` | Start a fresh session (wipes current history) |
400
+ | `/status` | Current status: provider, model, session age, token usage |
401
+ | `/cancel` | Cancel the currently running request |
402
+ | `/dir <path>` | Change the bot's working directory |
403
+
404
+ ### 9.2 AI control
405
+
406
+ | Command | Purpose |
407
+ |---|---|
408
+ | `/model` | Switch provider |
409
+ | `/model save` | Persist the current provider as default |
410
+ | `/fallback` | Rearrange fallback chain |
411
+ | `/effort low\|medium\|high\|max` | Set reasoning depth |
412
+ | `/voice on\|off` | Toggle voice replies (ElevenLabs or Edge TTS) |
413
+ | `/language en\|de\|es\|fr` | Switch session locale |
414
+
415
+ ### 9.3 Memory and history
416
+
417
+ | Command | Purpose |
418
+ |---|---|
419
+ | `/remember <text>` | Add something to long-term memory |
420
+ | `/recall <query>` | Semantic search across memories |
421
+ | `/export` | Export the current conversation to JSON |
422
+
423
+ ### 9.4 Tools
424
+
425
+ | Command | Purpose |
426
+ |---|---|
427
+ | `/web <query>` | Quick web search |
428
+ | `/imagine <prompt>` | Generate an image (Gemini Nano Banana / Google Imagen) |
429
+ | `/remind 30m <text>` | One-shot reminder |
430
+
431
+ ### 9.5 Bot management
432
+
433
+ | Command | Purpose |
434
+ |---|---|
435
+ | `/cron` | Manage scheduled jobs |
436
+ | `/subagents` | Manage sub-agents |
437
+ | `/webui` | Open web UI URL |
438
+ | `/setup` | Re-run the setup wizard flow from chat |
439
+ | `/restart` | Restart the bot process |
440
+ | `/update` | Pull latest, rebuild, restart |
441
+ | `/autoupdate on\|off\|status` | Configure auto-update |
442
+
443
+ ### 9.6 CLI commands (from a terminal)
444
+
445
+ | Command | Purpose |
446
+ |---|---|
447
+ | `alvin-bot setup` | Initial setup wizard |
448
+ | `alvin-bot start` | Start in background (pm2) |
449
+ | `alvin-bot start -f` | Start in foreground (for debugging) |
450
+ | `alvin-bot stop` | Stop the bot |
451
+ | `alvin-bot tui` | Terminal chat UI |
452
+ | `alvin-bot doctor` | Health check and diagnostics |
453
+ | `alvin-bot audit` | Security audit |
454
+ | `alvin-bot search <query>` | Search assets, memories, and skills |
455
+ | `alvin-bot update` | Git pull, npm install, rebuild |
456
+ | `alvin-bot launchd install` | **macOS only** — install as LaunchAgent (see §14.1) |
457
+ | `alvin-bot launchd uninstall` | Remove the LaunchAgent |
458
+ | `alvin-bot launchd status` | Show LaunchAgent state + recent logs |
459
+ | `alvin-bot version` | Print version |
460
+
461
+ ---
462
+
463
+ ## 10. Platforms
464
+
465
+ ### 10.1 Telegram
466
+
467
+ The primary platform. Full support: streaming messages, inline keyboards, voice transcription (via OpenAI Whisper or Edge TTS), photo understanding, document ingestion, sticker replies, command autocomplete.
468
+
469
+ Setup: `BOT_TOKEN` from BotFather + your user ID in `ALLOWED_USERS`.
470
+
471
+ ### 10.2 WhatsApp
472
+
473
+ Via WhatsApp Web using `whatsapp-web.js`. Two modes:
474
+
475
+ - **Self-chat** — treat your own WhatsApp number as a personal assistant notepad
476
+ - **Group whitelist** — the bot only responds in explicitly allowed groups, with per-contact access control inside those groups
477
+
478
+ Group messages go through an approval flow: the owner gets a Telegram notification (or WhatsApp DM fallback) before the bot responds, so there's no surprise chatter from the bot in a group.
479
+
480
+ Setup: scan the QR code printed on bot startup. Session cookies persist in `~/.alvin-bot/.wwebjs_auth/`.
481
+
482
+ ### 10.3 Discord
483
+
484
+ Bot with mention detection, slash commands, voice channel support. Uses the standard Discord bot token flow.
485
+
486
+ Setup: `DISCORD_TOKEN` in `.env`, invite the bot to your server with the correct intents (Message Content + Guild Messages).
487
+
488
+ ### 10.4 Signal
489
+
490
+ Via `signal-cli` REST API. Less feature-rich than the others because of Signal's tight UI model, but text, images, and voice messages work.
491
+
492
+ ### 10.5 Web UI
493
+
494
+ A full dashboard at `http://localhost:3100` (configurable via `WEB_PORT`). Password-protected via `WEB_PASSWORD`. Features:
495
+
496
+ - Live chat with streaming
497
+ - Dashboard: provider status, heartbeat, resource usage
498
+ - Memory manager: browse and edit long-term memories
499
+ - File browser: navigate and edit files the bot has access to
500
+ - Cron job editor
501
+ - Settings and env editor
502
+ - Plugin and MCP server manager
503
+ - Web terminal (in-browser shell)
504
+ - Security audit report
505
+
506
+ ### 10.6 TUI
507
+
508
+ `alvin-bot tui` starts a terminal chat with ANSI colors and streaming. Useful on remote servers without a browser.
509
+
510
+ ### 10.7 Slack
511
+
512
+ Uses `@slack/bolt`. Supports DMs and channel mentions.
513
+
514
+ ---
515
+
516
+ ## 11. Plugins and MCP servers
517
+
518
+ ### 11.1 Plugins
519
+
520
+ JavaScript modules under `plugins/` that register new Telegram commands and extend the bot's capabilities. Each plugin exports:
521
+
522
+ - `name`
523
+ - `version`
524
+ - `commands` (array of `{ name, description, handler }`)
525
+ - `init(ctx)` — called at startup, gets access to the bot instance
526
+ - `unload()` — called at shutdown
527
+
528
+ Built-in plugins:
529
+
530
+ | Plugin | Purpose |
531
+ |---|---|
532
+ | `calendar` | Google Calendar integration |
533
+ | `email` | Gmail / IMAP ingest |
534
+ | `finance` | Bank account queries |
535
+ | `notes` | Apple Notes / Obsidian sync |
536
+ | `smarthome` | Home Assistant control |
537
+ | `weather` | Weather forecasts |
538
+
539
+ User plugins go in `~/.alvin-bot/plugins/` and hot-reload on save.
540
+
541
+ ### 11.2 MCP servers
542
+
543
+ Model Context Protocol servers extend the bot with new tools. Configure them in `~/.mcp.json` or `~/.alvin-bot/mcp.json`:
544
+
545
+ ```json
546
+ {
547
+ "mcpServers": {
548
+ "filesystem": {
549
+ "command": "npx",
550
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
551
+ }
552
+ }
553
+ }
554
+ ```
555
+
556
+ The bot auto-discovers MCP tools at startup and makes them available to the AI provider (Claude SDK supports them natively; other providers get the tools as descriptions in the system prompt).
557
+
558
+ ---
559
+
560
+ ## 12. Skills
561
+
562
+ Skills are Markdown files under `skills/` that teach the AI how to do specific tasks. Each skill is a `SKILL.md` file with:
563
+
564
+ - Title and description
565
+ - When to use it (triggers)
566
+ - Step-by-step procedure
567
+ - Code templates and examples
568
+
569
+ Skills auto-activate based on message context. Built-in skills include:
570
+
571
+ - **apple-notes** — create and search Apple Notes
572
+ - **browser-automation** — control Chrome via Playwright
573
+ - **code-project** — scaffold, refactor, and test code projects
574
+ - **data-analysis** — pandas/jupyter-style data exploration
575
+ - **document-creation** — generate PDFs and Word docs
576
+ - **email-summary** — triage and summarize email
577
+ - **github** — issues, PRs, releases
578
+ - **summarize** — generic summarization with citations
579
+ - **system-administration** — shell tasks on Linux/macOS
580
+ - **weather** — forecast queries
581
+ - **web-research** — structured web research with sources
582
+
583
+ User skills go in `~/.alvin-bot/skills/` and are hot-reloaded.
584
+
585
+ ---
586
+
587
+ ## 13. Security
588
+
589
+ Security is taken seriously because this bot has real system access.
590
+
591
+ ### 13.1 Authentication
592
+
593
+ Only users listed in `ALLOWED_USERS` can chat with the Telegram bot. The `authMiddleware` silently drops everyone else.
594
+
595
+ For WhatsApp groups, each group must be explicitly whitelisted and the owner approves each message before the bot responds.
596
+
597
+ For the web UI, access is gated by `WEB_PASSWORD`.
598
+
599
+ ### 13.2 Execution sandboxing
600
+
601
+ The `EXEC_SECURITY` env var controls how shell commands are gated:
602
+
603
+ - `full` — no restrictions (use only on trusted machines)
604
+ - `allowlist` (default) — only whitelisted binaries from `~/.alvin-bot/exec-allowlist.txt` can run
605
+ - `deny` — shell execution completely disabled
606
+
607
+ ### 13.3 Security audit
608
+
609
+ `alvin-bot audit` runs a series of health checks:
610
+
611
+ - Are secrets in `.env` readable only by you?
612
+ - Is the data directory mode `0700`?
613
+ - Are there any API keys leaked into version-controlled files?
614
+ - Is the bot exposed on a public port?
615
+ - Are the allowed users list and exec allowlist intact?
616
+
617
+ Each check reports `PASS` / `WARN` / `FAIL` with a fix suggestion.
618
+
619
+ ### 13.4 Checkpoints during long runs
620
+
621
+ Alvin's Claude SDK provider injects a `[CHECKPOINT]` reminder into the prompt every 5 turns once certain thresholds are crossed (10+ messages or 15+ tool calls in a session). The reminder tells Claude to write a checkpoint to its memory file before processing the next request. This protects against context compaction losing progress on long multi-hour sessions.
622
+
623
+ ### 13.5 Git safety
624
+
625
+ The bot's own code is protected against accidental destruction:
626
+
627
+ - Never changes user passwords in projects
628
+ - Never touches auth functions without explicit instruction
629
+ - Never runs `git push --force` on main/master
630
+ - Never bypasses pre-commit hooks (`--no-verify`)
631
+ - Never amends commits that might be lost
632
+
633
+ ---
634
+
635
+ ## 14. Running in production
636
+
637
+ ### 14.1 macOS: `launchd` (recommended)
638
+
639
+ On macOS with the Claude Code SDK, you **must** run the bot as a `launchd` user agent, not via pm2. Claude Code stores the OAuth token for the Max subscription in the macOS Keychain under the service `"Claude Code-credentials"`, and only processes running inside the user's GUI login session can access that Keychain without a manual unlock.
640
+
641
+ Pm2 starts its daemon in a detached launchd context without Keychain access. Result: the bot sees `Not logged in` on every Claude SDK call. Launchd user agents, on the other hand, run inside the GUI session and inherit the unlocked Keychain automatically.
642
+
643
+ ```bash
644
+ alvin-bot launchd install
645
+ ```
646
+
647
+ This writes `~/Library/LaunchAgents/com.alvinbot.app.plist` with:
648
+
649
+ - `RunAtLoad true` — starts on login
650
+ - `KeepAlive Crashed=true` — auto-restart on crash
651
+ - `ThrottleInterval 10` — prevents restart loops
652
+ - `PATH` covering Apple Silicon and Intel Homebrew plus `~/.local/bin`
653
+ - stdout → `~/.alvin-bot/logs/alvin-bot.out.log`
654
+ - stderr → `~/.alvin-bot/logs/alvin-bot.err.log`
655
+
656
+ Management:
657
+
658
+ ```bash
659
+ alvin-bot launchd status # plist state, PID, last log lines
660
+ alvin-bot launchd uninstall # unload and remove the plist
661
+
662
+ # Restart:
663
+ launchctl kickstart -k gui/$UID/com.alvinbot.app
664
+ ```
665
+
666
+ If you'd previously set up the bot via pm2, uninstall the pm2 process first (`pm2 delete alvin-bot; pm2 kill`) before running `launchd install`.
667
+
668
+ ### 14.2 Linux / Windows: pm2
669
+
670
+ The `alvin-bot start` command wraps pm2:
671
+
672
+ ```bash
673
+ alvin-bot start # start in background, auto-restart on crash
674
+ alvin-bot start -f # start in foreground (for debugging)
675
+ alvin-bot stop # stop the bot
676
+ pm2 logs alvin-bot # live logs
677
+ ```
678
+
679
+ For systemd users, you can write a user unit pointing at `node dist/index.js` — see the example in `docs/systemd.md` (if included in your release).
680
+
681
+ ### 14.3 Auto-update
682
+
683
+ `/autoupdate on` tells the bot to check for updates daily. When an update is found, it runs `git pull`, `npm install`, `npm run build`, and restarts itself. The auto-update flag lives at `~/.alvin-bot/auto-update.flag`.
684
+
685
+ ### 14.4 Environment variables reference
686
+
687
+ Common env vars (all optional unless marked):
688
+
689
+ | Variable | Default | Purpose |
690
+ |---|---|---|
691
+ | `BOT_TOKEN` | — | **Required**. Telegram bot token. |
692
+ | `ALLOWED_USERS` | — | **Required**. Comma-separated Telegram user IDs. |
693
+ | `PRIMARY_PROVIDER` | `claude-sdk` | Registry key of the default provider. |
694
+ | `FALLBACK_PROVIDERS` | — | Comma-separated fallback chain. |
695
+ | `GOOGLE_API_KEY` | — | Required if using `google` as provider. |
696
+ | `GROQ_API_KEY` | — | For custom Groq provider. |
697
+ | `OPENAI_API_KEY` | — | For custom OpenAI provider. |
698
+ | `OPENROUTER_API_KEY` | — | For custom OpenRouter provider. |
699
+ | `NVIDIA_API_KEY` | — | For custom NVIDIA NIM provider. |
700
+ | `ELEVENLABS_API_KEY` | — | Voice synthesis (falls back to Edge TTS). |
701
+ | `WEB_PORT` | `3100` | Web UI port. |
702
+ | `WEB_PASSWORD` | — | Web UI access password. |
703
+ | `SESSION_MODE` | `per-user` | Session isolation mode. |
704
+ | `ALVIN_STUCK_TIMEOUT_MINUTES` | `10` | Adaptive stuck-detector window. |
705
+ | `MAX_SUBAGENTS` | `0` (auto) | Max parallel sub-agents. |
706
+ | `SUBAGENT_TIMEOUT` | `300000` | Per-agent timeout in ms. |
707
+ | `COMPACTION_THRESHOLD` | `80000` | Tokens before context compaction triggers. |
708
+ | `EXEC_SECURITY` | `allowlist` | Shell execution sandbox mode. |
709
+ | `ALVIN_DATA_DIR` | `~/.alvin-bot` | Data directory path. |
710
+
711
+ ---
712
+
713
+ ## 15. Troubleshooting
714
+
715
+ ### 15.1 Bot starts but doesn't respond
716
+
717
+ 1. `alvin-bot doctor` — runs 10+ health checks
718
+ 2. Check the log: `pm2 logs alvin-bot` (or `~/.alvin-bot/logs/alvin-bot.err.log` under launchd)
719
+ 3. Verify your provider: `/status` in chat shows the active provider and its health
720
+
721
+ ### 15.2 Claude SDK says "Not logged in"
722
+
723
+ You're hitting the Keychain problem documented in §14.1. Three paths:
724
+
725
+ - **Preferred**: switch to `alvin-bot launchd install` on macOS
726
+ - **Temporary**: `security unlock-keychain -p '<your-login-password>' ~/Library/Keychains/login.keychain-db`, then restart the bot in the same terminal session
727
+ - **Fallback**: run interactively: `claude` (opens the interactive CLI), then `/login`, then re-run the bot
728
+
729
+ ### 15.3 Sub-agent limit reached
730
+
731
+ Either increase the cap:
732
+
733
+ ```
734
+ /subagents max 8
735
+ ```
736
+
737
+ Or cancel a stuck agent:
738
+
739
+ ```
740
+ /subagents list
741
+ /subagents cancel <name>
742
+ ```
743
+
744
+ ### 15.4 Cron job not firing
745
+
746
+ - Is it `enabled: true`? `/cron` or `cat ~/.alvin-bot/cron-jobs.json`
747
+ - Is the schedule valid? Try `/cron run <id>` to trigger manually
748
+ - Check the bot log for `[cron]` lines
749
+
750
+ ### 15.5 Web UI shows "Not authorized"
751
+
752
+ `WEB_PASSWORD` isn't set or doesn't match. Add `WEB_PASSWORD=<pick-a-password>` to `.env` and restart.
753
+
754
+ ### 15.6 Sub-agent results shown twice
755
+
756
+ Happens if you upgrade from a version before 4.6.0 and a mid-stream shutdown race fired. Fixed in 4.6.0 — see CHANGELOG §9.2.
757
+
758
+ ### 15.7 Upgrading from 4.5.x
759
+
760
+ - Run `npm install -g alvin-bot@latest`
761
+ - Run `alvin-bot update` from chat (pulls, rebuilds, restarts)
762
+ - On macOS, consider switching from pm2 to `alvin-bot launchd install` for the Keychain fix
763
+
764
+ ---
765
+
766
+ ## 16. Upgrading
767
+
768
+ ### 16.1 Data directory compatibility
769
+
770
+ Alvin Bot follows semver for the **data directory format**. Minor version bumps never break `~/.alvin-bot/`; major bumps might introduce migration scripts that run automatically on first startup.
771
+
772
+ ### 16.2 From 4.5.x to 4.6.0
773
+
774
+ - Sub-agents: new fields in `sub-agents.json` (`visibility`). Old files auto-upgrade — the loader treats missing fields as defaults.
775
+ - Cron jobs: no schema change.
776
+ - Memory: no schema change.
777
+ - `.env`: no new required variables. `MAX_SUBAGENTS` and `SUBAGENT_TIMEOUT` are optional.
778
+
779
+ ### 16.3 From git
780
+
781
+ ```bash
782
+ cd ~/path/to/alvin-bot
783
+ git pull
784
+ npm install
785
+ npm run build
786
+
787
+ # If running under launchd:
788
+ launchctl kickstart -k gui/$UID/com.alvinbot.app
789
+
790
+ # If running under pm2:
791
+ alvin-bot start
792
+
793
+ # If running in foreground:
794
+ # Stop with Ctrl+C, then alvin-bot start -f
795
+ ```
796
+
797
+ ### 16.4 From npm
798
+
799
+ ```bash
800
+ npm install -g alvin-bot@latest
801
+ alvin-bot stop
802
+ alvin-bot start
803
+ ```
804
+
805
+ ### 16.5 Rollback
806
+
807
+ ```bash
808
+ npm install -g alvin-bot@4.5.1
809
+ ```
810
+
811
+ Old data in `~/.alvin-bot/` continues to work — nothing is deleted on upgrade.
812
+
813
+ ---
814
+
815
+ ## Feedback and bug reports
816
+
817
+ - GitHub Issues: <https://github.com/alvbln/Alvin-Bot/issues>
818
+ - Pull requests welcome
819
+ - Maintained by @alvbln