diff --git a/enroll-manifest.md b/enroll-manifest.md
new file mode 100644
index 0000000..47251bc
--- /dev/null
+++ b/enroll-manifest.md
@@ -0,0 +1,186 @@
+# enroll manifest
+
+Generate an Ansible "manifest" (roles/playbooks, and optionally inventory) from an existing harvest bundle.
+
+---
+
+## Synopsis
+
+```bash
+enroll manifest --harvest
--out [--fqdn ] [--jinjaturtle | --no-jinjaturtle] [--sops ]
+```
+
+---
+
+## Inputs
+
+### `--harvest ` (required)
+Path to the harvest input.
+
+- **Plain mode (no `--sops`)**
+ - must be a **directory** created by `enroll harvest` (containing `state.json`, `artifacts/`)
+
+- **SOPS mode (`--sops ...`)**
+ - may be either:
+ - a **directory** (already decrypted), or
+ - a **SOPS-encrypted harvest tarball** produced by `enroll harvest --sops` (e.g. `harvest.tar.gz.sops`)
+
+---
+
+## Outputs
+
+### Plain mode output (directory)
+In plain mode, `--out` is a directory that is written in-place.
+
+#### Default (single-site mode, no `--fqdn`)
+Typical top-level layout:
+
+- `roles/`
+- `playbook.yml`
+
+#### Site mode (`--fqdn `)
+Adds inventory scaffolding and per-host files:
+
+- `roles/`
+- `inventory/hosts.ini`
+- `inventory/host_vars//...`
+- `playbooks/.yml`
+- `ansible.cfg`
+
+In site mode, some raw harvested files are stored under:
+`inventory/host_vars///.files/...`
+to avoid cross-host clobber while still sharing role code.
+
+### SOPS mode output (single encrypted file)
+When `--sops ` is set, the manifest output is bundled and encrypted into one file:
+- `manifest.tar.gz.sops`
+
+`--out` may be:
+- a directory - `manifest.tar.gz.sops` is created inside it
+- a file path - that exact filename is written
+
+---
+
+## Options
+
+### `--out ` (required)
+Where to write the manifest output.
+
+- **Plain mode**: must be a directory path (created if needed).
+- **SOPS mode**: may be a directory or a file path (see above).
+
+### `--fqdn `
+Enable "site mode" output.
+
+- Generates `inventory/`, `inventory/host_vars//...`, and `playbooks/.yml`. This includes the `inventory/hosts.ini` with the fqdn inside it.
+- Generates an `ansible.cfg` with some nice defaults for running against multiple remote hosts.
+- Useful when you are enrolling multiple hosts into a shared repo layout
+
+If `--fqdn` is omitted (or empty), the manifest is generated in "single-site mode" with `playbook.yml`, and no inventory files (all role parameters are stored in `defaults/main.yml` in the roles) or `ansible.cfg`. In that scenario, you are responsible for creating the `inventory` file or using `-i`.
+
+If you *do* include `--fqdn`, and run the command repeatedly against different harvests but with the same `--out` param, Enroll will 'merge' the new host's inventory, roles, and playbooks into your manifest directory, as opposed to **overwrite** it.
+
+Therefore, if you keep running `harvest` against all your hosts, you can gradually assemble a 'complete' manifest of all roles/playbooks/inventory of all hosts!
+
+### JinjaTurtle integration
+
+#### `--jinjaturtle`
+Force JinjaTurtle templating integration **on**.
+
+- Errors if `jinjaturtle` is not available on `PATH`.
+
+#### `--no-jinjaturtle`
+Force JinjaTurtle integration **off**, even if it’s installed.
+
+#### Default (no flag)
+Auto mode: use JinjaTurtle if found on `PATH`, otherwise do not.
+
+### `--sops `
+Enable SOPS mode for manifest generation.
+
+In this mode:
+1) If `--harvest` is an encrypted file, `enroll` decrypts and extracts it (using `sops -d`) to a secure temp directory.
+2) It generates the manifest into a secure temp directory.
+3) It bundles (tar.gz) and encrypts the entire manifest output into `manifest.tar.gz.sops`.
+
+Requires `sops` available on `PATH`.
+
+---
+
+## Permutations (valid combinations)
+
+### Plain + single-site (default; JinjaTurtle auto)
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/ansible-dir
+```
+
+### Plain + site mode (`--fqdn`)
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/ansible-dir --fqdn host.example.com
+```
+
+### Plain + disable JinjaTurtle
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/ansible-dir --no-jinjaturtle
+```
+
+### Plain + force JinjaTurtle on
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/ansible-dir --jinjaturtle
+```
+
+---
+
+### SOPS output (manifest encrypted), harvest input is a directory
+Output to a directory (default filename inside):
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/out-dir --sops
+# writes /path/to/out-dir/manifest.tar.gz.sops
+```
+
+Output to a specific file:
+```bash
+enroll manifest --harvest /path/to/harvest-dir --out /path/to/manifest.tar.gz.sops --sops
+```
+
+### SOPS output, harvest input is an encrypted file
+```bash
+enroll manifest --harvest /path/to/harvest.tar.gz.sops --out /path/to/out-dir --sops
+```
+
+### SOPS output + site mode (`--fqdn`)
+```bash
+enroll manifest --harvest /path/to/harvest.tar.gz.sops --out /path/to/out-dir --fqdn host.example.com --sops
+```
+
+### SOPS output + JinjaTurtle control
+Force on:
+```bash
+enroll manifest --harvest /path/to/harvest.tar.gz.sops --out /path/to/out-dir --sops --jinjaturtle
+```
+
+Force off:
+```bash
+enroll manifest --harvest /path/to/harvest.tar.gz.sops --out /path/to/out-dir --sops --no-jinjaturtle
+```
+
+---
+
+## Working with the encrypted manifest (`manifest.tar.gz.sops`)
+
+The encrypted manifest is one file; to use it with Ansible you typically:
+
+```bash
+mkdir -p /tmp/enroll-manifest && cd /tmp/enroll-manifest
+sops -d /path/to/manifest.tar.gz.sops | tar -xzvf -
+```
+
+After extraction, run Ansible from inside the extracted tree.
+
+---
+
+## Common gotchas
+
+- In **plain mode**, `--out` is written in-place. If you re-run against the same output directory, expect files to be updated/overwritten.
+- In **site mode**, host-specific state lives under `inventory/host_vars//...`; this is intentionally per-host.
+- In **SOPS mode**, the manifest is not directly runnable until you decrypt and extract it.