Skip to main content
Routines and reminders that need the same detailed instructions shouldn’t duplicate them. Skills solve this — reusable instruction sets stored as markdown files under ~/.ollim-bot/skills/<name>/SKILL.md. Define a skill once, reference it by name, and every job that uses it gets the same instructions loaded at fire time.

How skills work

When a routine or reminder fires, the scheduler checks its skills: field. For each referenced skill:
  1. The scheduler loads the skill’s SKILL.md from ~/.ollim-bot/skills/<name>/
  2. The scheduler expands any dynamic context injection markers (!`command`) to command output
  3. The scheduler prepends the expanded instructions to the job message as a SKILL INSTRUCTIONS: block
  4. collect_skill_tools() merges tool dependencies from the skill’s allowed-tools into the routine or reminder’s tool set
The agent sees skill instructions before the job’s own message — like a preamble.
The scheduler loads skills fresh every time a job fires. If you update a skill’s instructions, the next firing picks up the changes automatically.

File format

Each skill lives in its own directory: ~/.ollim-bot/skills/<name>/SKILL.md. The directory name must match the skill’s name field — lowercase with hyphens.
skills/code-review/SKILL.md
---
name: "code-review"
description: "Review code changes for style, correctness, and test coverage."
allowed-tools:
  - "Bash(git *)"
  - "Read(**)"
  - "Glob(**)"
---
Review the staged changes in the repository.

Check for:
- Style violations against the project's conventions
- Logic errors or edge cases
- Missing test coverage for new behavior

Summarize findings as a bulleted list, grouped by file.

Frontmatter fields

FieldTypeDefaultDescription
namestrLowercase with hyphens — must match the directory name
descriptionstrWhat the skill does and when to use it (shown in the system prompt index)
allowed-toolslist[str] | nullnullTool dependencies merged into the host job’s allowed tools
The markdown body after the closing --- becomes the skill’s message — the actual instructions the agent receives.
Keep description concise and action-oriented. It appears in the system prompt’s skill index, so the agent uses it to decide when a skill is relevant — even outside of scheduled jobs.

Dynamic context injection

Skills sometimes need fresh data at fire time — not hardcoded values. The !`command` syntax embeds shell commands that the scheduler expands to their stdout before the agent sees the prompt.
skills/repo-status/SKILL.md (body)
Current branch and recent commits:

!`git -C ~/my-project rev-parse --abbrev-ref HEAD`

!`git -C ~/my-project log --oneline -5`

Use this context when reviewing the latest changes.
When the skill loads, the scheduler replaces each !`command` with the command’s output.

Expansion rules

RuleValue
Per-command timeout10 seconds
Total wall-clock cap30 seconds across all commands in one expansion
Max output per command2000 characters (truncated with [...truncated] if longer)
Working directory~/.ollim-bot/
Error handlingFailed commands are replaced with [command failed (exit N): cmd: error_line]
Timed-out commandsReplaced with [command timed out: cmd]
Skipped commandsIf the total 30s cap is reached, remaining commands become [command skipped (total timeout): cmd]
Commands run synchronously and block the scheduler for their duration. Keep commands fast — read-only queries, not long-running processes. The 10-second per-command and 30-second total timeouts are hard caps.

Using skills in routines and reminders

Reference skills by name in the skills: array of a routine or reminder’s YAML frontmatter:
routines/morning-code-review.md
---
id: "f3a8b1c2"
cron: "0 9 * * 1-5"
description: "Morning code review"
background: true
skills:
  - "code-review"
  - "repo-status"
---
Review any open PRs in the main project repository.
Ping me if anything needs my attention before standup.
When this routine fires, the agent receives:
[routine-bg:f3a8b1c2] <bg preamble>

SKILL INSTRUCTIONS:

### code-review
Review the staged changes in the repository.
...

### repo-status
Current branch and recent commits:
main
a1b2c3d Fix login redirect
...

Review any open PRs in the main project repository.
Ping me if anything needs my attention before standup.

Tool merging

If a skill declares allowed-tools, collect_skill_tools() merges those tools into the host job’s tool set. Background forks always have at least a minimal default tool set, so skill tools always merge. The function deduplicates — if two skills both need Bash(git *), only one entry appears.

Reminders with skills

Reminders work the same way. You can also pass skills via the CLI:
ollim-bot reminder add --delay 60 -m "Check deployment status" \
  --background --skills repo-status
For chained reminders, skills propagate through the chain — the follow_up_chain tool forwards the skills field from the ChainContext, so subsequent chain links inherit the same skill set.

Creating skills

The agent creates skills by writing SKILL.md files directly using its file tools (Write, Edit). You can also create them manually:
mkdir -p ~/.ollim-bot/skills/my-skill
Then create ~/.ollim-bot/skills/my-skill/SKILL.md with the frontmatter and instructions body. For the full format specification — including edge cases and advanced patterns — the agent reads ~/.ollim-bot/skill-spec.md on demand. You can also ask the bot to create a skill conversationally:
“Create a skill called ‘deploy-check’ that verifies the production deployment is healthy by checking the status endpoint and recent error logs.”
The agent reads the spec file, creates the skill directory, and writes the SKILL.md with appropriate frontmatter and instructions.

Developer reference

build_skill_index() in skills.py generates a dynamic index of all available skills and appends it to the system prompt. The format is:
Available skills:
- **code-review**: Review code changes for style, correctness, and test coverage.
- **repo-status**: Show current branch and recent commits for context.
This index tells the agent which skills exist. It references them when creating routines and suggests them when you describe a matching workflow.The agent rebuilds the index every time it starts, so newly created skills appear in the next session.
collect_skill_tools() collects allowed-tools from all referenced skills and returns a deduplicated list. The scheduler calls this in _merge_skill_tools() to extend the background fork’s tool configuration before launching.
def collect_skill_tools(skills: list[Skill]) -> list[str]:
    """Collect tool dependencies from referenced skills. Deduplicated."""
    tools: list[str] = []
    seen: set[str] = set()
    for skill in skills:
        if skill.allowed_tools:
            for tool in skill.allowed_tools:
                if tool not in seen:
                    seen.add(tool)
                    tools.append(tool)
    return tools
load_skills() in the scheduler loads skills before passing them to this function.
The ChainContext dataclass in agent_tools.py includes a skills field. When a chained reminder calls follow_up_chain, the tool forwards skill names via --skills CLI arguments to the next link in the chain. This means a reminder chain that starts with skills continues using those skills through every follow-up.
read_skill() resolves the skill path and verifies it stays within the skills/ directory, catching both path traversal sequences (e.g., ../../etc/passwd) and symlink escapes.

Next steps