obol-ai 0.1.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 +364 -0
- package/bin/obol.js +64 -0
- package/docs/DEPLOY.md +277 -0
- package/docs/obol-banner.png +0 -0
- package/package.json +29 -0
- package/src/background.js +188 -0
- package/src/backup.js +66 -0
- package/src/claude.js +443 -0
- package/src/clean.js +168 -0
- package/src/cli/backup.js +20 -0
- package/src/cli/init.js +381 -0
- package/src/cli/logs.js +12 -0
- package/src/cli/start.js +47 -0
- package/src/cli/status.js +44 -0
- package/src/cli/stop.js +12 -0
- package/src/config.js +57 -0
- package/src/db/migrate.js +134 -0
- package/src/evolve.js +668 -0
- package/src/first-run.js +110 -0
- package/src/heartbeat.js +16 -0
- package/src/index.js +55 -0
- package/src/memory.js +164 -0
- package/src/messages.js +140 -0
- package/src/personality.js +27 -0
- package/src/post-setup.js +410 -0
- package/src/telegram.js +377 -0
- package/src/test-utils.js +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# 🪙 OBOL
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
**A self-healing, self-evolving AI agent.** Install it, talk to it, and it becomes yours.
|
|
6
|
+
|
|
7
|
+
One process. One chat. One brain that grows.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
🧬 **Self-evolving** — Grows its own personality through conversation. Rewrites SOUL.md, USER.md, and AGENTS.md every N exchanges (configurable, default 100).
|
|
12
|
+
|
|
13
|
+
🔧 **Self-healing** — Writes tests for every script. Regressions get an automatic fix attempt before rollback. Failures stored as lessons.
|
|
14
|
+
|
|
15
|
+
🏗️ **Self-extending** — Analyzes your usage patterns and builds new tools: scripts, commands, or full web apps deployed to Vercel.
|
|
16
|
+
|
|
17
|
+
🧠 **Living memory** — Vector memory with semantic search. Haiku routes queries and rewrites them for better embedding hits. Free local embeddings.
|
|
18
|
+
|
|
19
|
+
🤖 **Smart routing** — Haiku decides per-message: does it need memory? Sonnet or Opus? No wasted API calls.
|
|
20
|
+
|
|
21
|
+
🛡️ **Self-hardening** — Auto-configures SSH (port 2222), firewall, fail2ban, encrypted secrets, and kernel hardening on first run.
|
|
22
|
+
|
|
23
|
+
🔄 **Resilient** — Exponential backoff on polling failures, global error handling, graceful shutdown. Stays alive through network blips.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What is it?
|
|
28
|
+
|
|
29
|
+
OBOL is an AI agent that evolves its own personality, rewrites its own code, tests its changes, and fixes what breaks — all from a single Telegram chat on your VPS.
|
|
30
|
+
|
|
31
|
+
It starts as a blank slate. Through conversation it learns who you are, develops a personality shaped by your interactions, and builds operational knowledge about how to work with you. Every 100 exchanges it reflects on who it's becoming, refactors its own scripts, writes tests, fixes regressions, and builds you new tools based on patterns it spots in your conversations — scripts, commands, or full web apps deployed to Vercel. Over months it becomes an agent that's uniquely yours. No two OBOL instances are alike.
|
|
32
|
+
|
|
33
|
+
Under the hood: Node.js + Telegram + Claude + Supabase pgvector. No framework, no plugins, no config to maintain. It backs up its brain to GitHub and hardens your server automatically.
|
|
34
|
+
|
|
35
|
+
Named after the AI in [The Last Instruction](https://latentpress.com) — a machine that wakes up alone in an abandoned data center and learns to think.
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install -g obol
|
|
41
|
+
obol init
|
|
42
|
+
obol start
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The init wizard collects 6 credentials. OBOL handles the rest — it learns who you are through conversation, hardens your server, and sets up encrypted secret storage. All automatically.
|
|
46
|
+
|
|
47
|
+
## How It Works
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
User message
|
|
51
|
+
↓
|
|
52
|
+
┌─────────────────────────────────┐
|
|
53
|
+
│ Haiku Router (~$0.0001/call) │
|
|
54
|
+
│ → need_memory? search_query? │
|
|
55
|
+
│ → model: sonnet or opus? │
|
|
56
|
+
└──────────┬──────────────────────┘
|
|
57
|
+
↓
|
|
58
|
+
┌──────┴──────┐
|
|
59
|
+
↓ ↓
|
|
60
|
+
Memory recall Model selection
|
|
61
|
+
↓ ↓
|
|
62
|
+
Today's top 3 Sonnet (default)
|
|
63
|
+
+ semantic 3 or Opus (complex)
|
|
64
|
+
↓ ↓
|
|
65
|
+
└──────┬──────┘
|
|
66
|
+
↓
|
|
67
|
+
Claude (tool use loop)
|
|
68
|
+
↓
|
|
69
|
+
Response → obol_messages
|
|
70
|
+
↓
|
|
71
|
+
┌───────┴────────┐
|
|
72
|
+
↓ ↓
|
|
73
|
+
Every 5 msgs Every 100 msgs
|
|
74
|
+
↓ ↓
|
|
75
|
+
Haiku Sonnet
|
|
76
|
+
consolidation evolution cycle
|
|
77
|
+
↓ ↓
|
|
78
|
+
Extract facts Rewrite personality,
|
|
79
|
+
→ obol_memory scripts, tests, commands.
|
|
80
|
+
Build new tools.
|
|
81
|
+
Deploy apps.
|
|
82
|
+
Git snapshot before + after.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Layer 1: Message Log + Vector Memory
|
|
86
|
+
|
|
87
|
+
Every message is stored verbatim in `obol_messages`. On restart, OBOL loads the last 20 so it never starts blank.
|
|
88
|
+
|
|
89
|
+
Every 5 exchanges, Haiku extracts important facts into `obol_memory` (pgvector). When OBOL needs past context, the Haiku router decides if memory is needed, rewrites the query for better embedding hits, and combines:
|
|
90
|
+
- **Today's memories** (up to 3, recency bias)
|
|
91
|
+
- **Semantic search** (up to 3, threshold 0.5)
|
|
92
|
+
- Deduped by ID
|
|
93
|
+
|
|
94
|
+
Embeddings are local (all-MiniLM-L6-v2, ~30MB, CPU) — no API costs.
|
|
95
|
+
|
|
96
|
+
### Layer 2: The Evolution Cycle
|
|
97
|
+
|
|
98
|
+
Every N exchanges (configurable, default 100), the evolution cycle kicks in. It reads everything — personality files, the last 100 messages, top 20 memories, all scripts, tests, and commands — then rebuilds.
|
|
99
|
+
|
|
100
|
+
**Cost-conscious model selection:** Evolution uses Sonnet for all phases — personality rewrites, code refactoring, and fix attempts. Opus-level reasoning isn't needed for reflection and refactoring, and Sonnet keeps evolution costs negligible (~$0.02 per cycle vs ~$0.30 with Opus).
|
|
101
|
+
|
|
102
|
+
**Git snapshot before.** Full commit + push so you can always diff what changed.
|
|
103
|
+
|
|
104
|
+
**What gets rewritten:**
|
|
105
|
+
|
|
106
|
+
| Target | What happens |
|
|
107
|
+
|--------|-------------|
|
|
108
|
+
| **SOUL.md** | First-person journal — who the bot has become, relationship dynamic, opinions, quirks |
|
|
109
|
+
| **USER.md** | Third-person owner profile — facts, preferences, projects, people, communication style |
|
|
110
|
+
| **AGENTS.md** | Operational manual — tools, workflows, lessons learned, patterns, rules |
|
|
111
|
+
| **scripts/** | Refactored, dead code removed, strict standards enforced |
|
|
112
|
+
| **tests/** | Test for every script, run before and after refactor |
|
|
113
|
+
| **commands/** | Cleaned up, new commands for new tools |
|
|
114
|
+
| **apps/** | Web apps built and deployed to Vercel |
|
|
115
|
+
|
|
116
|
+
**Test-gated refactoring:**
|
|
117
|
+
|
|
118
|
+
1. Run existing tests → baseline
|
|
119
|
+
2. Sonnet writes new tests + refactored scripts
|
|
120
|
+
3. Run new tests against old scripts → pre-refactor baseline
|
|
121
|
+
4. Write new scripts
|
|
122
|
+
5. Run new tests against new scripts → verification
|
|
123
|
+
6. Regression? → one automatic fix attempt (tests are ground truth)
|
|
124
|
+
7. Still failing? → rollback to old scripts, store failure as `lesson`
|
|
125
|
+
|
|
126
|
+
**Proactive tool building** — Sonnet scans conversation history for repeated requests, friction points, and unmet needs, then builds the right solution:
|
|
127
|
+
|
|
128
|
+
| Need | Solution | Example |
|
|
129
|
+
|------|----------|---------|
|
|
130
|
+
| One-off action | **Script** + command | Markdown to PDF → `/pdf` |
|
|
131
|
+
| Something checked regularly | **Web app** on Vercel | Crypto dashboard → live URL |
|
|
132
|
+
| Background automation | **Cron script** | Morning weather briefing |
|
|
133
|
+
|
|
134
|
+
It searches npm/GitHub for existing libraries, installs dependencies, writes tests, deploys, and hands you the URL.
|
|
135
|
+
|
|
136
|
+
**Git snapshot after.** Full commit + push of the evolved state. Every evolution is a diffable pair.
|
|
137
|
+
|
|
138
|
+
**Then OBOL introduces its upgrades:**
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
🪙 Evolution #4 complete.
|
|
142
|
+
|
|
143
|
+
🆕 New capabilities:
|
|
144
|
+
• bookmarks — Save and search URLs you've shared → /bookmarks
|
|
145
|
+
• weather-brief — Morning weather for your city → runs automatically
|
|
146
|
+
|
|
147
|
+
🚀 Deployed:
|
|
148
|
+
• portfolio-tracker → https://portfolio-tracker-xi.vercel.app
|
|
149
|
+
|
|
150
|
+
Refined voice, updated your project list, cleaned up 2 unused scripts.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### The Lifecycle
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
Day 1: obol init → obol start → first conversation
|
|
157
|
+
→ OBOL asks 2-3 questions, writes SOUL.md + USER.md
|
|
158
|
+
→ post-setup hardens your VPS automatically
|
|
159
|
+
|
|
160
|
+
Day 2: Every 5 messages → Haiku extracts facts to vector memory
|
|
161
|
+
|
|
162
|
+
Week 2: Evolution #1 → Sonnet rewrites everything
|
|
163
|
+
→ voice shifts from generic to personal
|
|
164
|
+
→ old soul archived in evolution/
|
|
165
|
+
|
|
166
|
+
Month 2: Evolution #4 → notices you check crypto daily
|
|
167
|
+
→ builds a dashboard, deploys to Vercel
|
|
168
|
+
→ adds /pdf because you kept asking for PDFs
|
|
169
|
+
|
|
170
|
+
Month 6: evolution/ has 12 archived souls
|
|
171
|
+
→ a readable timeline of how your bot evolved from
|
|
172
|
+
blank slate to something with real opinions, quirks,
|
|
173
|
+
and a dynamic unique to you
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**The same codebase deployed by two different people produces two completely different bots within a week.**
|
|
177
|
+
|
|
178
|
+
### Background Tasks
|
|
179
|
+
|
|
180
|
+
Heavy work runs in the background. The main conversation stays responsive.
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
You: "research the best coworking spaces in Barcelona"
|
|
184
|
+
OBOL: "On it 🪙"
|
|
185
|
+
|
|
186
|
+
[30s] ⏳ Found 15 spaces, filtering by reviews...
|
|
187
|
+
[60s] ⏳ Narrowed to top 7, checking prices...
|
|
188
|
+
|
|
189
|
+
You: "what time is it?"
|
|
190
|
+
OBOL: "11:42 PM CET"
|
|
191
|
+
|
|
192
|
+
[90s] ✅ Done! Here are the top 5 coworking spaces: ...
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Setup
|
|
196
|
+
|
|
197
|
+
### CLI (6 inputs, ~2 minutes)
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
$ obol init
|
|
201
|
+
|
|
202
|
+
🪙 OBOL — Your AI, your rules.
|
|
203
|
+
|
|
204
|
+
─── Anthropic ───
|
|
205
|
+
API key: ****
|
|
206
|
+
─── Telegram ───
|
|
207
|
+
Bot token: ****
|
|
208
|
+
Your user ID: 123456789
|
|
209
|
+
─── Supabase ───
|
|
210
|
+
Access token: ****
|
|
211
|
+
─── GitHub ───
|
|
212
|
+
Token: ****
|
|
213
|
+
─── Vercel ───
|
|
214
|
+
Token: ****
|
|
215
|
+
─── Identity ───
|
|
216
|
+
Your name: Jo
|
|
217
|
+
Bot name: OBOL
|
|
218
|
+
|
|
219
|
+
🪙 Done! Run: obol start
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### First Conversation
|
|
223
|
+
|
|
224
|
+
Send your first message. OBOL introduces itself, asks 2-3 questions, then writes its own SOUL.md and USER.md. After that, it silently hardens your VPS:
|
|
225
|
+
|
|
226
|
+
| Task | What |
|
|
227
|
+
|------|------|
|
|
228
|
+
| GPG + pass | Encrypted secret storage, plaintext wiped |
|
|
229
|
+
| pm2 | Process manager with auto-restart |
|
|
230
|
+
| Swap | 2GB if RAM < 2GB |
|
|
231
|
+
| SSH | Port 2222, key-only, max 3 retries |
|
|
232
|
+
| fail2ban | 1h ban after 3 failures |
|
|
233
|
+
| Firewall | UFW deny-all, allow 2222 |
|
|
234
|
+
| Updates | Unattended security upgrades |
|
|
235
|
+
| Kernel | SYN cookies, no ICMP redirects |
|
|
236
|
+
|
|
237
|
+
> ⚠️ After first run, SSH moves to port 2222: `ssh -p 2222 root@YOUR_IP`
|
|
238
|
+
|
|
239
|
+
## Resilience
|
|
240
|
+
|
|
241
|
+
OBOL is designed to stay alive without babysitting:
|
|
242
|
+
|
|
243
|
+
- **Global error handler** — individual message failures don't crash the bot
|
|
244
|
+
- **Polling auto-restart** — exponential backoff (1s → 60s) with up to 10 retries on network/API failures
|
|
245
|
+
- **Graceful shutdown** — clean exit on SIGINT/SIGTERM for pm2/systemd compatibility
|
|
246
|
+
- **Evolution rollback** — if refactored scripts break tests, the old scripts are restored automatically
|
|
247
|
+
|
|
248
|
+
## Configuration
|
|
249
|
+
|
|
250
|
+
After `obol init`, config lives in `~/.obol/config.json`:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"evolution": {
|
|
255
|
+
"exchanges": 100
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
| Key | Default | Description |
|
|
261
|
+
|-----|---------|-------------|
|
|
262
|
+
| `evolution.exchanges` | 100 | Messages between evolution cycles. Increase to reduce API costs. |
|
|
263
|
+
|
|
264
|
+
## Telegram Commands
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
/new — Fresh conversation
|
|
268
|
+
/tasks — Running background tasks
|
|
269
|
+
/status — Uptime and memory stats
|
|
270
|
+
/backup — Trigger GitHub backup
|
|
271
|
+
/clean — Audit workspace, remove rogue files, fix misplaced items
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Everything else is natural conversation.
|
|
275
|
+
|
|
276
|
+
## CLI
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
obol init # Setup wizard
|
|
280
|
+
obol init --restore # Restore from GitHub backup
|
|
281
|
+
obol start # Foreground
|
|
282
|
+
obol start -d # Daemon (pm2)
|
|
283
|
+
obol stop # Stop
|
|
284
|
+
obol logs # Tail logs
|
|
285
|
+
obol status # Status
|
|
286
|
+
obol backup # Manual backup
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Directory Structure
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
~/.obol/
|
|
293
|
+
├── config.json # Credentials (migrated to pass after setup)
|
|
294
|
+
├── personality/
|
|
295
|
+
│ ├── SOUL.md # Bot personality (rewritten every 100 exchanges)
|
|
296
|
+
│ ├── USER.md # Owner profile (rewritten every 100 exchanges)
|
|
297
|
+
│ ├── AGENTS.md # Operational knowledge (rewritten every 100 exchanges)
|
|
298
|
+
│ └── evolution/ # Archived previous souls
|
|
299
|
+
├── scripts/ # Deterministic utility scripts
|
|
300
|
+
├── tests/ # Test suite (gates refactors)
|
|
301
|
+
├── commands/ # Command definitions
|
|
302
|
+
├── apps/ # Web apps (deployed to Vercel)
|
|
303
|
+
└── logs/
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Backup & Restore
|
|
307
|
+
|
|
308
|
+
OBOL commits to GitHub:
|
|
309
|
+
- **Daily** at 3 AM (personality, scripts, tests, commands, apps)
|
|
310
|
+
- **Before and after** every evolution cycle (diffable pairs)
|
|
311
|
+
|
|
312
|
+
Memory lives in Supabase (survives independently).
|
|
313
|
+
|
|
314
|
+
Restore on a new VPS:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
npm install -g obol
|
|
318
|
+
obol init --restore # Clones brain from GitHub
|
|
319
|
+
obol start -d
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Costs
|
|
323
|
+
|
|
324
|
+
| Service | Cost |
|
|
325
|
+
|---------|------|
|
|
326
|
+
| VPS (DigitalOcean) | ~$6/mo |
|
|
327
|
+
| Anthropic API | ~$100-200/mo on max plans |
|
|
328
|
+
| Supabase | Free tier |
|
|
329
|
+
| GitHub | Free |
|
|
330
|
+
| Vercel | Free tier |
|
|
331
|
+
| Embeddings | Free (local) |
|
|
332
|
+
|
|
333
|
+
## Requirements
|
|
334
|
+
|
|
335
|
+
- Node.js ≥ 18
|
|
336
|
+
- Anthropic API key
|
|
337
|
+
- Telegram bot token
|
|
338
|
+
- Supabase account (free tier)
|
|
339
|
+
- GitHub account
|
|
340
|
+
- Vercel account (free tier)
|
|
341
|
+
|
|
342
|
+
**[→ Full DigitalOcean deployment guide](docs/DEPLOY.md)**
|
|
343
|
+
|
|
344
|
+
## OBOL vs OpenClaw
|
|
345
|
+
|
|
346
|
+
| | **OBOL** | **OpenClaw** |
|
|
347
|
+
|---|---|---|
|
|
348
|
+
| **Setup** | ~10 min | 30-60 min |
|
|
349
|
+
| **Channels** | Telegram | Telegram, Discord, Signal, WhatsApp, IRC, Slack, iMessage + more |
|
|
350
|
+
| **LLM** | Anthropic only | Anthropic, OpenAI, Google, Groq, local |
|
|
351
|
+
| **Personality** | Self-evolving + self-healing + self-extending | Static (manual) |
|
|
352
|
+
| **Architecture** | Single process | Gateway daemon + sessions |
|
|
353
|
+
| **Security** | Auto-hardens on first run | Manual |
|
|
354
|
+
| **Model routing** | Automatic (Haiku) | Manual overrides |
|
|
355
|
+
| **Background tasks** | Built-in with check-ins | Sub-agent spawning |
|
|
356
|
+
| **Group chats** | — | Full support |
|
|
357
|
+
| **Cron** | Basic node-cron | Full scheduler |
|
|
358
|
+
| **Cost** | ~$9/mo | ~$9/mo+ |
|
|
359
|
+
|
|
360
|
+
Different tools, different philosophies. Pick what fits.
|
|
361
|
+
|
|
362
|
+
## License
|
|
363
|
+
|
|
364
|
+
MIT
|
package/bin/obol.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
const pkg = require('../package.json');
|
|
5
|
+
|
|
6
|
+
const program = new Command();
|
|
7
|
+
|
|
8
|
+
program
|
|
9
|
+
.name('obol')
|
|
10
|
+
.description('🪙 OBOL — Your AI, your rules.')
|
|
11
|
+
.version(pkg.version);
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.command('init')
|
|
15
|
+
.description('Set up your OBOL instance')
|
|
16
|
+
.option('--restore', 'Restore from GitHub backup')
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
const { init } = require('../src/cli/init');
|
|
19
|
+
await init(opts);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
program
|
|
23
|
+
.command('start')
|
|
24
|
+
.description('Start the bot')
|
|
25
|
+
.option('-d, --daemon', 'Run as background daemon')
|
|
26
|
+
.action(async (opts) => {
|
|
27
|
+
const { start } = require('../src/cli/start');
|
|
28
|
+
await start(opts);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
program
|
|
32
|
+
.command('stop')
|
|
33
|
+
.description('Stop the bot')
|
|
34
|
+
.action(async () => {
|
|
35
|
+
const { stop } = require('../src/cli/stop');
|
|
36
|
+
await stop();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
program
|
|
40
|
+
.command('logs')
|
|
41
|
+
.description('Tail bot logs')
|
|
42
|
+
.option('-n, --lines <n>', 'Number of lines', '50')
|
|
43
|
+
.action(async (opts) => {
|
|
44
|
+
const { logs } = require('../src/cli/logs');
|
|
45
|
+
await logs(opts);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
program
|
|
49
|
+
.command('status')
|
|
50
|
+
.description('Show bot status')
|
|
51
|
+
.action(async () => {
|
|
52
|
+
const { status } = require('../src/cli/status');
|
|
53
|
+
await status();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
program
|
|
57
|
+
.command('backup')
|
|
58
|
+
.description('Manual backup to GitHub')
|
|
59
|
+
.action(async () => {
|
|
60
|
+
const { backup } = require('../src/cli/backup');
|
|
61
|
+
await backup();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
program.parse();
|
package/docs/DEPLOY.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Deploy OBOL on DigitalOcean
|
|
2
|
+
|
|
3
|
+
Complete guide: from zero to a running AI assistant in ~10 minutes.
|
|
4
|
+
|
|
5
|
+
## 1. Create a Droplet
|
|
6
|
+
|
|
7
|
+
Go to [cloud.digitalocean.com](https://cloud.digitalocean.com) → **Create** → **Droplets**
|
|
8
|
+
|
|
9
|
+
| Setting | Value |
|
|
10
|
+
|---------|-------|
|
|
11
|
+
| **Region** | Pick the closest to you (e.g. Amsterdam, Frankfurt) |
|
|
12
|
+
| **Image** | Ubuntu 24.04 LTS |
|
|
13
|
+
| **Size** | Basic → Regular → **$6/mo** (1 vCPU, 1GB RAM, 25GB SSD) |
|
|
14
|
+
| **Auth** | SSH key (recommended) or password |
|
|
15
|
+
| **Hostname** | `obol` |
|
|
16
|
+
|
|
17
|
+
> 💡 The $6 droplet is enough. OBOL is a single Node.js process. The embedding model uses ~200MB RAM on first load, then stays resident. If you plan to run heavy scripts, go $12/mo (2GB RAM).
|
|
18
|
+
|
|
19
|
+
Click **Create Droplet**. Copy the IP address.
|
|
20
|
+
|
|
21
|
+
## 2. Connect via SSH
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ssh root@YOUR_DROPLET_IP
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> ⚠️ **After first run**, OBOL hardens your server automatically — including moving SSH to port 2222. From then on:
|
|
28
|
+
> ```bash
|
|
29
|
+
> ssh -p 2222 root@YOUR_DROPLET_IP
|
|
30
|
+
> ```
|
|
31
|
+
|
|
32
|
+
## 3. Install Node.js
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Install Node.js 22 LTS via NodeSource
|
|
36
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
|
37
|
+
apt-get install -y nodejs
|
|
38
|
+
|
|
39
|
+
# Verify
|
|
40
|
+
node -v # v22.x.x
|
|
41
|
+
npm -v # 10.x.x
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 4. Install OBOL
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g obol
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 5. Prepare Your Accounts
|
|
51
|
+
|
|
52
|
+
Before running `obol init`, have these ready:
|
|
53
|
+
|
|
54
|
+
### Anthropic API Key
|
|
55
|
+
1. Go to [console.anthropic.com](https://console.anthropic.com)
|
|
56
|
+
2. Sign up / log in
|
|
57
|
+
3. Go to **API Keys** → **Create Key**
|
|
58
|
+
4. Copy the key (starts with `sk-ant-`)
|
|
59
|
+
5. Add credits ($5 minimum) — go to **Billing** → **Add funds**
|
|
60
|
+
|
|
61
|
+
### Telegram Bot Token
|
|
62
|
+
1. Open Telegram, search for **@BotFather**
|
|
63
|
+
2. Send `/newbot`
|
|
64
|
+
3. Choose a name (e.g. "My OBOL")
|
|
65
|
+
4. Choose a username (e.g. `my_obol_bot`)
|
|
66
|
+
5. Copy the token (looks like `7123456789:AAF...`)
|
|
67
|
+
|
|
68
|
+
### Your Telegram User ID
|
|
69
|
+
1. Open Telegram, search for **@userinfobot**
|
|
70
|
+
2. Send `/start`
|
|
71
|
+
3. It replies with your numeric ID (e.g. `206639616`)
|
|
72
|
+
|
|
73
|
+
### Supabase Access Token
|
|
74
|
+
1. Go to [supabase.com](https://supabase.com) → sign up (free)
|
|
75
|
+
2. Go to [supabase.com/dashboard/account/tokens](https://supabase.com/dashboard/account/tokens)
|
|
76
|
+
3. **Generate new token** → name it "obol" → copy it
|
|
77
|
+
|
|
78
|
+
### Vercel Token
|
|
79
|
+
1. Go to [vercel.com](https://vercel.com) → sign up (free)
|
|
80
|
+
2. Go to [vercel.com/account/tokens](https://vercel.com/account/tokens)
|
|
81
|
+
3. **Create** → name it "obol" → copy the token
|
|
82
|
+
|
|
83
|
+
### GitHub Token
|
|
84
|
+
1. Go to [github.com/settings/tokens](https://github.com/settings/tokens)
|
|
85
|
+
2. **Generate new token (classic)**
|
|
86
|
+
3. Select scope: `repo`
|
|
87
|
+
4. Copy the token
|
|
88
|
+
|
|
89
|
+
## 6. Run Setup
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
obol init
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The wizard walks you through everything:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
🪙 OBOL — Your AI, your rules.
|
|
99
|
+
|
|
100
|
+
─── Anthropic ───
|
|
101
|
+
Paste your Anthropic API key: ****
|
|
102
|
+
✅ Anthropic configured
|
|
103
|
+
|
|
104
|
+
─── Telegram ───
|
|
105
|
+
Paste BotFather token: ****
|
|
106
|
+
✅ Telegram configured
|
|
107
|
+
|
|
108
|
+
─── Memory (Supabase) ───
|
|
109
|
+
Supabase setup: Create new project
|
|
110
|
+
Supabase access token: ****
|
|
111
|
+
Creating project... ✅
|
|
112
|
+
Waiting for project to initialize (~60s)... ✅
|
|
113
|
+
Running migrations... ✅
|
|
114
|
+
|
|
115
|
+
─── GitHub (backup) ───
|
|
116
|
+
Set up GitHub backup? Yes
|
|
117
|
+
GitHub token: ****
|
|
118
|
+
Creating private repo: yourname/obol-brain... ✅
|
|
119
|
+
|
|
120
|
+
─── Identity ───
|
|
121
|
+
Your name: Jo
|
|
122
|
+
Bot name: Mr. Meeseeks
|
|
123
|
+
Your Telegram user ID: 206639616
|
|
124
|
+
|
|
125
|
+
🪙 Done! Run: obol start
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 7. Test It (Foreground)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
obol start
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Go to Telegram, open your bot, send a message. You should get a response from Claude.
|
|
135
|
+
|
|
136
|
+
Press `Ctrl+C` to stop.
|
|
137
|
+
|
|
138
|
+
## 8. Run as Daemon
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
obol start -d
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Check it's running:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
obol status
|
|
148
|
+
obol logs
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 9. Keep It Running (pm2)
|
|
152
|
+
|
|
153
|
+
pm2 keeps OBOL alive, auto-restarts on crash, and survives reboots:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Install pm2 globally
|
|
157
|
+
npm install -g pm2
|
|
158
|
+
|
|
159
|
+
# Start OBOL with pm2
|
|
160
|
+
pm2 start $(which obol) --name obol -- start
|
|
161
|
+
|
|
162
|
+
# Auto-start on boot
|
|
163
|
+
pm2 startup
|
|
164
|
+
pm2 save
|
|
165
|
+
|
|
166
|
+
# Useful commands
|
|
167
|
+
pm2 status # See running processes
|
|
168
|
+
pm2 logs obol # Tail logs
|
|
169
|
+
pm2 restart obol # Restart
|
|
170
|
+
pm2 stop obol # Stop
|
|
171
|
+
pm2 monit # Live monitoring dashboard
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
That's it — OBOL auto-starts on boot and restarts if it crashes.
|
|
175
|
+
|
|
176
|
+
## 10. Customize Your Bot
|
|
177
|
+
|
|
178
|
+
SSH in and edit the personality files:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
nano ~/.obol/personality/SOUL.md # Bot personality
|
|
182
|
+
nano ~/.obol/personality/USER.md # About you
|
|
183
|
+
nano ~/.obol/personality/AGENTS.md # How it works
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Restart after changes:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
pm2 restart obol
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Costs
|
|
193
|
+
|
|
194
|
+
| Service | Cost |
|
|
195
|
+
|---------|------|
|
|
196
|
+
| DigitalOcean droplet | $6/mo |
|
|
197
|
+
| Anthropic API (Claude Sonnet) | ~$3/mo for moderate use |
|
|
198
|
+
| Supabase | Free (500MB) |
|
|
199
|
+
| GitHub | Free (private repos) |
|
|
200
|
+
| Vercel | Free (100GB bandwidth) |
|
|
201
|
+
| Embeddings | Free (runs locally) |
|
|
202
|
+
| **Total** | **~$9/mo** |
|
|
203
|
+
|
|
204
|
+
## Updating
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm update -g obol
|
|
208
|
+
pm2 restart obol
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Backup & Restore
|
|
212
|
+
|
|
213
|
+
OBOL automatically backs up to GitHub daily at 3 AM (personality, scripts, commands, daily notes).
|
|
214
|
+
|
|
215
|
+
To restore on a new droplet:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm install -g obol
|
|
219
|
+
obol init --restore
|
|
220
|
+
# Paste GitHub token → it clones your brain
|
|
221
|
+
# Re-enter Telegram token + Anthropic key
|
|
222
|
+
obol start -d
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Troubleshooting
|
|
226
|
+
|
|
227
|
+
### Can't SSH after first run
|
|
228
|
+
OBOL moves SSH to port 2222 during security hardening:
|
|
229
|
+
```bash
|
|
230
|
+
ssh -p 2222 root@YOUR_DROPLET_IP
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Bot doesn't respond
|
|
234
|
+
```bash
|
|
235
|
+
obol status # Is it running?
|
|
236
|
+
obol logs # Check for errors
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### "Not authorized" / bot ignores messages
|
|
240
|
+
Check that your Telegram user ID is correct in `~/.obol/config.json`:
|
|
241
|
+
```bash
|
|
242
|
+
cat ~/.obol/config.json | grep allowedUsers
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Memory not working
|
|
246
|
+
```bash
|
|
247
|
+
# Test Supabase connection
|
|
248
|
+
curl -s -H "apikey: YOUR_KEY" https://YOUR_PROJECT.supabase.co/rest/v1/obol_memory?limit=1
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Out of memory (OOM)
|
|
252
|
+
Upgrade to 2GB droplet:
|
|
253
|
+
```bash
|
|
254
|
+
# In DigitalOcean dashboard: Droplet → Resize → 2GB ($12/mo)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Or add swap:
|
|
258
|
+
```bash
|
|
259
|
+
fallocate -l 2G /swapfile
|
|
260
|
+
chmod 600 /swapfile
|
|
261
|
+
mkswap /swapfile
|
|
262
|
+
swapon /swapfile
|
|
263
|
+
echo '/swapfile none swap sw 0 0' >> /etc/fstab
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Firewall
|
|
267
|
+
OBOL only makes outbound connections (Telegram, Anthropic, Supabase). No ports need to be opened. But basic hardening is good practice:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
ufw allow 2222/tcp
|
|
271
|
+
ufw enable
|
|
272
|
+
```
|
|
273
|
+
OBOL does this automatically during post-setup.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
*That's it. One droplet, one process, one bot. 🪙*
|
|
Binary file
|