> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ollim.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# File formats

> Reference the YAML frontmatter fields and JSONL schemas used by all data files.

YAML frontmatter specs for routines, reminders, webhooks, and skills, plus JSON/JSONL schemas for all state files.

All persistent data in ollim-bot lives under `~/.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                                                      |
| `reflect`             | `bool`              | `true`         | Write a [reflection trace](/scheduling/background-forks#reflections) after the background fork finishes |

The markdown body after the closing `---` becomes the routine's task message.

```yaml title="routines/nightly-sleep-review.md" theme={null}
---
id: "eb56e06b"
cron: "0 22 * * *"
description: "10 PM daily -- read sleep data"
background: true
---
Review tonight's sleep data and prepare a brief summary.
Check the sleep tracker for any anomalies.
```

<Note>
  Every background fork always receives the [default tools](/scheduling/background-forks#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](/scheduling/background-forks#tool-restrictions) for details.
</Note>

### 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                                                      |
| `reflect`             | `bool`              | `true`         | Write a [reflection trace](/scheduling/background-forks#reflections) after the background fork finishes |

```yaml title="reminders/pick-up-groceries.md" theme={null}
---
id: "a1b2c3d4"
run-at: "2026-02-24T18:30:00-08:00"
---
Pick up groceries on the way home.
```

Chained reminder example:

```yaml title="reminders/follow-up-on-project.md" theme={null}
---
id: "f5e6d7c8"
run-at: "2026-02-24T20:00:00-08:00"
max-chain: 2
chain-parent: "f5e6d7c8"
description: "Project follow-up"
---
Follow up on project timeline. Check if deadlines have been updated.
```

### 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                                           |
| `reflect`             | `bool`              | `true`      | Write a [reflection trace](/scheduling/background-forks#reflections) after the fork finishes |

The markdown body is a template — `{field_name}` placeholders are replaced with payload values at dispatch time.

```yaml title="webhooks/ci-for-repo-status.md" theme={null}
---
id: "ci"
isolated: true
model: "haiku"
fields:
  type: object
  required:
    - repo
    - status
  properties:
    repo:
      type: string
      maxLength: 200
    status:
      type: string
      enum: [success, failure]
  additionalProperties: false
---
CI for {repo}: {status}. Review the build logs and take any necessary action.
```

<Tip>
  String properties in the `fields` schema that lack an explicit `maxLength`
  automatically get a default limit of 500 characters. The total payload size
  is capped at 10 KB, with a maximum of 20 properties.
</Tip>

### 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  |

The markdown body contains the skill's instructions. It can include dynamic context markers using the `` !`command` `` syntax — shell commands expanded to their output at load time.

```yaml title="skills/ux-principles/SKILL.md" theme={null}
---
name: "ux-principles"
description: "User-facing design principles for notifications, proactive outreach, and bot responses"
---
When designing user-facing features, follow these principles:

1. Surface errors clearly — the user should never wonder what happened.
2. Prefer report_updates over pinging when the information isn't time-sensitive.
```

<Note>
  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](/extending/skills#dynamic-context-injection) for the full expansion rules.
</Note>

### 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`) |

The file is loaded with mtime-based caching — changes take effect without a restart.

```yaml title="tool-policy.yaml" theme={null}
main_session:
  additional_allowed:
    - "Bash(git status)"
bg_forks:
  additional_allowed:
    - "Bash(ollim-bot cal *)"
```

<Note>
  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.
</Note>

## 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 types:

| Event              | Description                                                                                 |
| ------------------ | ------------------------------------------------------------------------------------------- |
| `created`          | New session created                                                                         |
| `compacted`        | Session ID changed due to [context compaction](/architecture/session-management#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)                                                    |

```json title="session_history.jsonl" theme={null}
{"session_id": "sess_abc", "event": "created",
  "timestamp": "2026-02-24T14:30:45-08:00", "parent_session_id": null}
{"session_id": "sess_def", "event": "bg_fork",
  "timestamp": "2026-02-24T15:00:00-08:00", "parent_session_id": "sess_abc"}
```

### 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) |

Records expire after **7 days** (604,800 seconds). Expired entries are filtered out on read.

### 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 |

Main sessions **pop** (read + clear) pending updates on the next
interaction. Interactive forks **peek** (read-only). Writes are protected
by a lock to prevent concurrent corruption.

### 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)                         |

Records expire after **7 days**. Expired entries are filtered out on read.

```json title="inquiries.json" theme={null}
{
  "a3f8b2c1": {"prompt": "The user clicked 'Mark as done'. Complete the task.", "ts": 1740441045.12},
  "d4e9f0a2": {"prompt": "The user wants more details about this item.", "ts": 1740441060.45}
}
```

### 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                   |

<Warning>
  Ping budget is **not** git-committed — it is ephemeral state that resets to defaults if the file is deleted.
</Warning>

### Runtime configuration (`config.json`)

JSON object storing persistent settings you configure via the [`/config`](/core-usage/slash-commands#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                                                                 |

```json title="config.json" theme={null}
{
  "model_main": "sonnet",
  "thinking_fork": "32000",
  "fork_idle_timeout": 15
}
```

Only non-default values are stored. Missing keys use their defaults.

<Note>
  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.
</Note>

## Next steps

<Columns cols={2}>
  <Card title="Data directory" icon="folder" href="/configuration/data-directory">
    Full layout of the `~/.ollim-bot/` directory structure.
  </Card>

  <Card title="Configuration reference" icon="gear" href="/configuration/reference">
    Environment variables and configuration options.
  </Card>

  <Card title="Routines" icon="clock" href="/scheduling/routines">
    How to create and manage recurring routines.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/integrations/webhooks">
    External triggers and webhook spec files.
  </Card>
</Columns>
