---
title: Routine kinds
description: Code, skill, workflow and hybrid routines. What each kind is, how it maps to the real fields, and how to pick one.
sidebar:
  order: 1
---

## What it is

A routine kind describes **where a routine's work happens**: in scripts, in a skill, in a chain of stages, or split between code and the model. It is a design pattern, not a field. Nothing in `routine.toml` says `kind = "hybrid"`.

The fields that do exist are:

| Field | File | Values | Decides |
|---|---|---|---|
| `type` | `routine.toml` `[routine]` | `serverless`, `watch`, `approval-gated`, `interactive` | Who watches it, and whether it has a Desk and a gate |
| `delivery` | `app.toml` `[[routine]]` | `repo` (default), `account-skill`, `inline` | How the live routine gets its logic |
| stage `kind` | pack `stages` (since 0.6.0) | `code`, `model`, `skill`, `gate` | What each step of a packed routine is |

A kind is a way of combining these.

| Kind | Work happens in | Typical delivery | Example |
|---|---|---|---|
| [Code](/routine-kinds/code) | `lib/` scripts; the model only runs commands and reports | `repo` | A weekly report that counts and compares numbers |
| [Skill](/routine-kinds/skill) | A skill folder the run loads | `repo` or `account-skill` | Inbox triage with a reply-style skill |
| [Workflow](/routine-kinds/workflow) | A declared chain of stages | `repo` | A pack with fetch, judge, gate and write stages |
| [Hybrid](/routine-kinds/hybrid) | Code for rules, the model for reading and judging | `repo` | Hiring Signals (jobs-watch) |

## Why it exists

"Should this be code or a prompt?" is the first design question for every routine, and the answer differs per routine. A script that filters by market gives the same answer every run. A model that decides whether a role is a real lead needs to read. Getting the mix wrong costs either tokens (the model doing arithmetic) or quality (a regex judging fit).

## How it works

### The right mix

The design step states the mix per routine and the reason:

- Moves and filters structured data (fetch, filter, dedupe, count): scripts in `lib/`, zero model tokens for those steps.
- Reads, writes or judges (triage, summarising, drafting, research): the model.
- Plainly mechanical, repeated steps: code is suggested with the saving shown. The person decides.
- Budget check, gates and secrets handling always use a fixed mechanism. That is a safety rule, not a style choice.

And per rule:

- **Code:** settings filters, caps, ids, keys and times.
- **Judgement:** fit, classification, summaries, drafts.
- **A rule a person edits in Settings is always code.** If the model applied it, an edit on the Desk would not reliably change the run.

### Where the logic lives

Local files are always built first (`prompt.md`, scripts, any skill folder). `delivery` only decides how the live routine gets them.

| Delivery | How | Status |
|---|---|---|
| `repo` | The run clones a GitHub repo; skills under the repo's `.claude/skills/` come along. Needs `repo = "owner/name"` | Default. Proven end to end in a pilot (registry `repo-delivery`) |
| `account-skill` | The skill is uploaded to the person's claude.ai account and synced into each cloud session. Needs `skill` | Docs-based. The person uploads it; RoutineOS does not |
| `inline` | The prompt alone carries the logic | A repo-less routine was created and ran in a pilot (registry `repo-less-routine`) |

Skills kept only in `~/.claude/skills/` on one machine do not exist in a cloud run.

### The threat check

Every design is asked three questions: does it see private data, does it read content strangers control, and does it send things out? If all three are yes, the design says so plainly and recommends a split:

1. One routine reads untrusted content and has no send tool.
2. A second acts only on approved, structured output, behind a gate.

That is a recommendation. If the person keeps the combined design, the decision goes into `risks.md` with the date, and every external send keeps a gate. Every prompt treats fetched and stored text as data, and attaches only the connectors it needs.

## Worked example

Hiring Signals is `type = "watch"` with a gate, `delivery = "repo"`, and is a hybrid: the model searches and reads job pages; code applies `markets`, `title_keywords` and `excluded_companies`, computes ids, counts outcomes and writes the store. It reads public pages strangers control and sees no private data, and its only external action (an intro note) goes through an email gate. The threat check passes without a split.

## Common pitfalls

- **Looking for a kind field.** There is none. Set `type`, `delivery` and, in a pack, stage kinds.
- **A Settings rule applied by the model.** In a pilot the model kept two "Ecommerce" roles for the keyword `commerce` and the write script dropped them, because the script matched whole words. Put the rule in code so the Desk edit means what it says.
- **A skill only on your laptop.** Use `repo` or `account-skill`.

## Related

- [Routines](/concepts/routines)
- [Stages](/concepts/stages)
- [Scheduling and Claude cloud routines](/infrastructure/scheduling)
