Third-party features
Anyone can publish features for mfeflow, and you can install them from any registry you trust. A third-party feature is a feature.json on a static site, so there is no server to run and nothing that executes on your machine.
What you get
A registry is a folder of static files. You add it under a namespace like @acme, and its features install the same way as the built-in ones.
A third-party feature is declarative. It lists files, dependencies, script names and edits made by a fixed set of built-in operations. It never runs code: not at install, not in a hook, not in a migration. pnpm mfeflow add shows the plan and the diff before it writes anything, and without a terminal it needs --yes to apply a registry feature at all.
Add it
Register the site once, then install from it:
This command lists the registry's features next to the first-party ones:
What changes in your project is whatever the feature's feature.json declares. Your mfeflow.json also gets a registries entry.
Use it
Manage registries
registry add takes --dry-run and --json. To find a feature, search by name, description or keyword:
It reads every registry's index at the same time, so one slow registry does not delay the rest. It lists source, name, version and description.
A registry that cannot be read is reported with MFEFLOW_E401, or E403 for a bad index. The rest are still listed and the command exits 0.
With --json, each feature has a source, and every registry gets one status:
Write a feature
One folder per feature, each with a feature.json:
A third-party feature may use only these top-level fields:
Anything else, such as migrations, hooks or unknown keys, is refused with MFEFLOW_E203.
A target is the shell, all remotes, or one app's name:
Publish a registry
registry build checks every feature.json the way add @namespace/name will, then writes the files to host:
These flags change the build:
The build writes nothing when any feature fails, and it reports every failure in one go:
It also needs one namespace per registry, one folder per feature name, a semver version, a description, and no feature called index.
Host it on GitHub Pages
- Put the features in a repository, one folder each.
- Build into a folder Pages serves, here
docs/. - Commit it, then publish Pages from the
mainbranch and the/docsfolder in the repository settings. - Users add your registry with its URL.
The commands for steps 2 and 4:
Any static host works the same way: S3, R2, Netlify or your own nginx. A GitHub Action that runs registry build and deploys the output keeps it fresh on every push.
Try it before it is hosted
Switch the registry to its https URL before you commit mfeflow.json: run registry remove, then registry add.
Configure it
Registry rules
Trust a registry
Anyone who clones your repo also gets the registries listed in mfeflow.json. So mfeflow asks nothing of a registry until you trust it on your own machine.
Adding a registry trusts it, because you typed the address:
A registry that only came in with a cloned repo shows as "not trusted yet". Check its address, then trust it:
Trust covers the namespace and its exact URL. If someone changes the URL in mfeflow.json, you are asked again. mfeflow registry untrust @acme takes it back.
mfeflow records a hash of each registry feature when you add it. If the registry later serves different content, add remote and add shell stop with MFEFLOW_E406. Read what changed, then run again with --accept-changed-content.
Packages a registry feature adds are listed under NEW PACKAGES in the plan. Look at each one: npm and yarn run install scripts, pnpm 10 and later blocks them until you allow them.
Tokens in a registry URL are shown as *** in output, but they stay in mfeflow.json as written. Keep secrets out of files you commit.
The index
index.json sits in the folder the URL template starts in, before the first path segment with a placeholder:
The name has no namespace, because the registry's namespace goes in front: @acme/segment. Descriptions are plain text of at most 300 characters, with at most 20 keywords of 40 characters, at most 1000 items, and a file of at most 1 MB. Control characters are refused, so an index cannot write escape sequences to your terminal. The schema is at /schema/feature-registry-index.json.
What a feature may contain
How it works
A feature that breaks a rule fails with MFEFLOW_E203 and a message naming the file or field and the rule. Nothing is written. A transform operation that does not exist is MFEFLOW_E204. If you need an operation that is not in the list, open an issue: the operations are a public API, not an escape hatch.
Versions
Versions are semver, and your mfeflow.json records the version that was installed. Build into the same folder, or keep it under version control, and each release adds one file.
Adding a remote or shell later applies the installed registry features to the new app again, at the recorded version. If the registry now serves another version and your template has no {version}, add stops with MFEFLOW_E401 before writing anything.
A template with a version placeholder keeps working across releases, which is why the build writes both forms:
Gotchas
Do not delete old output from the folder you publish. A published <name>/<version>.json should never change, and users on that version need it. Publish a new version instead.
- Plain http is for this machine only. Any other http address, such as a LAN IP or a lookalike host name, is refused.
- A registry in use cannot be removed. Features installed from it are fetched again when you add a remote or shell.
- Review before you apply. Read the plan and the diff
addshows. Without a terminal,--yesskips that, so use it only for a registry you trust.
Reference
- Third-party features, the idea
- feature.json, the full manifest format
mfeflowCLI reference- Adding features
- E203, E204, E207, E401, E403 and E404