README.md (6213B)
1 # life-todo 2 3 A personal todo list managed by Claude via Telegram. Send messages in natural language — Claude formats, prioritises, and coalesces items, then commits the result to this repo. 4 5 --- 6 7 ## How It Works 8 9 ``` 10 You (Telegram) 11 | 12 | natural language message 13 v 14 Telegram Bot (long-polling) 15 | 16 v 17 src/bot.js — message router 18 | 19 ├── loads conversation history (data/conversations/<user-id>.json) 20 ├── reads current todo.md from disk 21 └── calls Claude API 22 | 23 v 24 src/claude.js 25 | 26 | system prompt + todo context + message history + new message 27 v 28 Anthropic API 29 | 30 | { reply: string, updatedTodo: string, commitMessage: string } 31 v 32 src/bot.js (continued) 33 | 34 ├── writes updated todo.md (src/todo.js) 35 ├── git add, commit, push (src/git.js) 36 ├── saves conversation history 37 └── sends reply to Telegram 38 ``` 39 40 --- 41 42 ## Directory Layout 43 44 ``` 45 life-todo/ 46 ├── README.md 47 ├── CLAUDE.md # Claude's standing instructions: format rules, 48 │ # priority scheme, categories, tone, etc. 49 ├── todo.md # The managed todo list (source of truth) 50 │ 51 ├── .env.example # Environment variable template 52 ├── .gitignore 53 ├── package.json 54 │ 55 ├── src/ 56 │ ├── index.js # Entry point — loads config, starts bot 57 │ ├── bot.js # Telegram bot setup, message handler, orchestration 58 │ ├── claude.js # Anthropic API client, prompt construction 59 │ ├── todo.js # Read/write todo.md 60 │ ├── git.js # git add / commit / push via child_process 61 │ └── state.js # Per-user conversation history (load/save/trim) 62 │ 63 ├── data/ 64 │ └── conversations/ # <telegram-user-id>.json — recent message history 65 │ # kept in .gitignore (private, ephemeral) 66 │ 67 └── scripts/ 68 └── setup.sh # One-time setup: git config, SSH key check, etc. 69 ``` 70 71 --- 72 73 ## Interaction Model 74 75 Each incoming Telegram message triggers the following sequence in `bot.js`: 76 77 1. **Load state** — read `data/conversations/<user-id>.json` (last N messages) 78 2. **Read todo** — read `todo.md` from disk 79 3. **Build prompt** — pass to `claude.js`: 80 - System prompt (from `CLAUDE.md` + hardcoded response format instructions) 81 - Current `todo.md` contents 82 - Recent conversation history 83 - New user message 84 4. **Call Claude API** — expect structured JSON response: 85 ```json 86 { 87 "reply": "Added 'book dentist' under Health. Anything urgent this week?", 88 "updatedTodo": "...(full updated todo.md contents)...", 89 "commitMessage": "add: book dentist (Health)" 90 } 91 ``` 92 5. **Write todo** — overwrite `todo.md` with `updatedTodo` 93 6. **Git push** — `git add todo.md && git commit -m <commitMessage> && git push` 94 7. **Save state** — append exchange to conversation history, trim to last 20 messages 95 8. **Reply** — send `reply` text back to the user via Telegram 96 97 --- 98 99 ## todo.md Format 100 101 Claude maintains `todo.md` as a structured markdown file. The exact schema is defined in `CLAUDE.md`, but roughly: 102 103 ```markdown 104 # Todo 105 106 ## Urgent 107 - [ ] Call landlord about boiler 108 109 ## This Week 110 - [ ] Book dentist appointment 111 - [ ] Review Q2 budget spreadsheet 112 113 ## Someday 114 - [ ] Learn to make sourdough 115 - [ ] Read Thinking Fast and Slow 116 117 ## Done 118 - [x] Renew car insurance _(2026-04-10)_ 119 ``` 120 121 Claude is responsible for deciding where new items belong, merging duplicates, splitting vague items into actionable ones, and occasionally asking clarifying questions about priority. 122 123 --- 124 125 ## Environment Variables 126 127 ```bash 128 # .env 129 TELEGRAM_BOT_TOKEN= # From @BotFather on Telegram 130 ANTHROPIC_API_KEY= # From console.anthropic.com 131 ALLOWED_USER_IDS= # Comma-separated Telegram user IDs (whitelist) 132 GIT_REMOTE= # e.g. git@github.com:you/life-todo.git 133 ``` 134 135 `ALLOWED_USER_IDS` locks the bot to your account(s) only — important since the bot will be publicly addressable once deployed. 136 137 --- 138 139 ## Deployment 140 141 The bot uses **long-polling** (not webhooks) so no public HTTPS endpoint is required. It can run on any machine that has: 142 143 - Node.js 20+ 144 - Git configured with SSH push access to the remote 145 - A persistent process manager (e.g. `pm2` or a `systemd` unit) 146 147 ### Quick start (local) 148 149 ```bash 150 git clone git@github.com:you/life-todo.git 151 cd life-todo 152 npm install 153 cp .env.example .env 154 # fill in .env values 155 node src/index.js 156 ``` 157 158 ### Server (VPS) 159 160 ```bash 161 npm install -g pm2 162 pm2 start src/index.js --name life-todo 163 pm2 save 164 pm2 startup # auto-restart on reboot 165 ``` 166 167 --- 168 169 ## Example Conversations 170 171 **Adding items:** 172 > You: remember to call mum, also need to sort out travel insurance before the trip, and at some point id like to get back into running 173 > 174 > Claude: Got it — added 3 items: 175 > - **Call mum** → This Week 176 > - **Travel insurance** → Urgent (when's the trip?) 177 > - **Get back into running** → Someday 178 > 179 > When is your trip? 180 181 **Reviewing priorities:** 182 > You: what's on my plate this week? 183 > 184 > Claude: You have 4 items this week: 185 > - Book dentist _(been here 2 weeks)_ 186 > - Review Q2 budget 187 > - Call mum 188 > - Travel insurance 189 > 190 > The dentist one keeps slipping — want to move it to Urgent? 191 192 **Marking done:** 193 > You: done with the budget review 194 > 195 > Claude: Moved "Review Q2 budget" to Done. 3 items left this week. 196 197 --- 198 199 ## Claude's Behaviour (`CLAUDE.md`) 200 201 `CLAUDE.md` is where you tune Claude's personality and rules for managing your list. For example: 202 203 - Priority categories and what they mean to you 204 - Whether to ask before moving items between categories 205 - How aggressively to merge duplicate or similar items 206 - Whether to suggest breaking vague items into subtasks 207 - Tone (terse vs. conversational) 208 209 Claude reads this file as part of its system prompt on every request.