Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Routines

A routine is a prompt Kimaki runs on a schedule: once at a future time, or again and again on a cron expression. The bot wakes up, does a job, and posts the result as a Discord thread you can reply to.

Scheduling with --send-at

Add --send-at to a kimaki send command. It accepts a one-time UTC ISO timestamp (ending in Z) or a cron expression:
# One-time: run at a specific UTC time kimaki send --channel <channel-id> --prompt 'Review open PRs' \ --send-at '2026-03-01T09:00:00Z' # Recurring: every Monday at 9am UTC kimaki send --channel <channel-id> \ --prompt 'Run the test suite and summarize failures' \ --send-at '0 9 * * 1'
The Kimaki bot must run on the machine that owns the channel. It stores the routine in its SQLite database and checks for due routines about every 5 seconds. If a cron routine misses runs while the bot is off, it runs once when the bot starts again.
With --channel (or --project), each run starts a new thread. With --thread (or --session), each run sends the prompt into that existing thread, shown as » routine #N: <prompt>.
All scheduling is in UTC. One-time dates must end with Z, and cron expressions fire in UTC too. Convert from your local time before scheduling.

Flagship example: a morning email digest

The pattern that makes routines shine: a morning email digest you can act on from Discord.
cron 0 7 * * * │ ▼ ┌─────────┐ ┌──────────┐ ┌───────────┐ │ read │ ───▶ │ post │ ───▶ │ you reply │ │ inbox │ │ digest │ │ (mark) │ └─────────┘ └──────────┘ └───────────┘
Schedule a routine that reads your inbox each morning with a CLI like Zele (a multi-account email and calendar CLI) and posts a summary:
kimaki send --channel <channel-id> \ --prompt 'Use the zele CLI to read my unread emails. Post a concise digest grouped by sender and importance. List the message IDs so I can act on them.' \ --send-at '0 7 * * *'
When the digest lands as a thread, reply to it to resume the work: "mark the GitHub ones as read and unsubscribe from the newsletters." The agent runs the corresponding zele commands. The whole loop, read then act, happens from one Discord thread.

Notify-only reminders

For a reminder that should not start an AI session, add --notify-only. It posts the prompt as a new thread in the channel. --notify-only needs --channel or --project, not a thread:
kimaki send --channel <channel-id> \ --prompt 'Reminder: <@user-id> the staging API key created today expires 2026-06-01. Renew it before it breaks prod.' \ --send-at '2026-05-28T09:00:00Z' --notify-only
Make reminder prompts detailed: the future reader has no context, so include what, when, why, and the exact action needed.

Other recurring patterns

  • Weekly QA: run the full test suite, summarize failures, mention a user only if review is needed.
  • Maintenance cron: rotate secrets, check dependency updates, clean stale branches on a 0 9 1 * * monthly schedule.
  • Project memory: have the routine read and update a markdown file in the repo each run.
Most other send flags (--notify-only, --worktree, --base-branch, --cwd, --name, --agent, --model, --user, --permission) work with --send-at. Two do not:
  • --wait: the routine runs in the future.
  • --file: put the file in the project and name it in the prompt.
With --worktree, each run gets a fresh worktree with its own name.
Pass --user when someone should see the thread in Discord. Omit it for quiet autonomous work so the thread stays out of the sidebar. Clear a stored user later with kimaki routine edit <id> --user ''.

Run only when needed

Use --pre-run to run a shell command in the project directory before a scheduled occurrence starts. This example uses crisp-cli to start a support session only when Crisp has unread customer messages.
Create scripts/should-run-support.ts:
#!/usr/bin/env bun import { $ } from 'bun' type Conversation = { session_id: string unread?: { operator?: number } preview_message?: { from?: string } } const output = await $`crisp-cli list_website_conversations`.text() const response = Bun.YAML.parse(output) as { items?: Conversation[] } const requests = (response.items ?? []).filter((conversation) => { return ( (conversation.unread?.operator ?? 0) > 0 && conversation.preview_message?.from === 'user' ) }) const sessionIds = requests.map((conversation) => conversation.session_id) if (sessionIds.length === 0) process.exit(1) console.log(Bun.YAML.stringify({ sessionIds }))
The unread operator count means the support team has not read the message. The from: user check excludes operator replies. Install and configure the CLI once before scheduling:
pnpm add -g crisp-cli crisp-cli config --token '<crisp-mcp-token>'
Then schedule the check every five minutes:
kimaki send --channel <channel-id> \ --send-at '*/5 * * * *' \ --pre-run 'bun scripts/should-run-support.ts' \ --prompt 'Read the Crisp session IDs in the pre-run output. Use crisp-cli to inspect each conversation and draft a support reply.'
An exit code of 0 starts the session. Kimaki appends the command's stdout to the routine prompt under a ## Pre-run command output heading. Any other exit code skips that occurrence. Stderr goes to the Kimaki log. A pre-run command is stopped after 10 minutes.
Routines do not overlap by default. If the session of the last run is still active, a cron routine skips that occurrence and runs again at the next scheduled time. A one-time routine waits until the last session is done. Add --allow-concurrency only when parallel runs are safe.

Managing routines

kimaki routine list kimaki routine edit <id> --prompt 'new prompt' [--send-at 'new schedule'] \ [--agent <name>] [--model <provider/model>] [--pre-run 'command'] \ [--allow-concurrency true|false] [--user '<discord-user-id>'] kimaki routine edit <id> --user '' kimaki routine run <id> kimaki routine delete <id>
kimaki routine list shows planned, running, and failed routines. An empty string in routine edit clears a value. routine run starts a routine now, outside its schedule. Routines were called scheduled tasks before; the old kimaki task commands still work.
The /routines slash command lists the server's routines in Discord. Each routine has a Run now button and a Delete button. For the full kimaki send reference and CI usage, see CI & Automation.