Skip to main content
ollim-bot is a standard Python project managed with uv. This guide covers setting up a development environment, running the bot locally, and understanding the project structure and conventions.

Prerequisites

  • uvcurl -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

1

Clone the repository

git clone https://github.com/Ollim-AI/ollim-bot.git
cd ollim-bot
2

Install dependencies

uv tool install --editable .
uv sync
uv run pre-commit install
The first command installs 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.
3

Configure environment variables

Copy the example file and fill in your values:
cp .env.example .env
VariableRequiredDescription
DISCORD_TOKENYesDiscord bot token
OLLIM_USER_NAMEYesYour display name (used in the system prompt)
OLLIM_BOT_NAMEYesThe bot’s display name
OLLIM_TIMEZONENoIANA timezone (e.g. America/New_York); defaults to auto-detected system timezone, then UTC
WEBHOOK_PORTNoPort for the webhook HTTP server (e.g. 8420)
WEBHOOK_SECRETConditionalBearer token for webhook auth (required if WEBHOOK_PORT is set)
4

Run the bot

ollim-bot
On startup, the bot checks Claude authentication — if not logged in, it DMs you an OAuth link via the Discord REST API. See the quickstart for the full startup flow. The bot also checks for an existing instance via a PID file at ~/.ollim-bot/state/bot.pid and exits if one is already running.

Running tests

uv run pytest
Dev dependencies include 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.
# Lint
uv run ruff check

# Format
uv run ruff format

# Type check
uv run ty check

# Install pre-commit hooks (one-time setup)
uv run pre-commit install
The pre-commit config runs 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 to main:
  • Lint jobruff check, ruff format --check, ty check
  • Test jobpytest across Python 3.11, 3.12, and 3.13

Project structure

The source lives under src/ollim_bot/. Each file owns a single domain — there are no utils, helpers, or common modules.
src/ollim_bot/
├── main.py              # CLI entry point, command router, SDK layout setup
├── bot.py               # Discord interface (DMs, slash commands)
├── channel.py           # DM channel reference, set once at startup
├── agent.py             # Agent SDK wrapper (sessions, MCP servers, slash routing)
├── agent_context.py     # Message context: timestamps, pending updates, ThinkingConfig
├── agent_streaming.py   # Stream consumer: SDK message loop, auto-compaction retry
├── prompts.py           # System prompt for main agent and fork prompt helpers
├── subagents.py         # Bundled agent installation and tool-set extraction
├── subagents/           # Subagent specs (markdown files with YAML frontmatter)
├── skills.py            # Skill data model and directory-based persistence
├── agent_tools.py       # MCP tools (discord_embed, ping_user, enter_fork, etc.)
├── auth.py              # Claude Code auth via bundled CLI (headless login flow)
├── config.py            # Env vars loaded from .env via dotenv
├── runtime_config.py    # Persistent runtime config (model, thinking, timeouts)
├── fork_state.py        # Fork state: contextvars, dataclasses, idle timeouts
├── forks.py             # Pending updates I/O and background fork execution
├── sessions.py          # Session ID persistence and session history JSONL log
├── permissions.py       # Discord-based tool approval (canUseTool callback)
├── tool_policy.py       # Tool-pattern validation and per-job tool restrictions
├── streamer.py          # Streams agent responses to Discord (throttled edits)
├── storage.py           # JSONL/markdown I/O and git auto-commit
├── embeds.py            # Embed/button types, builders, and build_embed/build_view
├── views.py             # Persistent button handlers via DynamicItem
├── inquiries.py         # Button inquiry prompt persistence (7-day TTL)
├── ping_budget.py       # Refill-on-read ping budget for background fork notifications
├── formatting.py        # Tool-label formatting helpers
├── webhook.py           # Webhook HTTP server for external triggers
├── google/
│   ├── auth.py          # Shared Google OAuth2 (Tasks + Calendar + Gmail)
│   ├── tasks.py         # Google Tasks CLI + API helpers
│   ├── calendar.py      # Google Calendar CLI + API helpers
│   └── gmail.py         # Gmail CLI (read-only)
└── scheduling/
    ├── scheduler.py     # APScheduler-based proactive scheduling
    ├── routines.py      # Routine dataclass and markdown I/O
    ├── reminders.py     # Reminder dataclass and markdown I/O
    ├── preamble.py      # Bg preamble and forward schedule builder
    ├── routine_cmd.py   # Routines CLI (ollim-bot routine)
    └── reminder_cmd.py  # Reminders CLI (ollim-bot reminder)

CLI subcommands

The ollim-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:
CommandDescription
ollim-botStart the Discord bot
ollim-bot routine add|list|cancelManage recurring routines
ollim-bot reminder add|list|cancelManage one-shot reminders
ollim-bot tasks list|add|done|update|deleteGoogle Tasks operations
ollim-bot cal today|upcoming|show|add|update|deleteGoogle Calendar operations
ollim-bot gmail unread|read|search|labelsGmail (read-only)
ollim-bot auth login|status|logoutManage Claude Code authentication
ollim-bot helpShow help text
See the CLI reference for full flag documentation.

Code conventions

These rules come from the project’s CLAUDE.md and apply to all contributions.

Hard invariants

Violating these causes runtime bugs.
Channel-sync invariant — every path into stream_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

RuleRationale
No utils/helpers/common filesEvery function belongs in a domain module
No catch-all directoriesName for what it does (google/, scheduling/), not what it is
Max ~400 lines per fileSplit by responsibility when approaching the limit
No duplicate logic across modulesIf 3 modules share a pattern, extract it
One logging systemlogging.getLogger(__name__) for library code, print() only in CLI commands

Dependencies

Key runtime dependencies (from pyproject.toml):
PackagePurpose
discord.pyDiscord bot framework
claude-agent-sdkClaude Agent SDK for persistent AI sessions
google-api-python-clientGoogle API access (Tasks, Calendar, Gmail)
google-auth-oauthlibGoogle OAuth2 flow
apschedulerCron-based scheduling for routines and reminders
python-dotenv.env file loading
pyyamlYAML frontmatter parsing
aiohttpWebhook HTTP server
jsonschemaWebhook payload validation
claude-historySession transcript search — bundled as a dependency, exposes the claude-history CLI
Key dev dependencies:
PackagePurpose
ruffLinting and formatting
tyType checking
pre-commitGit hooks for automated lint/format/type checks
pytestTest framework
pytest-asyncioAsync test support
pytest-covCoverage 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.