Skip to main content

Usage

Adds the named facets to facets.json and installs them into every connected adapter. There is no separate install step afterwards. Specifiers are validated before anything touches disk. If the project has no adapter, a terminal gets the picker and a non-interactive run fails pointing at facet adapter add. From there the run is an ordinary install, so it reports the same outcomes and can meet the same collision and MCP approval screens. A facet whose only asset is an MCP server is valid: it configures servers and writes no files. A facet that composes other facets with a non-empty facets array is rejected.

Examples

Flags

boolean
Show detailed step output on stderr. Declaration contents never appear here. See where declarations appear.
boolean
Approve the MCP configuration this run would write, without prompting.

Exit codes

Nothing is written unless the run had already started writing, in which case it is rolled back.

Details

Source grammar

Registry names

Git and GitHub sources

A git source is cloned and built locally, so git must be on your PATH.

Local paths

A ~ is not expanded by the CLI. Let your shell expand it, and remember the result still has to sit inside the project tree.

Forms that are rejected

Re-adding a facet

Re-adding pins one facet to a version you name. To move every declared facet to newer releases, use facet update instead.
  • Same source: a no-op, reported as unchanged or repaired. If you aliased or omitted one of its contributions since, it reports updated.
  • Different version: updates the entry and counts under N updated. Per-facet version transitions are printed by facet update.
  • Bare re-add: resolves the newest release and pins it, even over an existing wildcard.
  • Explicit @latest or wildcard: re-resolves to the newest match and keeps floating.
Recorded materialization overrides are preserved across a re-add, for text assets and servers alike. An override naming something the new version no longer contains is dropped, and the install tells you which. Under --frozen-lockfile that same stale override is blocking drift instead. What gets written per specifier shape is defined by the manifest write policy. A successful non-frozen add also stamps "manifestVersion": 0.2.

Troubleshooting

Cause: the specifier does not match the source grammar. Every specifier is parsed before any network or disk work, so the run stops with the project untouched.Fix: the error names the offending specifier and the accepted forms. See forms that are rejected for the common substitutions.
Cause: a git or GitHub source is cloned locally, and git was not found on your PATH.Fix: install git, or add the facet from the registry or a local path instead.
Cause: the repository is private, or the clone prompted for credentials.Fix: configure git authentication for the repository, or use a public one. Interactive credential prompts are not supported during a clone.
Cause: the branch, tag, or commit named after # does not exist in the cloned repository.Fix: correct the ref, or drop it to use the default branch.
Cause: a local source must resolve inside the project tree, so a facet cannot be installed from an arbitrary location on your machine.Fix: move or copy the facet into the project, then add it by a path inside the tree.
Cause: the source declares a non-empty facets array. Composition is reserved in the manifest format and is not installable yet.Fix: ask the publisher for a release that ships its own assets directly. There is no flag to install it as-is.
Cause: the clone or directory resolved, but its facet.json did not load, its name disagreed with what you asked for, or the build failed.Fix: run facet build --verify inside that source to see the validation errors, then fix and re-add.

See also