- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
call_tool() already returns str, so the str() wrapper was unnecessary. Added type: ignore for mypy's no-any-return. Closes #146 |
||
| .forgejo/workflows | ||
| docs | ||
| src/kronai | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| kronai.toml.example | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| requirements-dev.txt | ||
| requirements.txt | ||
| ROADMAP.md | ||
KronAI
AI-powered cron job scheduler. KronAI watches a jobs directory, discovers job configurations, and sends prompts to LLM APIs (OpenAI-compatible) on a schedule. Supports MCP (Model Context Protocol) servers for tool-augmented completions.
Installation
pip install kronai # Not yet on PyPI — install from source below
Or from source:
git clone https://git.lan.thwap.org/thwap/kronai.git
cd kronai
python -m venv .venv
source .venv/bin/activate
pip install -e .
Quick Start
1. Create a jobs directory
/var/lib/kronai/jobs/
hourly/
1/
prompt.md # The prompt to send to the LLM
config.toml # Optional job config
name # Optional human-readable name
description # Optional description
2. Write a prompt
What is the current weather in San Francisco?
3. Run it
# Run a single job by ID
kronai run 1
# Run all hourly jobs
kronai hourly
4. Schedule with cron
0 * * * * kronai hourly >> /var/log/kronai/cron.log 2>&1
0 3 * * * kronai daily >> /var/log/kronai/cron.log 2>&1
See docs/cron-integration.md for systemd and detailed cron setup.
Configuration
Search paths (first found wins):
/etc/kronai/config.toml~/.config/kronai/config.toml./kronai.toml--config PATHflag
Example kronai.toml
jobs_dir = "/var/lib/kronai/jobs"
log_dir = "/var/lib/kronai/logs"
log_level = "INFO"
json_logs = false
# log_max_bytes = 10485760
# log_backup_count = 5
llm_endpoint = "https://api.openai.com/v1"
llm_api_key = "sk-..." # Or set via env
default_model = "gpt-4o"
default_temperature = 0.7
default_max_tokens = 2048
[mcp_servers]
# [mcp_servers.filesystem]
# command = "npx"
# args = ["-y", "@modelcontextprotocol/server-filesystem"]
Job-specific config.toml
Placed inside a job directory, overrides global config:
model = "gpt-4o-mini"
temperature = 0.3
max_tokens = 1024
system_prompt = "You are a helpful coding assistant."
mcp_servers = ["filesystem"]
env = { DEBUG = "true" }
Usage
kronai list # List all jobs with IDs, names, descriptions
kronai run <id|name> # Run a job by numeric ID or symlink name
kronai hourly # Run all hourly jobs
kronai daily # Run all daily jobs
kronai weekly # Run all weekly jobs
kronai monthly # Run all monthly jobs
kronai --config PATH # Use explicit config file
kronai --log-level DEBUG # Override log level
Job Directories
Structure
jobs/
hourly/
1/
prompt.md # Required: prompt text
config.toml # Optional: job-specific config
name # Optional: human-readable name
description # Optional: description (shown in list)
.ephemeral # Optional: marker for run-once jobs
.recurring # Optional: marker for persistent jobs (default)
my-report -> 1/ # Symlink: named alias to job ID
daily/
1/
prompt.md
Symlinks for Naming
Create symlinks in the interval directory to give jobs friendly names:
ln -s 1 /var/lib/kronai/jobs/hourly/my-report
Then run by name:
kronai run my-report
Job Types
- Recurring (default): Job persists after running. Results saved to
results/TIMESTAMP/output.md. - Ephemeral: Job directory is deleted after successful run. Add a
.ephemeralmarker file:
touch /var/lib/kronai/jobs/hourly/1/.ephemeral
MCP Servers
KronAI supports MCP servers for tool-augmented LLM completions. Configure servers in kronai.toml and reference them in job configs.
[mcp_servers]
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem"]
In your job's config.toml:
mcp_servers = ["filesystem"]
Logging
- Console output to stderr
- File logging with rotation to
{log_dir}/kronai.log - JSON structured logs via
json_logs = true - Configurable via
log_level,log_max_bytes,log_backup_count
API
Supported LLM APIs
Any OpenAI-compatible API endpoint:
- OpenAI
- Anthropic (via API proxy)
- Local models (Ollama, vLLM, LM Studio, etc.)
- Azure OpenAI
Set the endpoint and key in config:
llm_endpoint = "http://localhost:11434/v1" # Ollama example
llm_api_key = "" # Not needed for local
default_model = "llama3"
Development
git clone https://git.lan.thwap.org/thwap/kronai.git
cd kronai
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pre-commit install
pytest
License
MIT — see LICENSE. Copyright (c) 2026 T.H.W.A.P. Labs and Mike 'Fuzzy' Partin.