~/.ollim-bot/ directory and what it does.
All persistent data lives in ~/.ollim-bot/. The directory is created on
first use and automatically managed as a git repository — storage.py
auto-commits after most writes.
The root contains agent-facing files (profile files, routines, reminders,
webhooks, and the optional tool-policy.yaml) that the
agent reads and writes directly. Infrastructure state (sessions, credentials, ping
budget, etc.) lives in the state/ subdirectory, keeping the agent’s
working directory clean. The state/ directory is write-protected
from agent tool access — a PreToolUse hook blocks Write and Edit calls
targeting paths inside state/. See
Permissions
for details.
Profile files
Two markdown files in the data directory root customize the bot’s persona and provide context about you. Both are prepended to the system prompt — see System prompt for how they compose into the final prompt.| File | Source | Description |
|---|---|---|
IDENTITY.md | bootstrap_identity() in profile.py — created on first run, skipped if file exists | Bot persona and communication style |
USER.md | User-created | Context about the user |
Downloads
Non-image Discord attachments (PDFs, text files, spreadsheets, etc.) are saved todownloads/ so the agent can read them with its Read
tool. Filename collisions are handled with numeric suffixes
(file-2.txt, file-3.txt). This directory is created on first use.
See File attachments
for user-facing details.
Session files
All files in this section and below live in thestate/ subdirectory.
These files track the agent’s conversation state across restarts.
| File | Format | Description |
|---|---|---|
sessions.json | Plain string | Active Agent SDK session ID. A raw string, not JSON. Read on startup to resume. |
session_history.jsonl | JSONL | Append-only log of session lifecycle events. One JSON object per line. |
Session events
Each line insession_history.jsonl contains:
| Field | Type | Description |
|---|---|---|
session_id | str | The Agent SDK session ID |
event | str | One of: created, compacted, swapped, cleared, interactive_fork, bg_fork, isolated_bg, restarting |
timestamp | str | ISO 8601 datetime in the configured timezone (OLLIM_TIMEZONE) |
parent_session_id | str | null | Set for compacted, swapped, and fork events |
session_history.jsonl
Compaction is detected two ways: the
/compact command detects it
via the compact_boundary SystemMessage from the SDK, while
save_session_id() catches SDK auto-compaction by detecting session
ID changes. A _swap_in_progress flag suppresses false compacted
events during swap_client().Fork and inquiry files
These files track ephemeral Discord interaction state. Both use a 7-day TTL — entries older than 7 days are pruned on every read.| File | Format | Description |
|---|---|---|
fork_messages.json | JSON array | Maps Discord message IDs to fork session IDs, enabling reply-to-fork. |
inquiries.json | JSON object | Maps 8-char hex keys to inquiry prompts. Persists button actions across restarts. |
fork_messages.json
fork_messages.json
| Field | Type | Description |
|---|---|---|
message_id | int | Discord message snowflake ID |
fork_session_id | str | Agent SDK session ID for the fork |
parent_session_id | str | null | Session the fork branched from |
ts | float | Unix timestamp for TTL pruning |
inquiries.json
inquiries.json
| Field | Type | Description |
|---|---|---|
| (key) | str | 8-character hex UUID |
prompt | str | The full prompt string for the button inquiry |
ts | float | Unix timestamp for TTL pruning |
Pending updates
Background forks write summaries topending_updates.json via the
report_updates MCP tool. The main session reads and clears these on
its next turn.
pending_updates.json
| Field | Type | Description |
|---|---|---|
ts | str | ISO 8601 datetime in the configured timezone (OLLIM_TIMEZONE) |
message | str | Summary from the background fork |
Concurrent background forks use an
asyncio.Lock to protect the
read-modify-write cycle on this file, preventing lost updates.Ping budget
ping_budget.json stores the refill-on-read token bucket state for
proactive pings. This file is not git-committed — it is ephemeral
state that resets naturally.
ping_budget.json
| Field | Type | Default | Description |
|---|---|---|---|
capacity | int | 5 | Maximum pings in the bucket |
available | float | — | Current fractional ping count |
refill_rate_minutes | int | 90 | Minutes per 1 ping refill |
last_refill | str | — | ISO 8601 datetime of last refill computation |
critical_used | int | — | Critical pings used today (resets daily) |
critical_reset_date | str | — | ISO date for critical_used reset |
daily_used | int | — | Total pings used today |
daily_used_reset | str | — | ISO date for daily_used reset |
load(), time-based refill is computed and daily counters are
reset if the date has changed. The updated state is saved back
immediately.
Runtime configuration
config.json stores persistent settings you configure via /config. These
include per-context model and thinking defaults, timeouts, and the default
permission mode. See Configuration reference for the full key listing.
This file is not git-committed — it is local configuration that may
vary between instances.
Agent-managed directories
Routines, reminders, webhooks, and skills are each stored as files in their own subdirectory. For routines, reminders, and webhooks, filenames are auto-generated slugs from the message content (max 50 characters) and theid field in YAML frontmatter is authoritative. Skills use a
different structure: each skill is a directory named after the skill,
containing a SKILL.md file.
| Directory | Contents | Description |
|---|---|---|
routines/ | *.md | Recurring cron-scheduled routines |
reminders/ | *.md | One-shot and chainable reminders |
webhooks/ | *.md | Webhook endpoint specs with prompt templates |
skills/ | */SKILL.md | Reusable instruction sets referenced by routines and reminders |
---, followed by a markdown body. See
File formats for the full field specs.
routines/morning-briefing.md
SDK layout directory
The.claude/ directory is the Agent SDK’s expected layout for discovering
subagents and skills. _ensure_sdk_layout() in main.py creates it
automatically at startup.
| Path | Type | Description |
|---|---|---|
.claude/agents/*.md | Regular files | Bundled subagent specs copied from the source tree with template expansion ({USER_NAME}, {BOT_NAME}). Existing files are never overwritten — your customizations persist across updates. |
.claude/skills/ | Symlink → ../skills/ | Lets the SDK discover skills without duplicating the skills/ directory. |
cwd=DATA_DIR and
setting_sources=["project"] — the SDK resolves .claude/ relative to
the working directory.
Google credentials
| File | Source | Description |
|---|---|---|
credentials.json | Manual — Google Cloud Console | OAuth 2.0 client creds |
token.json | Auto-generated after /google-auth | OAuth refresh and access tokens |
token.json is auto-generated
when you run /google-auth.
Process lock
bot.pid contains the PID of the running bot process. On startup,
_check_already_running() reads this file and uses os.kill(pid, 0) to
check if the process is alive. On Linux, it additionally verifies
/proc/<pid>/cmdline contains ollim-bot to avoid false positives from
recycled PIDs. Corrupted PID files (non-numeric content or read errors) are
silently overwritten. The file is deleted on exit via atexit.
Git tracking
The~/.ollim-bot/ directory is initialized as a git repository.
storage.py auto-commits after writes to most files. Files that are
not git-committed:
| File | Reason |
|---|---|
state/ping_budget.json | Ephemeral state that refills over time |
state/bot.pid | Process lock deleted on exit |
state/credentials.json | Sensitive OAuth client credentials |
state/token.json | Sensitive OAuth tokens |
state/sessions.json | Frequent overwrites on every agent turn |
state/fork_messages.json | Ephemeral mapping with 7-day TTL |
state/pending_updates.json | Ephemeral cross-fork messaging |
state/inquiries.json | Ephemeral button state with 7-day TTL |
state/config.json | Local runtime preferences |
.claude/agents/*.md | SDK infrastructure — written once at startup, not managed by storage.py |
.claude/skills/ | Symlink — SDK infrastructure |
Next steps
File formats
YAML frontmatter specs for routines, reminders, webhooks, and skills.
Configuration reference
Environment variables and .env file setup.
Ping budget
How the refill-on-read token bucket controls proactive pings.
Set up Google integration
Connect Google Tasks, Calendar, and Gmail.
