JClaw is a lightweight AI assistant daemon for macOS that polls Telegram, stores state in SQLite, and talks to any OpenAI-compatible API endpoint such as DeepSeek or GLM.
The bootstrap in this repo is intentionally lean:
- Telegram long-polling instead of a heavier chat bridge
- SQLite for history, memory, and automation state
- A compact prompt pipeline to reduce token usage
- A
launchdinstaller so it can stay alive on your MacBook
- Create a virtualenv and install the package:
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"- Generate a starter config:
jclaw init-config- Edit
~/.config/jclaw/config.tomlwith:
telegram.bot_tokenprovider.api_keyprovider.base_urlprovider.model
- Run a health check:
jclaw doctor- Run in the foreground:
jclaw run- Install as a background macOS daemon:
jclaw install-launchdJClaw can run cleanly with one production Telegram bot and one development Telegram bot.
prod: backgroundlaunchdservice, always-on bot, config at~/.config/jclaw/config.tomldev: foreground process for interactive testing, separate bot, config at~/.config/jclaw/config.dev.toml
The recommended pattern is:
- Keep
~/.config/jclaw/config.tomlas the full production config. - Make
~/.config/jclaw/config.dev.tomla small overlay that inherits from prod and overrides only the settings that should differ.
Example config.dev.toml:
extends = "/Users/guanw/.config/jclaw/config.toml"
[telegram]
bot_token = "YOUR_DEV_BOT_TOKEN"
allowed_chat_ids = []
[daemon]
state_dir = "/Users/guanw/Library/Application Support/JClawDev"
db_path = "/Users/guanw/Library/Application Support/JClawDev/jclaw.db"
stdout_log = "/Users/guanw/Library/Logs/JClawDev/stdout.log"
stderr_log = "/Users/guanw/Library/Logs/JClawDev/stderr.log"
launchd_label = "com.jclaw.dev"
[memory]
max_memory_items = 100Notes:
extends = "..."loads the base config first, then applies overrides from the current file.- Use a different Telegram bot token for dev so dev and prod do not fight over
getUpdates. - Use a separate
state_diranddb_pathfor dev if you want dev memory, traces, and offsets isolated from prod.
Start production:
scripts/bootstrap_local_prod.shRestart production after code changes:
scripts/bootstrap_local_prod.sh --restart-onlyStart the dev Telegram loop in the foreground:
scripts/run_dev.shRun a local dev turn without starting a Telegram poller:
.venv/bin/python jclaw.py send --config ~/.config/jclaw/config.dev.toml "test prompt"Important:
- In the current CLI,
--configmust come after the subcommand, for examplejclaw.py run --config .... jclaw.py --config ... runmay silently fall back to the default prod config.
This split avoids the common failure mode where two jclaw run processes use the same Telegram bot token and trigger Telegram 409 Conflict errors.
Create a bot with @BotFather, copy the bot token into the config, and send the bot a message from Telegram. If you want to restrict access, set telegram.allowed_chat_ids after you learn your chat ID from the logs or database.
JClaw keeps token usage down by:
- handling simple memory commands locally without an LLM call
- sending only a small recent history window
- retrieving only a few relevant memory snippets
- instructing the model to answer briefly by default
These can be sent from Telegram or from the CLI with jclaw send:
/help/remember project = building a telegram-first assistant/memory/forget projectRemind me every day at 9 AM to stretchRemind me to practice interview at 9 AM on April 27Remind me in 30 minutes to check the build