---
title: Install a pack
description: Validate and install a routine pack from a file or one https URL. Output, the connector report, renaming, and every refusal.
sidebar:
  order: 2
---

> Since 0.6.0.

## What it is

`pack validate` checks a pack. `pack install` validates it again, writes a routine folder from it, lints the folder, and prints what you must connect.

## Why it exists

A pack from someone else is untrusted. Validating before any file is written, refusing anything unsafe, and never running its code makes it safe to try.

## How it works

```
routineos.py pack validate <file-or-url> [--json]
routineos.py pack install <file-or-url> [--dir DIR] [--name NAME] [--json]
```

- **Source:** a local path, or one `https://` URL. Redirects are refused, the timeout is 20 seconds, no cookies or auth are sent, and the User-Agent is `routineos-pack/0.6.0`. A pack is at most 512 KiB.
- **Target:** `--dir`, else `./<id>`. It must not exist. Install writes a temporary sibling folder and renames it, so a failed install leaves nothing behind.
- **`--name`:** installs under a new routine name (lowercase letters, digits and hyphens, at most 64 characters). `workspace.template` keeps the source pack's id.
- **`--json`:** prints `{installed, files, lint, connectors}`, or for validate `{ok, problems}`.

Exit codes: 0 ok, 1 the pack or the installed folder has problems, 2 a usage or read error.

## Worked example

```
$ routineos.py pack validate jobs-watch.pack.json
ok: jobs-watch 0.1.0 is a valid pack

$ routineos.py pack install jobs-watch.pack.json --dir hiring-signals --name hiring-signals
installed hiring-signals 0.1.0 into hiring-signals (6 files)

Connectors for jobs-watch (hiring-signals)

Required:
  none

Optional:
  none

Nothing was connected for you, and the pack holds no secret. Connect each one yourself.
```

Installing again:

```
error: hiring-signals already exists, refusing to overwrite
```

A pack with problems, validated:

```
FAIL pack: unknown key 'colour'
FAIL routine.first_run must be report-only in a pack; a person switches a routine live
FAIL connectors[0]: a write connector needs routine.gate.enabled = true
FAIL prompt: contains an email address; people add addresses on the Desk
```

An `http://` source:

```
error: only https:// URLs or local file paths are accepted
```

### After install

1. Read `README.md` and the connector report. Connect what is required.
2. `routineos.py doctor hiring-signals` and `routineos.py permissions hiring-signals`.
3. `routineos.py app-init hiring-signals` for the app layer.
4. Publish the Desk and seed it, as in the [Quickstart](/introduction/quickstart).

## Common pitfalls

- **A redirecting URL.** Use the final URL.
- **Expecting install to fix a bad pack.** It refuses; fix the pack.
- **Running a pack's `lib/` script to "test" it.** Read it first. Install never runs it, and you should not either until you have.

## Related

- [Connectors in packs](/templates/connectors)
- [The catalog](/templates/catalog)
- [CLI reference](/reference/cli)
