samayly.com is live. Hosted plans open soon. Join the waitlist →
Phone optionreference19 min read

Option 6: Self-Hosted Chat Bot (WhatsApp or Telegram), No Cloud

Chat with your tracker from WhatsApp or Telegram, from any phone, with everything running on your Mac: no Cloud Run, no Twilio, no public webhook, no second Google service account.

⏱️ Telegram: 15 min · WhatsApp: 30 min · 💰 $0 extra (only your Claude plan) · 👥 You + allowlisted friends/groups

🆕 Running it for a whole WhatsApp group? Follow Guide 11: WhatsApp group bot on local Kubernetes. It adds the k3d deployment, a separate bot number, owner vs member paths, a verified tool-free sandbox for members (ts03-bot selftest), @bot triggers, subjects from the Color Legend tab, reply formats (cards/table/json/yaml), help/about/capabilities replies and every fix found in a real rollout. This page stays as the quick single-user overview.


Why this beats Options 2 and 4

Option 2 / 4 (cloud) Option 6 (self-hosted)
Where it runs Cloud Run + Twilio Your Mac
Public URL / inbound port Required None for Telegram; localhost-only for WhatsApp
Brain New Python code + Claude API key + service account Your existing ts03 commands (Claude Code + Sheets MCP + CLAUDE.md)
Cost Cloud + Twilio + API usage Nothing extra
Open source Partly Bot, gateway (WAHA core), container runtime (Colima)
New features Rebuild each one Every new ts03-* command becomes a bot command

💻 Your Mac (always on)

📱 Any phone

linked device
(outbound)

webhook /hook/secret

long polling
(outbound)

WhatsApp
/week

Telegram
/week

WAHA container
127.0.0.1:3000

ts03-bot
allowlist · commands · queue

ts03-* commands
Claude Code + Sheets MCP

Report server :8765

📊 Google Sheet


Choose your channel

Telegram ⭐ recommended WhatsApp (WAHA)
Official API ✅ Bot API ⚠️ Unofficial (acts as a linked device)
Account risk None Possible ban: use a spare number
Extra software None Docker runtime + WAHA container
Inbound connection None (long polling) Localhost webhook only
Groups ✅ Add the bot to a group ✅ Spare number joins the group
Best for Batch-wide use Personal / small trusted group where everyone is on WhatsApp

About WhatsApp: tools like WAHA drive WhatsApp the way WhatsApp Web does. WhatsApp's terms don't allow unofficial automation, and numbers doing it can be banned. Use a dedicated spare SIM, keep volume low, reply only to commands, and never bulk-message. If that's not acceptable, use Telegram or Meta's official WhatsApp Cloud API.


Bot commands (both channels)

Command Runs Who
/week /brief /today /tomorrow /urgent /next /month /overdue /subjects /load /plan matching ts03-* command Allowed chats
/sub GPU Programming ts03-sub ... Allowed chats
/ask which subject has most pending work ts03 ... (read-only) Allowed chats
/html week builds the HTML report, replies with the link Allowed chats
/add /done /submit /move /note <details> write commands Owner only
/help command list Allowed chats
/whoami shows chat id and sender id Anyone (setup helper)

Plain messages (not starting with /) are ignored, so the bot stays quiet in group chats.

Built-in safety (scripts/ts03-bot): - User text is shell-quoted before reaching zsh: no command injection - Allowlist by chat id and sender id; everyone else is ignored and logged - Writes only from OWNER_ID, even inside an allowed group - One Claude call at a time (queue) + per-chat cooldown - WhatsApp webhook only answers on /hook/<HOOK_SECRET>; wrong paths get 404 - Log: ~/Library/Logs/ts03-bot.log


Part A · Common setup (both channels)

Requires Guides 1-4 (and 10 for /html): ts03-brief must work on the Mac.

1Get the repo

bash
git clone https://github.com/rpaut03l/google-sheets-mcp-guide.git
cd google-sheets-mcp-guide

2Create the config file

bash
mkdir -p ~/.config
cp templates/ts03-bot.env.example ~/.config/ts03-bot.env
chmod 600 ~/.config/ts03-bot.env

You'll fill it in during Part B or C. Template: templates/ts03-bot.env.example

3Keep the Mac awake and logged in

The bot runs as a launchd user agent: it needs you logged in (screen can be locked) and the Mac not sleeping. System Settings → Battery → Options → prevent sleep on power adapter, wake for network access.


Step 4
Create bot with @BotFather

Step 5
Token into ts03-bot.env

Step 6
Run once, /whoami

Step 7
Set OWNER_ID / ALLOWED_CHATS

Step 8
Install as service

Step 9
Add to batch group (optional)

4Create the bot

Telegram → @BotFather → /newbot → name TS-03 Tracker → username e.g. my_ts03_bot. Copy the token.

Optional: /setcommands in BotFather and paste:

code
week - Due in the next 7 days
brief - Morning brief
urgent - Due within 3 days
next - Next deadline
subjects - Subjects and professors
html - HTML report link, e.g. /html week
help - All commands

5Add the token

bash
nano ~/.config/ts03-bot.env          # TG_TOKEN=123456:ABC...

6First run and find your id

bash
cp scripts/ts03-bot ~/.local/bin/ && chmod +x ~/.local/bin/ts03-bot
ts03-bot telegram

In Telegram open your bot → Start → send /whoami. It replies with your chat id and sender id. Press Ctrl+C in the terminal.

7Allow yourself (and others)

