---
title: Templates and packs
description: Start a routine from a bundled template or a routine pack. What a pack is, the ten shipped packs, maturity, and what a pack can never do.
sidebar:
  order: 1
---

> Packs since 0.6.0. Bundled templates (`new --from-template`) work in 0.4.0 and later.

## What it is

- A **template** is a routine folder bundled with the plugin (`templates/jobs-watch`, `templates/watch`). `new --from-template` copies it.
- A **pack** is one JSON file (`routineos.pack.v1`) that holds a whole routine: `routine.toml` as data, the prompt, the README, the definition, the declared stages and connectors, and any `lib/` scripts or skills. It can be validated, installed from a file or an https URL, exported from any routine folder, and listed in a catalog.

## Why it exists

A good routine is worth reusing. A pack makes one shareable as a single file that can be checked before install, never runs code on install, carries no secrets, and tells the person exactly what to connect.

## How it works

### From a bundled template

```
python3 skills/routineos/scripts/routineos.py new hiring-signals --from-template jobs-watch
```

### From a pack

```
python3 skills/routineos/scripts/routineos.py pack validate jobs-watch.pack.json
python3 skills/routineos/scripts/routineos.py pack install jobs-watch.pack.json --name hiring-signals
```

See [Install a pack](/templates/install).

### The shipped packs

| id | type | Code stages | Skill stage | Gate | Maturity |
|---|---|---|---|---|---|
| `jobs-watch` | watch | `learn`, `write` | none | email, 48 hours | piloted |
| `watch` | watch | `learn` | none | off by default | piloted |
| `meeting-brief` | watch | `write` | none | no | unpiloted |
| `weekly-marketing-report` | watch | `lib/week_over_week.py`, `write` | none | no | unpiloted |
| `inbox-triage` | approval-gated | `write` | `reply-style` | before any send | unpiloted |
| `support-gap-digest` | watch | `lib/group_questions.py`, `write` | none | no | unpiloted |
| `invoice-exceptions` | watch | `lib/invoice_checks.py`, `write` | none | no; never pays | unpiloted |
| `candidate-shortlist` | watch | `lib/score_rubric.py`, `write` | none | no; never rejects | unpiloted |
| `content-calendar` | approval-gated | `lib/check_citations.py`, `write` | `house-style` | before any post | unpiloted |
| `engineering-digest` | watch | `lib/stale_items.py`, `write` | none | no | unpiloted |

`maturity` is `piloted` only for a pack that has run for real. Everything else is `unpiloted`, and says so.

### What a pack never does

- Runs code on install. `lib/` files are written, never executed.
- Fetches any URL but the one given.
- Holds a secret, an email address or a Slack-style id. Validation scans for them.
- Writes a people collection (`decisions`, `settings`, `merges`, `userstate`, viewer state).
- Ships with `first_run = "live"`. A person switches a routine live.
- Overwrites a folder.
- Ships the Desk as HTML. Install writes the bundled Desk.
- Includes the app layer. Run `app-init` afterwards.

## Worked example

Installing `jobs-watch` as Hiring Signals writes six files (`README.md`, `dashboard/index.html`, `definition.json`, `pack.json`, `prompt.md`, `routine.toml`) and prints a connector report. From there it is the same routine as one made with `new --from-template`.

## Common pitfalls

- **Treating `unpiloted` as tested.** It validated; it has not run for real.
- **Expecting install to connect things.** It reports what to connect; you connect it.

## Related

- [Install a pack](/templates/install)
- [Writing a pack](/templates/writing-a-pack)
- [Pack schema](/reference/pack-schema)
