Skip to main content

Usage

facet add <source> [more sources...]
Adds the named facet(s) to facets.json and immediately installs them into every connected adapter. There is no separate “install after add” step — facet add is the single command for bringing a new facet into a project. If the project has no adapters installed, facet add will launch the adapter picker before doing any work (in an interactive terminal). In a non-interactive environment, it exits with an error pointing at facet adapter install.

What it does

1

Parse

Validate every source specifier up front. Invalid grammar exits before touching disk.
2

Discover adapters

If none installed: launch the picker (TTY) or fail (non-TTY).
3

Prepare

Read each source’s facet.json to learn its name. Reject composition (facets: [...]). Load the project manifest if it exists.
4

Commit

Delegate to the install pipeline with the additions delta. Non-exact specifiers always re-resolve to the newest match. Exact versions with a warm cache skip the download entirely — but creating a new lockfile entry still requires one metadata call to confirm the content against the registry’s published integrity. Offline, that confirmation fails closed (“cannot create a lockfile entry without registry confirmation”) rather than writing an unconfirmed entry; reproducing an existing entry works fully offline.
The manifest, lockfile, and receipt are never written ahead of success. On failure, the journal rolls back all materialization and the project is left unchanged.

Source grammar

facet add accepts these source forms:
FormExampleNotes
Registry nameviper-plansEquivalent to viper-plans@latest. Resolved version is written back to facets.json (default-to-pinned).
Registry name with versionviper-plans@1.2.3Exact pin.
Registry name with @latestviper-plans@latestRe-resolves to the newest published version; latest is preserved verbatim in facets.json (the entry floats). Only a bare name pins.
Registry name with wildcardviper-plans@*, 1.*, 1.2.*Wildcard preserved in facets.json; resolved exact version goes in the lockfile.
Scoped registry name@scope/name, @scope/name@1.2.3, @scope/name@latest, @scope/name@1.*A scoped facet (@scope/name). The leading @ marks the scope; a trailing @ separates the version (so @scope/name@1.2.3 pins @scope/name to 1.2.3). Versioning and pinning rules are identical to unscoped names.
GitHub shorthandgithub:owner/repo, github:owner/repo#mainOptional #ref (branch, tag, SHA).
HTTPS git URLhttps://github.com/owner/repo.git#v1.0.0Must end in .git.
SCP-style git URLgit@github.com:owner/repo.git#mainStandard user@host:path SSH form.
Local path./facets/viper-plans, /abs/path, ~/fooMust resolve inside the project tree.
file: prefixfile:./facets/viper-plansTolerated; the prefix is stripped and the rest is treated as a local path.

Forms that are rejected

FormReason
git+https://..., git+ssh://...The git+ prefix is not supported. Drop it: https://...git, git@host:owner/repo.
^1.2.3, ~1.2.3Caret/tilde ranges. Use 1.* for major-pinned, 1.2.* for minor-pinned, or 1.2.3 for exact.
>=1.0.0, <2.0.0, 1.0.0 || 2.0.0Comparator and OR ranges. Pick one version.
1.x, 1.2.xx-style placeholders. Use 1.* or 1.2.* instead.

Examples

# Bare name  -- resolves to the latest published version, writes the
# exact resolved version back to facets.json.
facet add viper-plans

# Pinned version  -- written verbatim to facets.json.
facet add viper-plans@1.2.3

# Major-pinned wildcard  -- wildcard preserved, lockfile records the
# specific resolved version.
facet add viper-plans@1.*

# Scoped facet  -- the leading @ is the scope; an optional trailing
# @version pins it (e.g. @acme/deploy-tools@1.2.3).
facet add @acme/deploy-tools

# GitHub shorthand with a ref.
facet add github:agent-facets/viper-plans#main

# Local path under the project tree.
facet add ./local-facets/my-plans

# Multiple sources in one command.
facet add viper-plans rezi planner@2.*

Re-adding a facet

Running facet add against a facet that’s already in facets.json is supported:
  • Same source as before → no-op (lockfile may report unchanged or repaired).
  • Different version pin → updates the entry; the install summary shows (was X → Y).
  • Bare re-add (no version) → resolves the newest published version and pins it in facets.json. A bare add always pins to the resolved exact version, even over an existing wildcard spec.
  • Explicit @latest/wildcard re-add → re-resolves to the newest match (the lockfile never pins an explicit non-exact add), but the specifier itself is written verbatim and keeps floating.

Flags

FlagDescription
--verboseShow detailed step output on stderr.

Exit codes

CodeMeaning
0Add and install succeeded.
1Failed (parse error, no adapters in non-TTY, install failure, etc.). No files are modified on failure.

See also

  • facet install — re-runs the install pipeline against the current facets.json and lockfile, useful after a fresh git clone or to reapply assets after manual edits.
  • facet adapter install — install adapters into your machine.