# `mix precompiled.bundle`
[🔗](https://github.com/TomHoenderdos/elixir_precompiled/blob/v0.2.1/lib/mix/tasks/precompiled.bundle.ex#L5)

Writes a bundle a device installs from with no network:
`Precompiled.install(:recon, source: "file:///media/usb/precompiled")`.
It plans on this host exactly as the device would, from the device's
facts, and copies only what that plan needs.

    mix precompiled.bundle PKG[@REQ]... --out DIR (--system NAME@VSN | --pure) \
      --otp N --elixir V [--cpu C] [--source URL] [--root FILE]
    mix precompiled.bundle PKG[@REQ]... --out DIR --device-report FILE \
      [--source URL] [--root FILE]

`DIR` (new, or empty) gets the API's own layout:

  * `root.json` - the root the batch verified under: the source's served
    root when it chains from the trusted one, else the trusted root
    itself (`--root`, or the root this library ships);
  * `batch.json` - the signed batch, byte for byte as verified;
  * `v2/manifests/<pkg>.json` - for each planned package, the exact bytes
    the batch's hash names (`manifests/<pkg>.json` for a format-1 one);
  * `files/<sha256>` - every file of every planned build.

Every byte is checked against its signed hash before it is written, and
the bundle appears in `DIR` only once all of it has been. No key, and
nothing that is not in the plan, is ever written.

The device facts come from the flags: `--system` (or `--pure` for a
device with no Nerves system, which takes `pure_elixir` builds only),
`--otp`, `--elixir` and `--cpu` (default `aarch64-unknown-linux-gnu`),
with `kernel`, `stdlib`, `elixir`, `logger` and `crypto` present. Or they
come from `--device-report FILE`, the JSON that
`Precompiled.install(..., dry_run: true, report: path)` writes on the
device: its system, OTP, Elixir, CPU and present apps, so the bundle
holds what that device would fetch. With it, `--system`, `--pure`,
`--otp`, `--elixir` and `--cpu` are ignored. Apps the device has, by
name and exact version, are not bundled. The device checks everything
again when it installs.

`--source` is the API root (default the official one) and `--root` the
trust anchor (default the shipped `root.json`).

A bundle's `batch.json` expires 24 hours after it was issued. For a
device that stays offline longer, the holder of the root's `offline` key
signs the bundle with `mix portal.precompiled.sign_offline`, within a day
of the batch's issue, passing the current production `root.json` as
`--root`: the bundle's `root.json` must be that root.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
