~/.ollim-bot/ as flat files.
There are two families of formats: markdown files with YAML frontmatter
(routines, reminders, webhooks, skills) and JSON/JSONL files (sessions, pending
updates, inquiries, ping budget). The data directory is a git repository —
most writes are auto-committed.
Markdown files (YAML frontmatter)
Routines, reminders, and webhooks share a common file structure: YAML frontmatter delimited by---, followed by a markdown body. Fields that
match their default value are omitted from the YAML when serialized.
Routines
Stored in~/.ollim-bot/routines/*.md. Filenames are auto-generated slugs based on the message body.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | auto-generated | 8-character hex UUID (uuid4().hex[:8]) |
cron | str | — | Cron expression (5-field standard format) |
description | str | "" | Human-readable description |
background | bool | false | Run as background fork |
model | str | null | null | Model override ("opus", "sonnet", "haiku") |
thinking | bool | true | Enable extended thinking |
isolated | bool | false | Run in isolated session (no conversation history) |
update-main-session | str | "on_ping" | When to report: always, on_ping, freely, blocked |
allow-ping | bool | true | Allow ping_user and discord_embed tools |
allowed-tools | list[str] | null | null | Additional tools merged with default background tools |
skills | list[str] | null | null | Skill names to load at fire time (e.g., [ux-principles, async-principles]) |
subagent | str | null | null | Subagent to delegate the core task to at fire time |
--- becomes the routine’s task message.
routines/nightly-sleep-review.md
Every background fork always receives the default tools — help, tasks CLI, and read-only file tools (
Read, Glob, Grep scoped to ./**.md). Discord tools are controlled separately by allow-ping and update-main-session. When allowed-tools is set, your tools are merged in on top of these defaults. See Tool restrictions for details.Reminders
Stored in~/.ollim-bot/reminders/*.md. Same slug-based filenames as routines.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | auto-generated | 8-character hex UUID |
run-at | str | — | ISO 8601 datetime with timezone (e.g., 2026-02-24T15:30:00-08:00) |
description | str | "" | Human-readable description |
background | bool | true | Run as background fork |
chain-depth | int | 0 | Current position in a follow-up chain (0 = root) |
max-chain | int | 0 | Maximum chain depth (0 = no chaining) |
chain-parent | str | null | null | ID of chain root (auto-set to own id when max-chain > 0) |
model | str | null | null | Model override |
thinking | bool | true | Enable extended thinking |
isolated | bool | false | Run in isolated session |
update-main-session | str | "on_ping" | When to report: always, on_ping, freely, blocked |
allow-ping | bool | true | Allow ping_user and discord_embed tools |
allowed-tools | list[str] | null | null | Additional tools merged with default background tools |
skills | list[str] | null | null | Skill names to load at fire time (e.g., [ux-principles, async-principles]) |
subagent | str | null | null | Subagent to delegate the core task to at fire time |
reminders/pick-up-groceries.md
reminders/follow-up-on-project.md
Webhooks
Stored in~/.ollim-bot/webhooks/*.md. Same slug-based filenames.
| Field | Type | Default | Description |
|---|---|---|---|
id | str | — | Webhook identifier (used in endpoint URL: POST /hook/{id}) |
fields | dict | — | JSON Schema (Draft 7) defining the expected payload |
isolated | bool | false | Run in isolated session |
model | str | null | null | Model override |
thinking | bool | true | Enable extended thinking |
allow-ping | bool | true | Allow notification tools |
update-main-session | str | "on_ping" | When to report: always, on_ping, freely, blocked |
allowed-tools | list[str] | null | null | Additional tools merged with default background tools |
skills | list[str] | null | null | Skill names to load at fire time |
subagent | str | null | null | Subagent to delegate the core task to at fire time |
{field_name} placeholders are replaced with payload values at dispatch time.
webhooks/ci-for-repo-status.md
Skills
Stored in~/.ollim-bot/skills/<name>/SKILL.md. Each skill is a directory containing a single SKILL.md file.
| Field | Type | Default | Description |
|---|---|---|---|
name | str | — | Skill name (lowercase with hyphens, matches directory name) |
description | str | — | What the skill does and when to use it |
allowed-tools | list[str] | null | null | Tool dependencies merged into the host job’s allowed tools |
!`command` syntax — shell commands expanded to their output at load time.
skills/ux-principles/SKILL.md
Dynamic context markers (
!`command`) have a 10-second per-command timeout and a 30-second total cap. Each command’s output is truncated to 2000 characters. See Dynamic context injection for the full expansion rules.Tool policy (tool-policy.yaml)
Stored at ~/.ollim-bot/tool-policy.yaml. An optional YAML file that lets you extend or override the default tool sets without editing source code.
| Key | Type | Description |
|---|---|---|
main_session.additional_allowed | list[str] | Extra tool patterns merged into the main session’s allowed_tools |
bg_forks.additional_allowed | list[str] | Extra tool patterns merged into the default background fork tools |
bg_forks.override | list[str] | Completely replaces the default background fork tools (takes precedence over additional_allowed) |
tool-policy.yaml
If
bg_forks.override is set, it completely replaces the default background tools — use with care. The additional_allowed key is safer for most use cases.Shared markdown conventions
These rules apply to routines, reminders, and webhooks. Skills use a directory-based structure (skills/<name>/SKILL.md) instead of slug-generated filenames, but share the same atomic write and git conventions.
| Behavior | Details |
|---|---|
| Slug generation | Lowercase, replace non-alphanumeric characters with -, max 50 characters, strip trailing - |
| Collision handling | Same id overwrites the file; different id appends -2, -3, etc. |
| Atomic writes | Writes are atomic — partial writes never corrupt files |
| Default omission | Only non-default fields appear in YAML frontmatter |
| String serialization | Double-quoted: key: "value" |
| Boolean serialization | Lowercase: key: true |
| List serialization | YAML block format with quoted string items |
| Parsing | Unknown YAML keys are silently skipped (forward-compatible) |
| Git integration | Each write auto-commits with a message like "add routine eb56e06b" |
JSON and JSONL files
Session history (session_history.jsonl)
Append-only JSONL log of session lifecycle events.
| Field | Type | Description |
|---|---|---|
session_id | str | Session identifier |
event | str | Event type (see below) |
timestamp | str | ISO datetime in the configured timezone |
parent_session_id | str | null | Parent session for forks and compactions |
| Event | Description |
|---|---|
created | New session created |
compacted | Session ID changed due to context compaction |
swapped | Fork promoted to main session |
cleared | Session cleared via /clear |
interactive_fork | Interactive fork created |
bg_fork | Background fork created |
isolated_bg | Isolated background fork created |
restarting | Bot is restarting (recorded before exit) |
session_history.jsonl
Current session (sessions.json)
Plain text file containing the current session ID. Despite the
.json extension, it is not JSON — it contains only the raw session
ID string.
Fork messages (fork_messages.json)
JSON array tracking Discord messages associated with active forks.
| Field | Type | Description |
|---|---|---|
message_id | int | Discord message ID |
fork_session_id | str | Session ID of the fork |
parent_session_id | str | null | Parent session ID |
ts | float | Unix timestamp (for TTL enforcement) |
Pending updates (pending_updates.json)
JSON array of updates written by background forks for the main session.
| Field | Type | Description |
|---|---|---|
ts | str | ISO datetime string |
message | str | Summary text from the report_updates tool |
Inquiries (inquiries.json)
JSON object mapping 8-character hex UUIDs to button inquiry entries.
Persists inquiry prompts so agent-created buttons survive bot restarts.
| Field | Type | Description |
|---|---|---|
prompt | str | The prompt text sent to the agent when the button is clicked |
ts | float | Unix timestamp (for TTL enforcement) |
inquiries.json
Ping budget (ping_budget.json)
JSON object tracking the refill-on-read ping budget for background forks.
| Field | Type | Default | Description |
|---|---|---|---|
capacity | int | 5 | Maximum available pings |
available | float | 5.0 | Current available pings (fractional during refill) |
refill_rate_minutes | int | 90 | Minutes per ping refill |
last_refill | str | — | ISO datetime of last refill calculation |
critical_used | int | 0 | Critical pings used today (bypasses budget) |
critical_reset_date | str | — | ISO date for critical counter reset |
daily_used | int | 0 | Total pings used today |
daily_used_reset | str | — | ISO date for daily counter reset |
Runtime configuration (config.json)
JSON object storing persistent settings you configure via the /config slash command.
| Key | Type | Default | Description |
|---|---|---|---|
model_main | str | null | null | Default model for the main session |
model_fork | str | null | null | Default model for interactive forks |
thinking_main | str | "off" | Extended thinking mode for the main session ("off", "adaptive", or a budget integer as string) |
thinking_fork | str | "adaptive" | Extended thinking mode for interactive forks ("off", "adaptive", or a budget integer as string) |
bg_fork_timeout | int | 1800 | Max background fork runtime (seconds) |
fork_idle_timeout | int | 10 | Interactive fork idle timeout (minutes) |
permission_mode | str | "dontAsk" | Default permission mode |
auto_update | bool | false | Auto-pull, upgrade tool install, and restart on new commits |
auto_update_interval | int | 60 | Update check interval (minutes) |
auto_update_hour | int | 6 | Hour of day (0-23) to apply updates |
config.json
The JSON keys use underscores (
model_main), while the /config slash command displays them with dots (model.main). The command translates between the two formats automatically.Next steps
Data directory
Full layout of the
~/.ollim-bot/ directory structure.Configuration reference
Environment variables and configuration options.
Routines
How to create and manage recurring routines.
Webhooks
External triggers and webhook spec files.
