Prerequisites
- uv —
curl -LsSf https://astral.sh/uv/install.sh | sh(automatically installs the required Python version) - A Discord bot token (see the quickstart)
- Google OAuth credentials (see Google integration setup) if using Google integrations
Setup
Install dependencies
ollim-bot and claude-history as global
commands. claude-history is a CLI tool required by
subagents. uv sync installs dev dependencies
(pytest, ruff, ty). Pre-commit hooks enforce linting and type checking
on every commit.Configure environment variables
Copy the example file and fill in your values:
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN | Yes | Discord bot token |
OLLIM_USER_NAME | Yes | Your display name (used in the system prompt) |
OLLIM_BOT_NAME | Yes | The bot’s display name |
OLLIM_TIMEZONE | No | IANA timezone (e.g. America/New_York); defaults to auto-detected system timezone, then UTC |
WEBHOOK_PORT | No | Port for the webhook HTTP server (e.g. 8420) |
WEBHOOK_SECRET | Conditional | Bearer token for webhook auth (required if WEBHOOK_PORT is set) |
Run the bot
~/.ollim-bot/state/bot.pid and exits if one is already running.Running tests
pytest, pytest-asyncio, and pytest-cov.
See Testing for the test philosophy and conventions.
Linting and type checking
ollim-bot uses ruff for linting and formatting, and ty for type checking. Pre-commit hooks run both automatically on every commit.ruff --fix (auto-fixes safe lint issues), ruff format,
and ty check on staged Python files. CI runs the same checks — see below.
CI
GitHub Actions runs on every push and pull request tomain:
- Lint job —
ruff check,ruff format --check,ty check - Test job —
pytestacross Python 3.11, 3.12, and 3.13
Project structure
The source lives undersrc/ollim_bot/. Each file owns a single domain —
there are no utils, helpers, or common modules.
CLI subcommands
Theollim-bot command doubles as both the bot runner and a CLI for managing
routines, reminders, and Google integrations. Running ollim-bot with no
arguments starts the Discord bot. Subcommands route to their respective modules:
| Command | Description |
|---|---|
ollim-bot | Start the Discord bot |
ollim-bot routine add|list|cancel | Manage recurring routines |
ollim-bot reminder add|list|cancel | Manage one-shot reminders |
ollim-bot tasks list|add|done|update|delete | Google Tasks operations |
ollim-bot cal today|upcoming|show|add|update|delete | Google Calendar operations |
ollim-bot gmail unread|read|search|labels | Gmail (read-only) |
ollim-bot auth login|status|logout | Manage Claude Code authentication |
ollim-bot help | Show help text |
Code conventions
These rules come from the project’sCLAUDE.md and apply to all contributions.
Hard invariants
Channel-sync invariant — every path intostream_chat must call both
agent_tools.set_channel and permissions.set_channel. This applies to
_dispatch, _check_fork_transitions, slash_fork, send_agent_dm,
button handlers in views.py, and check_fork_timeout in scheduler.py.
Design rules
| Rule | Rationale |
|---|---|
No utils/helpers/common files | Every function belongs in a domain module |
| No catch-all directories | Name for what it does (google/, scheduling/), not what it is |
| Max ~400 lines per file | Split by responsibility when approaching the limit |
| No duplicate logic across modules | If 3 modules share a pattern, extract it |
| One logging system | logging.getLogger(__name__) for library code, print() only in CLI commands |
Dependencies
Key runtime dependencies (frompyproject.toml):
| Package | Purpose |
|---|---|
discord.py | Discord bot framework |
claude-agent-sdk | Claude Agent SDK for persistent AI sessions |
google-api-python-client | Google API access (Tasks, Calendar, Gmail) |
google-auth-oauthlib | Google OAuth2 flow |
apscheduler | Cron-based scheduling for routines and reminders |
python-dotenv | .env file loading |
pyyaml | YAML frontmatter parsing |
aiohttp | Webhook HTTP server |
jsonschema | Webhook payload validation |
claude-history | Session transcript search — bundled as a dependency, exposes the claude-history CLI |
| Package | Purpose |
|---|---|
ruff | Linting and formatting |
ty | Type checking |
pre-commit | Git hooks for automated lint/format/type checks |
pytest | Test framework |
pytest-asyncio | Async test support |
pytest-cov | Coverage reporting |
Data directory
All persistent state lives in~/.ollim-bot/. If this directory is a git
repository, storage.py auto-commits on writes to routines, reminders, and
other managed files. See
Data directory for the full layout.
Next steps
Testing
Test philosophy, running tests, and the no-mocks policy.
CLI reference
Full documentation of all CLI subcommands and flags.
Architecture overview
Module map, dependency diagram, and data flow.
Adding integrations
How to add new Google services, MCP tools, and webhook specs.
