Your personal AI agent — accessible from Telegram, powered by Gemini. It knows who you are, remembers what matters, learns new skills, and keeps running 24/7.
Imagine having a personal assistant that lives in your Telegram — one that knows your name, remembers your projects, runs tasks on your server, and gets smarter the more you use it. That's Gelegram.
It's not a chatbot. It's an agent. You give it a personality on first run, and from that point on it remembers everything — your preferences, your work, your history. It can read and write files, execute scripts, search the web, and even automate tasks on a schedule. All from your phone.
Here are some real things people use Gelegram for:
You: Hey, what did we talk about yesterday regarding the API migration?
Agent: Yesterday you decided to migrate from REST to GraphQL. You wanted to keep the old endpoints for 2 weeks, then deprecate. I saved that to my memory.
You: Remind me to deploy v2.1 on Friday at 3pm
Agent: Done — I've added a one-shot cron job. You'll get a Telegram notification at 3pm on Friday.
The agent remembers past conversations and can reference them later. No more "what was that thing I said last week?"
You:
/run sysinfoAgent: ✅ OS: Windows 11 Pro CPU: AMD Ryzen 9 RAM: 31.4 GB free / 64 GB Disk C: 234 GB free / 500 GB
You: Check my disk space every 6 hours and tell me if it drops below 50 GB
Agent: Added cron job
disk-watch— runs every 6h, notifies you only on failure. Use/cronto verify.
Preset /run commands execute instantly (no AI delay). Cron jobs run 24/7 even when you're not chatting.
You: I need a blog post about why self-hosting AI is the future. Casual tone, ~800 words.
Agent: (writes it, saves to
projects/blog-posts/self-hosting-ai.md, and sends the file)
You: Make the intro punchier and add a section about privacy
Agent: (edits the file in-place and sends the updated version)
The agent can create, edit, and send files directly through Telegram.
You: (sends a screenshot of a stack trace)
Agent: That's a
NullPointerExceptioninUserService.java:142. ThegetUser()call returns null when the session expires. Here's a fix…
You: Write a Python script that monitors my API endpoint and alerts me if it goes down
Agent: (writes the script, saves it to
scripts/api-monitor.py, and sets up a cron job to run it every 5 minutes)
Send photos, documents, code files — the agent processes them all.
You: Remember that my AWS account ID is 123456789012 and the staging server is at 10.0.1.50
Agent: Noted! I've saved that to my memory. I'll remember it across sessions.
You: What's my staging server IP again?
Agent: 10.0.1.50 — you told me on May 15th.
The agent maintains a curated MEMORY.md file with facts, preferences, and lessons. It genuinely remembers.
You: Every morning at 8am, send me a summary of the weather and my calendar
Agent: Added cron job
morning-briefing— runs daily at 08:00.
You:
/cronAgent: 📝 Scheduled Jobs: •
morning-briefing— at 08:00 — ✅ enabled •disk-watch— every 6h — ✅ enabled •deploy-reminder— once 2026-05-23 15:00 — ✅ enabled
All automation runs on the gateway process — it keeps working even if the AI session restarts.
| Gelegram | ChatGPT / Gemini web | Other Telegram bots | |
|---|---|---|---|
| Remembers you | ✅ Persistent memory across sessions | ❌ Resets every conversation | ❌ No memory |
| Has a personality | ✅ You define it on first run | ❌ Generic | ❌ Generic |
| Runs on your machine | ✅ Full access to your files and scripts | ❌ Cloud sandbox | ❌ Cloud-only |
| Automates tasks | ✅ Built-in cron scheduler + preset commands | ❌ Manual only | ❌ Limited |
| Learns new skills | ✅ Drop a SKILL.md and it gains abilities | ❌ Fixed capabilities | ❌ Fixed |
| Runs 24/7 | ✅ Gateway watchdog + system service | ❌ Browser tab | |
| Free | ✅ Self-hosted, MIT license | ❌ Subscription | |
| Private | ❌ Cloud-stored | ❌ Cloud-stored |
Only prerequisite: Python 3.11+ and a Telegram bot token from @BotFather. The setup script installs everything else automatically.
git clone https://github.com/krazyguy/Gelegram.git
cd Gelegram
cp .env.example .env # Edit .env — set TELEGRAM_BOT_TOKEN
docker compose up -d
docker exec -it gelegram gemini auth # One-time Google OAuthgit clone https://github.com/krazyguy/Gelegram.git
cd Gelegram
powershell -ExecutionPolicy Bypass -File setup.ps1git clone https://github.com/krazyguy/Gelegram.git
cd Gelegram
chmod +x setup.sh && ./setup.shThe setup script will:
- ✅ Install Node.js (winget / brew / apt / nvm as appropriate)
- ✅ Install uv (Python package manager)
- ✅ Install Gemini CLI via npm
- ✅ Create Python virtual environment and install dependencies
- ✅ Generate your
.envfile (prompts for bot token, password, workspace) - ✅ Optionally install as a background service (NSSM on Windows, systemd on Linux, launchd on macOS)
- ✅ Run
gemini authfor Google OAuth
That's it. Message your bot on Telegram — on the first message, the agent will introduce itself and walk you through setting up its identity (name, personality, rules). After that it's yours. 🎉
| Feature | Details |
|---|---|
| 🧠 Persistent identity | Agent has a name, personality, and memory that survive restarts |
| 💾 Long-term memory | Curated MEMORY.md — facts, preferences, lessons, project history |
| 📅 Short-term memory | Daily session logs distilled into memory/YYYY-MM-DD.md summaries |
| 🔧 Pluggable skills | Drop a SKILL.md + scripts into skills/ and the agent gains new abilities |
| 🗣️ Gemini CLI ACP bridge | JSON-RPC 2.0 over stdio — real-time streaming responses |
| 👥 Multi-chat isolation | Each Telegram chat gets its own independent agent session |
| 📎 File attachments | Send photos, docs, audio or video — Gemini can send files back |
| 🖼️ Media album support | Multiple photos in one album are delivered to the agent together |
| 🔒 Password authentication | Restrict access with an optional bot password |
| 🕵️ Private mode | Toggle transcript logging per session with /private |
| ⚡ Auto-tool approval | File edits, shell commands, web search — all auto-approved |
| 🛑 Task cancellation | /kill stops a long-running task without resetting the session |
🚀 Preset commands (/run) |
Execute predefined shell commands instantly — bypasses Gemini entirely, zero latency |
| ⏰ Cron scheduler | Automate recurring tasks — runs on the gateway, survives bot restarts, sends output to Telegram |
| 🖥️ Cross-platform service | Windows (NSSM), Linux (systemd), macOS (launchd) — all via one setup script |
| 🔄 Watchdog gateway | Exponential backoff restart if the agent process crashes |
| 🔍 Startup CLI validation | Gateway checks Gemini CLI path on start, warns early if misconfigured |
| 📊 Tool call audit log | Every tool Gemini invokes is logged to tools.log with full params |
| ⚡ Live activity panel | A single Telegram message updates in real-time showing the current tool being used |
| 🔥 Session warm-up | /memory (or auto on /start//reset) pre-loads identity & memory so first replies are instant |
- What Can It Do?
- Why Gelegram?
- Quick Start
- Features
- How It Works
- Platform Support
- Manual Installation
- Configuration
- Running the Bot
- Bot Commands
- Agentic Workspace System
- Background Service (Production)
- Docker Deployment
- Architecture Notes
- Project Structure
- Troubleshooting
Telegram User ──────────────────────► bot.py ────────────────► gemini --acp
(python-telegram-bot) (JSON-RPC 2.0) (subprocess)
◄────────────────────── ◄────────────────
- User sends a message (text, photo, document, audio, or video) via Telegram.
bot.pyreceives it via the Telegram API (async long-polling).GeminiACPClientforwards the prompt to a persistentgemini --acpsubprocess using JSON-RPC 2.0 overstdio.- Streaming response chunks are accumulated and returned to the Telegram user.
- If Gemini appends a
file:<path>tag to its response, the bot automatically attaches and sends that file.
The ACP subprocess is started once on the first message and kept alive for subsequent messages, maintaining full context across the conversation. If it crashes, it is transparently restarted.
Gelegram runs on Windows, Linux, and macOS. The core bot (bot.py + gateway.py) is pure Python and works identically across all platforms. The only platform-specific component is the background service mechanism.
| Platform | Setup Script | Service Manager | Node.js Install |
|---|---|---|---|
| Windows | setup.ps1 |
NSSM (auto-downloaded) | winget → MSI fallback |
| Linux | setup.sh |
systemd user service | nvm → apt/dnf/pacman |
| macOS | setup.sh |
launchd LaunchAgent | nvm → Homebrew |
Note (Windows): After installing via npm, the Gemini CLI binary is at
%APPDATA%\npm\gemini.cmd. The setup script detects this automatically and writes it to.env.
Note (Linux/macOS): The systemd service uses
loginctl enable-lingerso the bot keeps running after you log out of SSH.
If you prefer to set up manually instead of using the setup script:
# Install Node.js 18+ from https://nodejs.org
# Install uv from https://github.com/astral-sh/uv
# Install Gemini CLI
npm install -g @google/gemini-cli
# Authenticate (opens browser for Google OAuth — do this once)
gemini authgit clone https://github.com/krazyguy/gelegram.git
cd gelegram
# Create virtual environment
uv venv .venv
# Install dependencies
uv pip install -r requirements.txt# Windows
Copy-Item .env.example .env
# Linux / macOS
cp .env.example .env
# Edit .env and add your TELEGRAM_BOT_TOKEN at minimum# -- Required ------------------------------------------------------------------
# Your Telegram Bot Token from @BotFather
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxyz
# -- Optional ------------------------------------------------------------------
# Full path to the gemini executable (default: "gemini" -- uses PATH)
# Windows: usually at C:\Users\<you>\AppData\Roaming\npm\gemini.cmd
# Run: where gemini (Windows) or which gemini (Linux/macOS)
GEMINI_CLI_PATH=gemini
# Working directory for the gemini-cli subprocess.
# Gemini will read/write files here. The agentic workspace is scaffolded here.
# Use an absolute path for reliability.
GEMINI_WORKING_DIR=./workdir
# Maximum seconds to wait for a Gemini response (default: 120)
# After ACP_TIMEOUT, the user is notified and the bot waits up to 30 minutes.
ACP_TIMEOUT=120
# Optional bot password. Users must send this before the bot accepts messages.
# Leave empty to allow all users.
BOT_PASSWORD=# Windows
.venv\Scripts\activate
python bot.py
# Linux / macOS
source .venv/bin/activate
python bot.pypython gateway.pyThe gateway automatically restarts bot.py if it crashes, with exponential backoff. It also validates the Gemini CLI path on startup and warns early if it's misconfigured.
Expected output:
2026-05-13 12:00:00 | INFO | gateway | ============================================================
2026-05-13 12:00:00 | INFO | gateway | Gelegram Gateway - Watchdog Service
2026-05-13 12:00:00 | INFO | gateway | ============================================================
2026-05-13 12:00:00 | INFO | gateway | bot.py started (pid=12345)
| Command | Description |
|---|---|
/start |
Welcome message, then auto-loads memory so you can chat immediately |
/reset |
Restart the Gemini session, then auto-loads memory |
/new |
Alias for /reset |
/memory |
Pre-warm session — loads identity & memory files silently (shows live tool panel) |
/kill |
Cancel the active long-running request without resetting the session |
/private |
Toggle private mode — disables transcript logging for this session |
/status |
Show ACP subprocess status (PID, session ID, timeout) |
/run |
Execute a preset command from run.json — bypasses Gemini entirely |
/cron |
View and manage scheduled automation jobs from cron.json |
| (any text) | Forwards the message to Gemini and replies with the response |
- Send a file to Gelegram and it is saved to
<GEMINI_WORKING_DIR>/media/incoming/and the path is shared with Gemini. - Gemini sends a file back by appending
file:<absolute_path>to its response. The bot intercepts this tag and delivers the file as a Telegram attachment (photo or document). - Media albums (multiple photos sent together) are collected and delivered to Gemini as a single grouped prompt.
If BOT_PASSWORD is set in .env, users must send the correct password before the bot will accept any messages. Once authenticated, the chat ID is saved to trusted_users.json so users don't need to re-authenticate after a restart.
Gelegram includes a full agentic markdown memory system that scaffolds itself automatically when a new GEMINI_WORKING_DIR is detected.
On first run with a new working directory, workspace_init.py creates:
<GEMINI_WORKING_DIR>/
├── GEMINI.md <- Agent entry point & identity bootstrap instructions
├── AGENTS.md <- Behavioral rules and operational protocols
├── TODO.md <- Task tracker
├── TOOLS.md <- Environment-specific notes (SSH, devices, etc.)
├── HALLUCINATIONS.md <- Hallucination tracking policy
├── run.json <- Preset commands for /run (see below)
├── cron.json <- Scheduled automation jobs for /cron (see below)
├── memory/ <- Daily memory logs (YYYY-MM-DD.md)
├── skills/
│ ├── memory-agent/
│ │ ├── SKILL.md <- Memory distillation skill documentation
│ │ └── scripts/
│ │ └── distill.py <- Transcript -> memory summary tool
│ ├── run-commands/
│ │ └── SKILL.md <- Teaches agent to manage /run commands
│ └── cron-scheduler/
│ └── SKILL.md <- Teaches agent to manage cron jobs
├── projects/ <- Project-specific work folders
├── scripts/ <- User/agent scripts
├── transcripts/ <- Raw session transcripts (auto-logged)
├── media/incoming/ <- Files received from Telegram
├── state/ <- Persistent state (processed sessions, etc.)
└── tmp/ <- Scratch files
When SOUL.md is missing, GEMINI.md triggers Bootstrap Mode:
- Gemini detects no identity files exist.
- It asks the user to define the agent's name, personality vibe, and rules.
- It creates
SOUL.md,IDENTITY.md,USER.md, andMEMORY.mdinteractively. - Subsequent sessions load these files automatically for persistent context.
The included skills/memory-agent/scripts/distill.py converts raw session transcripts into concise memory summaries stored in memory/:
python <GEMINI_WORKING_DIR>/skills/memory-agent/scripts/distill.py --workspace <GEMINI_WORKING_DIR>Execute predefined shell commands instantly — bypasses Gemini entirely, so there's zero latency. Commands are defined in run.json:
{
"commands": {
"sysinfo": {
"cmd": "systeminfo",
"description": "Show system information",
"timeout": 15
},
"hello": "echo Hello from Gelegram!"
}
}/run— lists all available commands with descriptions/run sysinfo— runs the command and sends stdout back to Telegram/run hello world— appends extra args:echo Hello from Gelegram! world- Ask the agent "add a run command for checking disk space" and it edits
run.jsonfor you via the skill
Automate recurring tasks with a built-in cron system. Jobs are defined in cron.json and executed by a scheduler thread running inside gateway.py — it survives bot restarts and runs 24/7:
{
"jobs": {
"health-check": {
"cmd": "python scripts/health.py",
"description": "Check service health",
"schedule": "every 30m",
"timeout": 30,
"notify": "on_failure"
},
"daily-backup": {
"cmd": "python scripts/backup.py",
"schedule": "at 02:30",
"notify": "always"
}
}
}Schedule expressions (human-readable, no crontab):
| Expression | Meaning |
|---|---|
every 30s / every 5m / every 2h |
Interval-based |
at 09:00 |
Daily at a fixed time |
at 09:00 weekday=mon |
Weekly on a specific day |
once 2026-05-21 14:00 |
One-shot at exact datetime (auto-disables after firing) |
Notify modes: always · on_failure · on_output · never
/cron— lists all jobs with status and last run info/cron health-check— show detail for a specific job/cron disable health-check//cron enable health-check— toggle jobs- Ask the agent "schedule a cron job to check disk space every 6 hours" and it edits
cron.jsonfor you via the skill - Hot-reload: the scheduler watches
cron.jsonevery 60s — no restart needed
The recommended production setup uses a two-layer resilience architecture:
OS Service Manager (NSSM / systemd / launchd)
└── gateway.py (watchdog with exponential backoff)
└── bot.py (the actual Telegram bot)
The setup script handles service installation automatically. For manual control:
# Install (requires Administrator)
powershell -ExecutionPolicy Bypass -File install_service.ps1
# Uninstall
powershell -ExecutionPolicy Bypass -File uninstall_service.ps1
# Status / control
Get-Service Gelegram
Start-Service Gelegram
Stop-Service Gelegram
Restart-Service Gelegram
# Live log tail
Get-Content .\logs\gelegram_stdout.log -Tail 50 -Wait# Status
systemctl --user status gelegram
# Control
systemctl --user start gelegram
systemctl --user stop gelegram
systemctl --user restart gelegram
# Live logs
journalctl --user -u gelegram -f
# Remove service
systemctl --user disable --now gelegram
rm ~/.config/systemd/user/gelegram.service
systemctl --user daemon-reloadPLIST="$HOME/Library/LaunchAgents/com.gelegram.bot.plist"
# Status
launchctl list | grep gelegram
# Stop / Start
launchctl unload "$PLIST"
launchctl load "$PLIST"
# Live logs
tail -f gateway.log
# Remove service
launchctl unload "$PLIST" && rm "$PLIST"gateway.py wraps bot.py with:
| Feature | Details |
|---|---|
| Exponential backoff | 5s → 10s → 20s → … → max 120s between restarts |
| Stability reset | Backoff resets after 60s of stable uptime |
| Telegram cool-down | 5s delay after bot exit before restart (prevents getUpdates conflicts) |
| Orphan cleanup | Kills leftover bot.py processes from previous runs (via bot.pid + psutil) |
| Graceful shutdown | Handles SIGINT / SIGTERM / CTRL+BREAK cleanly |
| CLI path validation | Checks Gemini CLI exists on startup; warns with install hint if missing |
| Cron scheduler | Runs scheduled jobs in a daemon thread — survives bot restarts |
| Separate logging | All lifecycle events go to gateway.log |
Gelegram ships with a multi-stage Dockerfile and a docker-compose.yml for one-command deployment.
# 1. Configure
cp .env.example .env
# Edit .env — set TELEGRAM_BOT_TOKEN at minimum
# 2. Launch
docker compose up -d
# 3. Authenticate Gemini CLI (first time only — opens a URL to copy/paste)
docker exec -it gelegram gemini auth
# 4. You're live! Message your bot on Telegram.# View live logs
docker compose logs -f
# Restart after code changes
docker compose up -d --build
# Stop
docker compose down
# Shell into the container for debugging
docker exec -it gelegram bashThe Dockerfile uses a multi-stage build to keep the image lean:
| Stage | What it does |
|---|---|
| builder | Installs Node.js 20, Gemini CLI (npm), and Python deps into isolated prefixes |
| runtime | Slim Python 3.12 image with Node.js runtime, Gemini CLI, and the app |
| Volume | Mount | Purpose |
|---|---|---|
gelegram-data |
/data |
Persistent workspace (memory, skills, transcripts, cron state, run.json, cron.json) |
gelegram-gemini-config |
/root/.config |
Gemini CLI OAuth credentials (survives container rebuilds) |
All variables from .env are supported. The container sets sensible defaults:
| Variable | Default | Notes |
|---|---|---|
GEMINI_WORKING_DIR |
/data/workdir |
Points to the persistent volume |
GEMINI_CLI_PATH |
gemini |
Pre-installed in the image |
ACP_TIMEOUT |
120 |
Seconds before "still working" notification |
PYTHONUNBUFFERED |
1 |
Ensures logs stream to docker logs in real-time |
The container includes a built-in health check (pgrep -f gateway.py) that runs every 30s. Docker will mark the container as unhealthy if the gateway process dies — useful for orchestrators like Docker Swarm or Kubernetes.
The ACP server communicates via newline-delimited JSON on stdin/stdout:
// 1. Initialize
-> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientInfo":{"name":"gelegram","version":"1.0.0"},"clientCapabilities":{}}}
<- {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"authMethods":[...]}}
// 2. Create session
-> {"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":"...","mcpServers":[],"trustedFolders":["..."]}}
<- {"jsonrpc":"2.0","id":2,"result":{"sessionId":"sess-abc123"}}
// 3. Send prompt (streaming)
-> {"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"sessionId":"sess-abc123","prompt":[{"type":"text","text":"Hello!"}]}}
<- {"jsonrpc":"2.0","method":"session/update","params":{"update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Hello"}}}}
<- {"jsonrpc":"2.0","id":3,"result":{}}- An
asyncio.Lockserialises all ACP calls per chat, preventing JSON-RPC ID collisions. concurrent_updates=Trueallows multiple chats to be handled simultaneously.- Each chat ID gets its own
GeminiACPClientinstance with an isolated session.
Gelegram provides real-time visibility into what the agent is doing while it processes your message:
Live activity panel — a single Telegram message is sent immediately when you submit a request. It acts as a live status bar:
⚙️ Working …
📖 MEMORY.md ← updates to the current tool in real-time
When the agent starts streaming its reply, the panel transitions to show a text preview. When the final response is sent, the panel is silently deleted — leaving only the clean reply.
Tool call audit log — every tool invocation (file reads, shell commands, web searches) is written to tools.log with a timestamp and full parameters:
2026-05-14 22:01:34 | sessionUpdate=tool_call update={"kind":"read","title":"SOUL.md",...}
2026-05-14 22:01:35 | sessionUpdate=tool_call update={"kind":"read","title":"MEMORY.md",...}
Session warm-up — /memory (automatically triggered by /start, /reset, and /new) sends a silent primer to Gemini asking it to read all startup files. The user sees the live tool panel while this runs, then ✅ Memory loaded! — and the next real message gets an instant reply.
gemini --acp -y runs in YOLO mode. When Gemini emits a session/request_permission server-request for tool actions, the bot automatically responds with proceed_always. This allows Gemini to edit files, run shell commands, and use web search without manual confirmation.
Telegram has a 4096-character message limit. Long responses are automatically split into numbered parts ([Part 1/N], [Part 2/N], …).
gelegram/
├── bot.py <- Main bot: Telegram polling + GeminiACPClient + /run + /cron
├── gateway.py <- Watchdog: auto-restarts bot.py + hosts cron scheduler
├── scheduler.py <- Cron scheduler engine (pure stdlib, daemon thread)
├── workspace_init.py <- Scaffolds agentic workspace on first run
├── chat.py <- (utility module)
├── Dockerfile <- Multi-stage Docker image (Python + Node.js + Gemini CLI)
├── docker-compose.yml <- One-command Docker deployment
├── .dockerignore <- Docker build context exclusions
├── setup.ps1 <- One-command onboarding script (Windows)
├── setup.sh <- One-command onboarding script (Linux / macOS)
├── install_service.ps1 <- NSSM Windows service installer
├── uninstall_service.ps1 <- NSSM Windows service uninstaller
├── run_gateway.bat <- Batch launcher for the Windows service
├── requirements.txt <- Python dependencies
├── .env.example <- Configuration template (copy to .env)
├── .env <- Your secrets ⚠️ never commit this!
├── trusted_users.json <- Authenticated chat IDs (auto-managed)
├── bot.log <- Bot runtime log (created on first run)
├── gateway.log <- Gateway lifecycle log
├── tools.log <- Tool call audit log (every Gemini tool invocation)
├── bot.pid <- Current bot.py PID (auto-managed)
├── workdir/ <- Default agentic workspace (see GEMINI_WORKING_DIR)
└── logs/ <- Service stdout/stderr logs (created by service managers)
| Symptom | Fix |
|---|---|
TELEGRAM_BOT_TOKEN is not set |
Create .env and add your token from @BotFather |
Could not find Gemini CLI executable |
Set GEMINI_CLI_PATH in .env to the full path; on Windows try %APPDATA%\npm\gemini.cmd |
| Bot hangs on first message | Run gemini auth to complete Google OAuth |
Conflict: terminated by other getUpdates |
Wait 10s and try again; the gateway handles this automatically on restart |
ACP error in logs |
Check bot.log for the raw JSON-RPC error message |
Timeout after ACP_TIMEOUT seconds |
The user is notified automatically; bot waits up to 30 min. Increase ACP_TIMEOUT for complex tasks |
| Bot stops responding | Send /reset to restart and auto-reload memory |
| Session not persisting after restart | This is expected — send any message or /memory and a fresh session starts automatically |
EOFError: ACP subprocess closed stdout |
Gemini CLI crashed; the bot auto-restarts it on the next message |
| Windows service not starting | Run install_service.ps1 as Administrator; check logs/ for NSSM output |
| Linux service not starting | Run journalctl --user -u gelegram -n 50 to see startup errors |
| macOS service not starting | Run tail -50 gateway.log; check plist with launchctl list | grep gelegram |
| Gateway warns "Gemini CLI could not be found" | Set GEMINI_CLI_PATH in .env to the absolute path of gemini or gemini.cmd |
tools.log is empty |
The bot hasn't processed a message yet — tool calls only appear after Gemini uses a tool |
To see all raw JSON-RPC messages exchanged with gemini-cli, edit bot.py:
logging.basicConfig(..., level=logging.DEBUG, ...)MIT — see LICENSE for details.
Built with python-telegram-bot and Gemini CLI.