bash
nano ~/.config/ts03-bot.env
code
OWNER_ID=<your sender id>
ALLOWED_CHATS=<friend ids or group id, comma-separated>

8Install as a service

bash
scripts/install-bot.sh telegram                    # always on
scripts/install-bot.sh telegram --digest 08:00     # + morning brief at 08:00 daily

✅ com.ts03.bot.telegram running

Test: send /week to the bot.

Step 9 (optional): Batch group

  1. Add the bot to the Telegram group
  2. Send /whoami in the group → copy the chat id (negative number)
  3. Add it to ALLOWED_CHATS, set DIGEST_CHAT to it if the group should get the morning brief
  4. Restart: scripts/install-bot.sh telegram --digest 08:00

Members type /week or /week@my_ts03_bot; only you can use write commands.


Part C · WhatsApp (WAHA, self-hosted)

Step 10
Spare number + Colima

Step 11
Secrets in ts03-bot.env

Step 12
Start WAHA (localhost)

Step 13
Scan QR

Step 14
Install bot, /whoami

Step 15
Allowlist + test

10Spare number and container runtime

  • A spare WhatsApp number (second SIM / eSIM, or WhatsApp Business on another number)
  • Open-source Docker runtime: bash brew install colima docker docker-compose colima start (Docker Desktop also works.)

11Secrets

bash
echo "WAHA_KEY=$(openssl rand -hex 16)"   >> ~/.config/ts03-bot.env
echo "HOOK_SECRET=$(openssl rand -hex 16)" >> ~/.config/ts03-bot.env
grep -E "^(WAHA_KEY|HOOK_SECRET)=." ~/.config/ts03-bot.env   # both should show values (empty template lines are ignored)

12Start WAHA (bound to localhost)

bash
mkdir -p ~/waha/sessions
set -a; source ~/.config/ts03-bot.env; set +a
export WA_HOOK_HOST=host.lima.internal        # Colima. Docker Desktop: host.docker.internal
docker compose -f templates/docker-compose.waha.yml up -d
docker logs -f waha                           # Ctrl+C once it says it's running

Compose file: templates/docker-compose.waha.yml

Open http://localhost:3000 (dashboard/Swagger; use WAHA_KEY when asked) → start session default → show the QR → on the spare phone: WhatsApp → Linked devices → Link a device → scan.

WAHA's UI and environment variable names change between versions. If something doesn't match, check https://waha.devlike.pro/.

14Install the bot and find ids

bash
scripts/install-bot.sh whatsapp

From your own WhatsApp, message the spare number: /whoami → it replies with your chat id (e.g. [email protected]).

15Allowlist and test

bash
nano ~/.config/ts03-bot.env
code
[email protected]
ALLOWED_CHATS=<group id>@g.us

(Group id: add the spare number to the group, send /whoami there.)

Restart and test:

bash
scripts/install-bot.sh whatsapp --digest 08:00

Send /week, /html week, /ask which subject has most pending work.


Operations

bash
launchctl list | grep ts03.bot                     # running? (number in first column)
tail -f ~/Library/Logs/ts03-bot.log                # activity
cat ~/Library/Logs/com.ts03.bot.telegram.err       # errors (or ...whatsapp.err)
scripts/install-bot.sh telegram                    # restart after editing ts03-bot.env
scripts/install-bot.sh whatsapp --uninstall        # remove
docker compose -f templates/docker-compose.waha.yml down   # stop WAHA

Troubleshooting

Symptom Fix
Bot silent /whoami works? Then the chat isn't in ALLOWED_CHATS/OWNER_ID. Check the log
/whoami also silent (Telegram) Wrong TG_TOKEN; see .err log
/whoami silent (WhatsApp) Webhook not reaching the bot: check WA_HOOK_HOST (Colima host.lima.internal, Docker Desktop host.docker.internal), HOOK_SECRET matches, docker logs waha
"Only the tracker owner can change the sheet" Expected for non-owners; set OWNER_ID to your sender id
"One moment, still working" Per-chat cooldown (COOLDOWN_SECONDS)
Answers say "Not logged in" Log in to Claude Code once on the Mac: claude → /login
/html link doesn't open Report server from Guide 10 must be running; link works on the same Wi-Fi
WhatsApp session logged out Re-scan QR in the WAHA dashboard; sessions persist in ~/waha/sessions

Security checklist

  • [ ] ~/.config/ts03-bot.env is chmod 600 and never committed (.gitignore covers *.env)
  • [ ] WAHA published on 127.0.0.1:3000 only, with WAHA_KEY
  • [ ] macOS firewall on; webhook port 5055 not reachable from other machines (only the container needs it)
  • [ ] OWNER_ID set, ALLOWED_CHATS minimal
  • [ ] Spare number for WhatsApp; no bulk messaging
  • [ ] Sheet data sent in replies goes to the chat's members: only allow people who may see it

Fully open source, model included?

Swap ts03 for a local model: Ollama + an MCP-capable CLI client (e.g. mcphost) using the same mcp-google-sheets server, and point the READ command map in ts03-bot at it. Fine for simple lookups; local models are much weaker at multi-step tool use, so keep writes on Claude.


Files

File Purpose
scripts/ts03-bot The bot (Telegram + WhatsApp), Python standard library only
scripts/install-bot.sh launchd service + optional daily digest
templates/ts03-bot.env.example Config template
templates/docker-compose.waha.yml WAHA on localhost

⬅️ All iPhone integrations

Questions or corrections: [email protected]