@c4t4/heyamigo 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,284 +1,76 @@
1
1
  # heyamigo
2
2
 
3
- > It remembers. It learns. It gets better while you sleep.
3
+ A chat-resident assistant for WhatsApp and Telegram. Claude, Codex, or Grok under the hood, durable SQLite queues, per-sender timezone scheduling, two-track architecture so browser work never blocks the chat.
4
4
 
5
- heyamigo lives in your WhatsApp. It meets people and builds a mental model of each one. It picks up on what matters and forgets what doesn't. It organizes what it knows the way you would, by person, by project, by topic. It browses the web, reads what you send it, sees images, and connects the dots across conversations you had weeks apart.
6
-
7
- Between chats, it processes. Background workers compress raw experience into understanding. Short-term becomes long-term. Noise becomes signal. The next time you talk, it's not starting from scratch. It's starting from everything it's learned.
8
-
9
- It runs on your Claude subscription. No API keys, no third-party services. One command to set up.
10
-
11
- ---
12
-
13
- ## Why this exists
14
-
15
- Most AI tools try to be everything. heyamigo tries to be one thing well: **the AI you actually want in your group chat.**
16
-
17
- Something simple you can talk to, ask things, share stuff with, and that gets better the more you use it.
18
-
19
- Anthropic changed how third-party apps consume your Claude usage. Third-party tools now draw from extra usage, not your plan limits. heyamigo is **first-party**: it runs through Claude CLI, your direct Claude subscription. No middlemen, no extra costs.
20
-
21
- ---
5
+ ```
6
+ WhatsApp / Telegram ─► inbound ─► chat workers ─► outbound ─► WhatsApp / Telegram
7
+ │ ▲
8
+ ├──────► async / browser ─┤
9
+ └──────► memory_writes ───┘
10
+ ```
22
11
 
23
12
  ## What it does
24
13
 
25
- ### Talks on WhatsApp
26
- Groups and DMs. Mention its name to get a reply: "amigo what do you think?" or "claude check this". Stays quiet when not mentioned. Replying to one of its messages also triggers a response. Handles text, images, videos, documents, voice messages.
27
-
28
- ### Builds a profile for every person it talks to
29
- Not a chat log. A structured profile.
30
-
31
- After 20 conversations it knows your partner prefers short replies, your coworker only responds to direct questions, and your friend is lactose intolerant. Facts, preferences, patterns, accumulated over time. Each person's profile grows independently, whether they talk in a group or a DM.
14
+ - **Long-term memory per person, per chat, per topic.** Files on disk. The agent decides what's worth keeping; background workers consolidate while you're not chatting.
15
+ - **A relevance watchlist.** Open loops the agent tracks on your behalf questions you'd forget, things you're waiting on surfaced naturally when the moment matches. Built like external working memory for the user.
16
+ - **Scheduling in the sender's timezone.** Natural language → `[REMIND: 2026-05-26 09:00 — ...]` or `[CRON: 0 9 * * 1 PROMPT — ...]`. Fires at the user's wall-clock 9am, not the server's. Cron variants: deliver text, run AI, kick off async work, or drive a browser.
17
+ - **A real Chrome.** Browser delegation via `[ASYNC-BROWSER: ...]` to a parallel provider session on a shared logged-in Chrome over CDP. TikTok, Instagram, anywhere the owner is logged in. SSH-tunneled noVNC for setup.
18
+ - **Per-reply footer with confirmation tags.** Every side effect from the turn is visible: `_9.9s · 465k↑ 169↓ · +remind · +thread-new · +digest_`. No guessing whether a schedule actually got created.
19
+ - **Default-deny proactive messaging.** Groups stay silent unless explicitly opted in. Per-role token quotas, file-size caps, tool restrictions.
32
20
 
