A lightweight Telegram bot for adding transactions to your Beancount ledger file with fuzzy account matching.
- Add transactions via simple Telegram messages
- Fuzzy account name matching for fast entry
- Multi-leg transaction support
- Account completion based on usage frequency
- Transaction revert functionality
- Docker support with GitHub Container Registry
- Uptime Kuma push monitor support
- Create a bot with @BotFather and get your bot token
- Get your Telegram User ID from @userinfobot
- Create a
.envfile with your configuration:BOT=your_bot_token_here CHAT_ID=your_telegram_user_id BEANCOUNT_ROOT=/data/main.beancount BEANCOUNT_OUTPUT=/data/transactions.beancount CURRENCY=CNY PROXY= # Optional: leave empty if not needed - Run with Docker Compose:
docker-compose up -d
- Create a bot with @BotFather and get your bot token
- Get your Telegram User ID from @userinfobot
- Copy
src/.env.exampletosrc/.envand update with your values - Install dependencies and run:
# Using uv (recommended) uv run src/bot.py # Or using pip python3 -m pip install -r requirements.txt python3 src/bot.py
The docker-compose.yaml uses the pre-built image from GitHub Container Registry by default:
image: ghcr.io/wogong/beancount-bot:masterUpdate the volumes section with your beancount files path:
volumes:
- /path/to/your/beancount/files:/data
- ./src/.env.docker:/app/src/.envTo build locally instead, uncomment the build section in docker-compose.yaml.
Send a message to the bot with the following format:
{account_from1 amount1} {account_from2 amount2} ... account_to note
Rules:
- Account names use fuzzy matching (similar to vim/vscode completion)
- First
2n+1space-separated tokens are parsed as accounts and amounts - Everything after that becomes the transaction note
- Transactions with ambiguous account matches are marked with
! - Each transaction gets a "Revert" button to undo if needed
Examples:
-
Simple two-leg transaction:
1234 20 Restau 中饭Generates:
2024-01-10 * "" "中饭" Assets:Savings:BOC1234 -20.00 CNY Expenses:Food:Restaurant 20.00 CNY -
Multi-leg transaction:
1234 48.12 in:alibaba 1.88 fruit 水果:西瓜 菠萝蜜Generates:
2024-01-10 * "" "水果:西瓜 菠萝蜜" Assets:Savings:BOC1234 -48.12 CNY Income:Bonus:Alibaba -1.88 CNY Expenses:Food:Fruit 50.00 CNY
/start- Start the bot/help- Show available commands/reload- Reload account list fromaccounts.listfile
The bot uses an accounts.list file for fuzzy account matching:
- Generated automatically on first startup from your beancount output file
- Accounts are sorted by usage frequency (most used first)
- Located in the same directory as your
BEANCOUNT_ROOTfile - Manually edit or regenerate by deleting and restarting the bot
# Using pytest
pytest src/test_bot.py
# Using uv
uv run pytest src/test_bot.pyThe bot automatically publishes Docker images to GitHub Container Registry on every push to master or version tag.
Pull pre-built image:
docker pull ghcr.io/wogong/beancount-bot:masterBuild locally:
docker build -t beancount-bot ..
├── src/
│ ├── bot.py # Main bot code
│ ├── test_bot.py # Unit tests
│ └── .env.example # Environment variables template
├── Dockerfile # Docker image definition
├── docker-compose.yaml # Docker Compose configuration
└── pyproject.toml # Python dependencies (uv)
| Variable | Description | Example |
|---|---|---|
BOT |
Telegram bot token from BotFather | 123456:ABC-DEF... |
CHAT_ID |
Your Telegram user ID | 123456789 |
BEANCOUNT_ROOT |
Path to main beancount file | /data/main.beancount |
BEANCOUNT_OUTPUT |
Path to output file for new transactions | /data/transactions.beancount |
CURRENCY |
Default currency | CNY or USD |
PROXY |
Optional HTTP proxy | Leave empty if not needed |
UPTIME_URL |
Uptime Kuma push monitor URL | Leave empty to disable |
UPTIME_INTERVAL |
Heartbeat interval in seconds | 60 (default) |
- beancount - Double-entry accounting from text files
- vim-beancount - Account completion inspiration
- python-telegram-bot - Telegram Bot API wrapper