# `mix mob.new_plugin`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mix/tasks/mob.new_plugin.ex#L1)

Generates the skeleton for a new mob plugin under `plugins/<name>/`.

    mix mob.new_plugin <name> [--tier <0|1|2|3|4>] [--dest <DIR>]

Tiers (per [`MOB_PLUGINS.md`](https://github.com/GenericJam/mob/blob/master/MOB_PLUGINS.md)):

- `0` (default) — pure-Elixir helpers. No manifest, no native code.
- `1` — native NIF + Elixir wrapper. Manifest with `:nifs`; ships an Erlang
  NIF stub and the matching C source. Wired into the build by
  `MobDev.Plugin.Merge.nifs/1` + the build.zig `-Dplugin_c_nifs` arg.
- `2` — native UI component via `Mob.UI.native_view` + `Mob.Component`.
  Manifest with `:ui_components`; ships an Elixir `Mob.Component` module,
  the matching Kotlin Composable, and a Swift View placeholder.
- `3` — multi-screen plugin. Manifest with `:screens` + `:migrations` (and
  optionally `:assets`); ships two `Mob.Screen` modules and an Ecto migration
  the host applies on device.
- `4` — embedded sub-app. Manifest with `:lifecycle` + `:settings` +
  `:notifications`; ships a lifecycle module, a supervised worker, a
  notification handler, and a settings editor screen.

## Signing (tiers 1–4)

A plugin with a manifest is verified by every host before its native build
uses it: `priv/mob_plugin.sig` must be a v2 signature over every file the
build reads (`MobDev.Plugin.Sign.build_inputs/2`), made with the key whose
public half is `priv/mob_plugin.pub`, and the host must trust that key. So
tiers 1–4 also get:

- `.gitignore` ignoring `priv/mob_plugin.sig` (`priv/mob_plugin.pub` is
  committed);
- `mix.exs` with Hex package metadata (`package files:` ship all of
  `priv/`; set `@source_url` to the plugin's repository) and a dev-only
  `:mob_dev` dep for the signing tasks, plus a `README.md` and the
  `CHANGELOG.md` the release notes are taken from;
- `.github/workflows/release.yml`: on a `version:` bump in `mix.exs` it tags,
  creates the GitHub Release, checks that the `MOB_PLUGIN_SIGN_KEY` secret
  derives the committed public key, runs `mix mob.validate_plugin` and
  `mix mob.plugin.sign`, then `mix hex.publish`. The published package
  therefore carries a fresh signature over exactly what ships.

One-time setup, in the plugin directory:

    mix deps.get
    mix mob.plugin.keygen      # priv/mob_plugin.pub + ~/.mob/keys/<name>.priv
    gh secret set MOB_PLUGIN_SIGN_KEY < ~/.mob/keys/<name>.priv
    gh secret set HEX_API_KEY

`mix mob.plugin.sign` signs locally for testing; a host records trust with
`mix mob.plugin.trust <name>`. Tier 0 has no manifest and nothing to sign.

## Options

  * `--tier <0|1|2|3|4>` — plugin tier; defaults to `0`.
  * `--dest <DIR>` — destination directory; defaults to `plugins/<name>`
    relative to the current working directory.

---

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