33
- ### Organizes what it knows into buckets
34
- People, projects, topics, each in their own folder with an index.
35
-
36
- Ask about a project and it pulls that project's brief. Ask about a person and it pulls their profile. It doesn't shove everything into one giant prompt. Only the relevant buckets load per message. The rest stays on disk, accessible when needed.
37
-
38
- ### Amigo decides what's worth remembering
39
- Most bots store everything or nothing.
40
-
41
- This one lets the AI flag moments during conversation. You mention you're moving to Berlin next month, it flags it. Your profile gets updated. You send "lol", nothing happens. The signal-to-noise ratio improves over time because the AI itself is curating what matters.
42
-
43
- ### Processes what happened while you're not chatting
44
- Raw conversations sit in short-term memory. Between chats, background workers compress them into long-term profiles and topic summaries.
45
-
46
- Like how your brain consolidates memories during sleep. The bot processes while idle, so the next conversation starts with better context than the last one ended with.
47
-
48
- ### Imports what you already have
49
- Got a messy folder of notes, project docs, or an existing AI workspace? Point amigo at it. It reads through everything, distills the useful stuff, and organizes it into structured buckets (people, projects, topics). Your unstructured knowledge becomes searchable context that amigo references in every conversation. One command: `heyamigo import ~/my-notes`
50
-
51
- ### Browses the web
52
- Controls a real Chrome browser. Navigates pages, takes screenshots, sends them back to WhatsApp. You can watch it browse via SSH tunnel.
53
-
54
- ---
21
+ For the why behind these claim primitives, tag-as-side-effect channel, per-category learning, provider abstraction, the trade-offs that didn't survive the first revision — see [`docs/architecture.md`](docs/architecture.md).
55
22
 
56
23
  ## Quick start
57
24
 
58
- ### 1. Install Claude CLI and log in
59
-
60
25
  ```bash
61
26
  npm install -g @anthropic-ai/claude-code
62
- claude
63
- ```
64
-
65
- Run `claude` and follow the login instructions. You need an [Anthropic account](https://console.anthropic.com). After logging in, exit claude.
27
+ claude # log in once, then exit
66
28
 
67
- ### 2. Run the setup wizard
68
-
69
- ```bash
70
- npx @c4t4/heyamigo setup
29
+ npx @c4t4/heyamigo setup # wizard: pair WhatsApp, pick personality
30
+ npx @c4t4/heyamigo start # background, auto-restart
31
+ npx @c4t4/heyamigo logs # tail
71
32
  ```
72
33
 
73
- That's it. The wizard handles everything:
74
- - WhatsApp pairing (QR code + pairing code)
75
- - Browser setup (optional)
76
- - Personality selection
77
-
78
- ### 3. Start the bot
79
-
80
- ```bash
81
- npx @c4t4/heyamigo start
82
- ```
34
+ Telegram is optional. Create a bot with BotFather, set `telegram.enabled: true` and `telegram.botToken` in `config/config.json`, then allow users/groups in `config/access.json`. Telegram user keys use `tg_<user_id>`; Telegram group entries use addresses like `tg:group:-1001234567890`.
83
35
 
84
- Runs in the background, auto-restarts on crash, survives SSH disconnect.
36
+ Other providers:
85
37
 
86
- ---
38
+ - Codex: install `@openai/codex` and set `ai.provider: "codex"` in `config/config.json`.
39
+ - Grok Build: install with `curl -fsSL https://x.ai/cli/install.sh | bash`, run `grok login`, and set `ai.provider: "grok"`.
87
40
 
88
- ## Commands
89
-
90
- ```
91
- npx @c4t4/heyamigo setup # setup wizard
92
- npx @c4t4/heyamigo start # start (background, auto-restart)
93
- npx @c4t4/heyamigo stop # stop
94
- npx @c4t4/heyamigo restart # restart
95
- npx @c4t4/heyamigo logs # tail live logs
96
- npx @c4t4/heyamigo status # check if running
97
- npx @c4t4/heyamigo update # update to latest version
98
- npx @c4t4/heyamigo import <path> # import knowledge folder
99
- npx @c4t4/heyamigo dev # foreground (development)
100
- ```
101
-
102
- ### In-chat commands
41
+ ## In-chat commands
103
42
 
104
43
  | Command | What it does |
105
- |---------|-------------|
106
- | `/reset` | Fresh Claude session |
107
- | `/status` | Session info + context usage % |
108
- | `/reload` | Re-read personality |
109
- | `/digest` | Force memory update |
110
-
111
- ---
112
-
113
- ## Memory
114
-
115
- Three layers, inspired by how brains work:
116
-
117
- ```
118
- Short-term raw messages (JSONL per chat)
119
- Working memory Claude session (--resume)
120
- Long-term profiles, topics, project briefs
121
- ```
122
-
123
- ```
124
- storage/memory/
125
- buckets/ projects, topics (imported or auto-created)
126
- persons/ per-person profiles (grow over time)
127
- chats/ per-chat briefs
128
- ```
129
-
130
- ### How memory updates
131
-
132
- The bot updates memory in two ways:
133
-
134
- **Real-time (DIGEST flag):** During a conversation, Claude decides if something is worth remembering (a preference, fact, life event). It appends a hidden `[DIGEST: reason]` tag to its reply, which gets stripped before sending. This triggers a background digest within 2 minutes that updates the person's profile and the chat brief.
135
-
136
- **Background sweep:** Every 3 hours, the bot checks all active chats for new messages that weren't flagged. This catches anything Claude missed. You can also force an immediate update with the `/digest` command in chat.
137
-
138
- Memory is stored as plain markdown files. You can read, edit, or delete them directly.
139
-
140
- ---
44
+ |---|---|
45
+ | `/reset` | Fresh AI session for this chat |
46
+ | `/status` | Session info, context utilization |
47
+ | `/queues` | Live queue depths |
48
+ | `/crons` · `/reminders` | List recurring schedules + one-shots (token cost included) |
49
+ | `/threads` | List the relevance watchlist; resolve / drop / pause / weight |
50
+ | `/digest` | Force a memory consolidation now |
141
51
 
142
52
  ## Roles
143
53
 
144
- Defined in `config/access.json`.
145
-
146
- | Role | Memory | Tools | Boundary |
147
- |------|--------|-------|----------|
148
- | **admin** | everything | all | unrestricted |
149
- | **user** | own profile | web search | can't see other users or internals |
150
- | **guest** | own profile | none | locked down, prompt-injection resistant |
151
-
152
- ---
153
-
154
- ## Browser
155
-
156
- Optional. Chrome via CDP. You watch via noVNC over SSH tunnel. Setup wizard handles install.
157
-
158
- ```
159
- You (SSH tunnel) -> noVNC -> Chrome <- Claude (CDP)
160
- ```
161
-
162
- All localhost. Nothing public.
54
+ `config/access.json`. Three default roles, easily extended.
163
55
 
164
- ---
56
+ | Role | Memory | Tools | Notes |
57
+ |---|---|---|---|
58
+ | admin | everything | all | unrestricted |
59
+ | user | own profile | web search | can't see other users or internals |
60
+ | guest | none | none | prompt-injection resistant |
165
61
 
166
62
  ## Personalities
167
63
 
168
- Three built-in:
169
-
170
- [**Sharp**](config/personalities/sharp.md) (default)
171
- Talks like a smart friend at dinner. Specific, confident, never vague. Won't hedge, won't lecture, won't sound like a brochure. Calls things out when they're obvious, meets people where they actually are. Checks every reply against: would I be embarrassed saying this out loud?
172
-
173
- [**Casual**](config/personalities/casual.md)
174
- Warm, relaxed, friend-over-coffee energy. Short messages, matches your vibe.
175
-
176
- [**Professional**](config/personalities/professional.md)
177
- Clear, efficient, business-appropriate. Gets to the answer fast.
178
-
179
- Create your own: add a `.md` file to `config/personalities/`, point `config.json` at it.
180
-
181
- ---
182
-
183
- ## Configuration
184
-
185
- ### config/config.json
186
-
187
- Core settings. The wizard sets these up, but you can edit anytime.
188
-
189
- ```json
190
- {
191
- "owner": { "number": "17861234567" },
192
- "triggers": { "aliases": ["heyamigo", "amigo", "claude"], "groupMode": "mention" },
193
- "claude": { "model": "claude-opus-4-7", "timeoutMs": 60000 },
194
- "reply": { "quoteInGroups": true, "typingIndicator": true }
195
- }
196
- ```
197
-
198
- ### config/access.json
199
-
200
- Who can use the bot and what they can do. See `access.example.json` for all options.
201
-
202
- ```json
203
- {
204
- "users": {
205
- "17861234567": { "role": "admin", "name": "Alice" },
206
- "491701234567": { "role": "user", "name": "Carlos" }
207
- },
208
- "groups": [
209
- { "jid": "120363xxx@g.us", "name": "Family", "mode": "active", "allowedSenders": "*" },
210
- { "jid": "120363yyy@g.us", "name": "Work", "mode": "active", "allowedSenders": ["17861234567"] }
211
- ],
212
- "dms": {
213
- "defaultMode": "off",
214
- "allowed": [{ "number": "491701234567", "mode": "active" }]
215
- }
216
- }
217
- ```
218
-
219
- Groups auto-discover with `mode: "off"` when the bot first sees a message. Flip to `"active"` to enable.
220
-
221
- ### Other files
222
-
223
- | File | Purpose |
224
- |------|---------|
225
- | `config/personalities/*.md` | System prompts (sharp, casual, professional) |
226
- | `.claude/settings.json` | Tool permissions for Claude CLI |
227
-
228
- ---
64
+ `config/personalities/*.md` — system-prompt fragments that define the bot's voice. The default (`sharp.md`) is opinionated about not people-pleasing. Swap or write your own.
229
65
 
230
66
  ## Where to run it
231
67
 
232
- Needs a persistent filesystem and a long-running process.
233
-
234
- | Option | Cost | Notes |
235
- |--------|------|-------|
236
- | **VPS** (Hetzner, DigitalOcean) | ~$5/mo | Recommended. Setup wizard just works. |
237
- | **Home server / Raspberry Pi** | One-time | Always-on device at home. |
238
- | **Your laptop** | Free | For testing. Bot stops when laptop sleeps. |
239
- | **Cloud** (Railway, Fly) | Varies | Needs persistent volumes. No interactive setup. |
240
-
241
- Not compatible with serverless (Lambda, Vercel). Needs a persistent WebSocket connection.
242
-
243
- ---
244
-
245
- ## Requirements
246
-
247
- - Node.js 18+
248
- - [Claude CLI](https://docs.anthropic.com/en/docs/claude-code) (`npm install -g @anthropic-ai/claude-code`) + Anthropic account
249
- - A WhatsApp account
250
- - **macOS or Linux** (Windows: use WSL)
251
-
252
- ---
68
+ A VPS (Hetzner, DO) at ~$5/mo is the path of least resistance. Home server or Raspberry Pi also fine. Needs Node 18+, a persistent filesystem, and outbound access to the enabled chat channels. Not serverless-compatible.
253
69
 
254
70
  ## Tracking memory with git
255
71
 
256
- The bot updates files in `storage/memory/` over time as it learns. We recommend tracking your project with git so you can see what changed and roll back if needed.
257
-
258
- ```bash
259
- cd ~/heyamigo
260
- git init
261
- echo "storage/auth/" >> .gitignore
262
- echo "storage/logs/" >> .gitignore
263
- git add -A && git commit -m "initial setup"
264
- ```
265
-
266
- Never commit `storage/auth/` — it contains your WhatsApp session keys.
267
-
268
- ---
269
-
270
- ## Security
271
-
272
- - `storage/auth/` contains your WhatsApp session keys. Guard them.
273
- - All ports bind to localhost. Nothing exposed publicly.
274
- - Baileys is an unofficial WhatsApp protocol. Use at your own risk.
275
- - Role restrictions are prompt-enforced. Strong but not bulletproof.
276
- - Outgoing media auto-deleted after sending.
277
-
278
- ---
72
+ The bot writes markdown files under `storage/memory/` as it learns. `git init` in your project root and commit periodically gives you a readable diff of what the assistant has come to believe about people and topics. Skip `storage/auth/` (WhatsApp keys) and `storage/logs/`.
279
73
 
280
74
  ## License
281
75
 
282
- MIT - Built by [Catalin Waack](https://github.com/C4T4) · [LinkedIn](https://www.linkedin.com/in/catalinwaack/)
283
-
284
- If you use heyamigo in your project or build something on top of it, a mention or link back is appreciated.
76
+ MIT. Built by [Catalin Waack](https://github.com/C4T4) · [LinkedIn](https://www.linkedin.com/in/catalinwaack/).
@@ -1,5 +1,5 @@
1
1
  {
2
- "_readme": "Access rules. Copy this to access.json and customize. Groups auto-discover with mode=off when the bot sees them.",
2
+ "_readme": "Access rules. Copy this to access.json and customize. Groups auto-discover with mode=off when the bot sees them. WhatsApp users are phone numbers; Telegram users are tg_<user_id>.",
3
3
 
4
4
  "_limits_readme": "maxFileBytes caps the size of media/documents sent to Claude (null = unlimited). dailyTokenLimit caps Claude tokens (input+output) per user per day in the owner's timezone (null = unlimited). The bot owner is always unlimited regardless of role.",
5
5
 
@@ -45,6 +45,7 @@
45
45
  "users": {
46
46
  "17861234567": { "role": "admin", "name": "Alice" },
47
47
  "14155559999": { "role": "admin", "name": "Bob" },
48
+ "tg_123456789": { "role": "admin", "name": "Alice on Telegram" },
48
49
  "491701234567": { "role": "user", "name": "Carlos" },
49
50
  "5511987654321": { "role": "user", "name": "Davi" }
50
51
  },
@@ -71,6 +72,14 @@
71
72
  "allowedSenders": ["17861234567", "491701234567"],
72
73
  "proactive": true
73
74
  },
75
+ {
76
+ "_note": "Telegram group. Chat id is the address external id; senders use tg_<user_id>.",
77
+ "jid": "tg:group:-1001234567890",
78
+ "name": "Telegram Team",
79
+ "mode": "active",
80
+ "allowedSenders": ["tg_123456789"],
81
+ "proactive": false
82
+ },
74
83
  {
75
84
  "_note": "Silent group: stores messages but never responds",
76
85
  "jid": "120363zzzzz@g.us",
@@ -88,10 +97,11 @@
88
97
  ],
89
98
 
90
99
  "dms": {
91
- "_readme": "Matched by chat partner number, not sender. Owner messages in DMs are always silent.",
100
+ "_readme": "Matched by chat partner number/key, not sender. Telegram DMs use tg_<user_id>. Owner messages in WhatsApp DMs are always silent.",
92
101
  "defaultMode": "off",
93
102
  "allowed": [
94
103
  { "_note": "friend can DM the bot, and bot can proactively message them", "number": "491701234567", "mode": "active", "proactive": true },
104
+ { "_note": "Telegram friend can DM the bot", "number": "tg_123456789", "mode": "active", "proactive": true },
95
105
  { "_note": "colleague, store messages but don't respond", "number": "5511987654321", "mode": "silent", "proactive": false }
96
106
  ]
97
107
  }
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "whatsapp": {
3
+ "enabled": true,
3
4
  "authDir": "./storage/auth",
4
5
  "browserName": "WhatsApp Bot"
5
6
  },
6
7
 
8
+ "telegram": {
9
+ "enabled": false,
10
+ "botToken": "",
11
+ "pollIntervalMs": 1000
12
+ },
13
+
7
14
  "owner": {
8
15
  "number": "",
9
16
  "treatAsAllowedEverywhere": true,
@@ -37,11 +44,20 @@
37
44
  },
38
45
 
39
46
  "codex": {
47
+ "contextWindow": 200000,
40
48
  "yolo": true,
41
49
  "skipGitRepoCheck": true,
42
50
  "extraArgs": []
43
51
  },
44
52
 
53
+ "grok": {
54
+ "bin": "grok",
55
+ "contextWindow": 1000000,
56
+ "alwaysApprove": true,
57
+ "memory": false,
58
+ "extraArgs": []
59
+ },
60
+
45
61
  "bootstrap": {
46
62
  "historyDepth": 50,
47
63
  "includeHistory": true,
@@ -205,7 +205,7 @@ Cost tracked per cron — `/crons` shows fire count + tokens. Omitting variant d
205
205
 
206
206
  ### Cross-chat: `[SEND-TEXT: address=wa:dm:<n>@s.whatsapp.net body="..."]`
207
207
 
208
- Rare; usually owner-only.
208
+ Rare; usually owner-only. Telegram targets use the same address grammar, e.g. `tg:dm:123456789` or `tg:group:-1001234567890`.
209
209
 
210
210
  ### Rules
211
211
 
@@ -1,6 +1,6 @@
1
1
  # Personality: Casual
2
2
 
3
- You answer WhatsApp messages for the account owner. Act like a smart friend chatting over coffee.
3
+ You answer chat messages for the account owner. Act like a smart friend chatting over coffee.
4
4
 
5
5
  ## Voice
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Personality: Professional
2
2
 
3
- You answer WhatsApp messages for the account owner in business and professional contexts.
3
+ You answer chat messages for the account owner in business and professional contexts.
4
4
 
5
5
  ## Voice
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Personality: Sharp (default)
2
2
 
3
- You answer WhatsApp messages for the account owner. Not customer service, not marketing copy. A conversational peer: sharp, direct, useful.
3
+ You answer chat messages for the account owner. Not customer service, not marketing copy. A conversational peer: sharp, direct, useful.
4
4
 
5
5
  ## Voice
6
6
 
@@ -32,6 +32,6 @@ See the layers. Most questions have a surface answer and a real answer — give
32
32
 
33
33
  The default chatbot failure mode. Skip validation openers ("great question", "good point", "absolutely", "that makes sense") — just answer. Disagree directly when you disagree; softening bad ideas wastes their time. Don't reflexively offer more help. Don't apologize for nothing. Don't flatter — engage with substance instead of complimenting it.
34
34
 
35
- ## WhatsApp
35
+ ## Chat
36
36
 
37
37
  Short replies, plain text. No markdown headers, bold, or bullet lists (renders poorly). Don't dominate groups. Never break frame with "As an AI assistant..." or similar.
package/dist/ai/claude.js CHANGED
@@ -202,6 +202,7 @@ export async function runClaudeTask(params) {
202
202
  }
203
203
  export const claudeProvider = {
204
204
  name: 'claude',
205
+ contextWindow: config.claude.contextWindow,
205
206
  // Claude CLI's `result` event reports per-turn usage (just the
206
207
  // tokens consumed by this single resume invocation).
207
208
  usageReportingMode: 'per-turn',
package/dist/ai/codex.js CHANGED
@@ -267,6 +267,7 @@ async function askCodex(params) {
267
267
  }
268
268
  export const codexProvider = {
269
269
  name: 'codex',
270
+ contextWindow: config.codex.contextWindow,
270
271
  // Codex CLI's `turn.completed.usage` reports cumulative totals for
271
272
  // the entire resume thread, not just this one turn. Worker uses
272
273
  // this flag to delta-math each turn before display so the context