CLIBreakingNew Feature
Resolve name collisions between facets; manifest 0.1, lockfile 0.3, and asset aliasing
Two facets, one name
Facets are published independently, so sooner or later two of them ship an asset with the same name. Until now the second one quietly overwrote the first. Nowfacet add and
facet install detect every collision across the
whole project before writing anything, and stop.In a terminal, the install pauses and hands you the decision:- Nothing is written until you decide. A collision leaves
facets.json,facets.lock, the receipt, and your materialized assets byte-identical. Cancelling withEscends the command without applying anything — it reports the cancellation and exits non-zero, and your project is exactly as you left it. - You decide once. Your choices are saved into
facets.json, so the next install — and every teammate’s, and CI’s — replays them without prompting. - No tool picks a winner. Not the CLI, not the registry, not the facet authors. A silent winner means a silently discarded asset.
Alias or omit any asset
The same mechanism works without a collision. A facet entry can carry amaterialization block naming, per asset, what you want:facets.json
- Aliasing renames the file, nothing else. Archive paths, per-file integrity, and the lockfile all keep the publisher’s authored name. That is what makes an alias safe: it can never be used to smuggle different content in under a familiar name.
- Omitted assets are still verified. They are resolved, hashed, and recorded in the lockfile — they are just never written to disk. Dropping them from the lockfile would make an omission indistinguishable from a facet that never published the asset.
- Skills and commands share one namespace, agents have their
own. A skill
deployand a commanddeploycollide; an agentdeploycoexists with both.
Breaking: facets.json entries may be objects
facets.json now carries a manifestVersion (currently 0.1), and
a facet entry is either a source string or an object with
source and materialization:facets.json
facets.json, it must handle both
forms. Code that assumes every value is a string will render an
expanded entry as [object Object] — or, worse, destroy a recorded
alias when it rewrites the file.A manifest with no manifestVersion is still read as the legacy
format and is migrated in place on the next successful install. There
is no separate migration command and nothing to run.Breaking: lockfile 0.3 (and receipt 0.3)
Every asset entry in facets.lock now carries a required
materialization disposition — authored, aliased, or omitted.
Version 0.2 remains readable and is migrated to 0.3 by any normal
install. The withdrawn closed-alpha 1 is no longer read at all: if
you still have one, delete facets.lock and run facet install to
regenerate it. The number 1 is reserved for the eventual stable v1
format.The machine-local install receipt moves to 0.3 alongside it, so it
can record the disposition each asset was materialized under. It
migrates itself on the next install and lives outside your repository,
so there is nothing to commit and nothing to run.facets.lock
name and files keep the authored name even when aliased.
Versions are matched exactly, never by ordering: a version number
names a schema rather than a position in a sequence, so a reader
recognizes the versions it supports and fails on anything else
instead of comparing magnitudes.Each asset’s files are also checked against the asset itself now,
not just for path safety: an agent or command lists exactly its own
primary file, and every path in a skill lives under that skill’s
directory. A lockfile that pointed an asset at an unrelated file no
longer validates.In CI: a --frozen-lockfile install fails if
facets.json declares any materialization override while
facets.lock is still at 0.2, which has no field in which to
record it. Run one normal facet install locally and commit the
migrated lockfile. Frozen mode also treats a changed alias as drift,
exactly like a changed version, and never prompts.The install pipeline resolves everything before writing anything
Commit used to be an interleaved loop — resolve facet A, write it, then start facet B. Detecting that A and Z want the same name is impossible that way, because A is already on disk.It now runs in three phases: Resolve-all, Compose, then Apply. The first two are read-only, which is why a collision, an invalid alias, or a cancelled resolution leaves the project untouched rather than rolled back. Deletion also moved to the start of Apply, before any write, so an asset name can transfer from one facet to another in a single install without the new owner’s file being deleted behind it.Removing a facet is the exception. When your machine’s install receipt already accounts for everything you are keeping,facet remove refines those lockfile entries in place
instead of resolving them, so it still works with a cold cache and an
unreachable registry.Two smaller consequences you may notice:- Disposition changes report as
updated. Aliasing an asset at an unchanged version is a real change to what is on disk, not a no-op and not a repair. - Stale choices are pruned and reported. If you upgrade a facet and the publisher removed an asset you had aliased, the override is dropped on a successful install and the CLI tells you which one.
Breaking: only your install receipt authorizes deletion
facets.lock is shared, version-controlled state. It says what
should be materialized — not what your machine actually wrote —
so it is no longer treated as proof of ownership. Deletion is driven
by the machine-local install receipt alone.Two rules replace the old fallback:- Your project’s desired state authorizes writes. An install still materializes every declared asset, overwriting an unmanaged file that happens to occupy the same name. (If what is already there matches byte for byte, it is adopted without a rewrite.) Either way the file is tracked from then on.
- The receipt authorizes deletions. Files the CLI has no record of writing are never deleted.
- Pull a teammate’s
facets.lockonto a machine that never ran an install, thenfacet removethe facet:facets.jsonandfacets.lockdrop it and the files stay exactly where they are. The summary says so instead of reporting a cleanup that did not happen, and those files are then yours to delete by hand. facet removemay need the network. The offline guarantee is a property of tracked state, not of removal. If a facet you are keeping is not fully accounted for by your receipt, the removal runs the ordinary pipeline to materialize it before claiming it — which succeeds when the content is reachable and fails, deleting nothing, when it is not. Runfacet installfirst to take ownership.- An unusable receipt is reported. Unreadable, or recorded against a different project: nothing on disk is tracked, so nothing is cleaned up, and the run records only what it materializes.
Breaking: facet remove decides what is declared under the lock
Whether a name is declared is now answered by the commit, holding the
project lock, instead of by a read taken before it. A pre-lock read
can be stale, and acting on one let a facet added by a concurrent
process survive the removal that asked for it.So facet remove ghost in a project with no adapter opens the picker
in a terminal and exits non-zero in CI, rather than printing a no-op
summary it never verified. Names that really are absent under the
lock are still ignored, and a removal whose names are all absent
still succeeds. An unreadable facets.json is still reported as a
manifest problem, before any adapter is discovered.Adapter authors
The adapter contract is unchanged — no rebuild, no version bump. Butrequest.name has always been, and now visibly is, the effective
name: the name the consuming project chose. Address files by
request.name and never re-derive a path from a facet’s manifest.
See Custom adapters.CLIBreakingNew Feature
Facets ship non-asset files; archive 0.2, per-file lockfiles, first-class README, and the 0.1 adapter contract
Facets can ship non-asset files
A facet is no longer just its assets. You can now declare supplementary files that travel inside the.facet archive and are integrity-protected
like everything else:- Skill companions — files beside a
SKILL.md(references, scripts, templates). They install and remove atomically with their skill, and files you add to a skill directory yourself are preserved on removal. - Top-level archive-only files —
README.md,LICENSE, design notes. They ship in the archive but are never written to disk at install.
files
array or a skill descriptor’s own files array:First-class README authoring
facet create now writes and declares an editable
README.md by default (skip it with --no-readme), and
facet edit has a dedicated README panel for
creating, adopting, editing, or removing both README.md and the
extensionless README.Breaking: archive 0.2, per-file lockfiles, and naming
- Archive format
0.2. Every build now emitsfacetVersion: 0.2with a complete per-entry hash map covering every file, asset or not. Consumers still accept legacy0.1archives during the compatibility window; the two are dispatched by exact version match, never numeric ordering. An archive whose version your CLI doesn’t support fails with upgrade guidance — runfacet self-update. - Lockfile
0.2.facets.lockrecords a per-file{ path, integrity }record for every materialized file inside each asset, and install reconciles them before writing, reporting and repairing drift by exact path. A verified legacy alpha lockfile migrates automatically on a normal install. See Lockfile. - Asset names. Skill, command, and agent names are now single-segment
Agent Skills names — slash-namespaced
names like
viper-plans/planningare no longer valid in new manifests (useviper-planning). Skills and commands now share one namespace and can’t reuse a name. - Primary files carry no front matter. Asset metadata lives in the
manifest; a
SKILL.md, agent, or command file with YAML front matter is now a build error. Supplementary files still ship verbatim.
Breaking: adapter API 0.0 → 0.1
The adapter contract advances from the positional single-file shape (0.0)
to the tagged multi-file request/result contract (0.1) that carries skill
companions. A 0.1 CLI treats a positional 0.0 adapter as unsupported and
fails closed before any write. Rebuild against a 0.1 SDK and reinstall:facetVersion, the lockfile version, and the adapter API are
three independent axes — a consumer classifies each separately. See
Custom adapters.Rollout
The change ships consumer-first: the protocol package publishes dual0.1/0.2 verification, then the registry adopts it, then the adapter SDK
and first-party adapters publish 0.1, and finally the CLI release turns on
0.2 production. Existing 0.0 CLIs keep selecting compatible 0.0 adapters
until you update.facet remove prunes empty adapter directories
Removing a facet now cleans up empty parent directories left behind
in each connected adapter. When facet remove (or
facet rm) deletes the last asset inside a nested folder — for
example skills/<name>/SKILL.md under Claude Code or OpenCode — the
CLI walks up and removes empty parent directories, stopping at (but
not including) the adapter’s root.What this means for you:- Tidier working tree. Uninstalling a facet no longer leaves behind empty namespace folders that you’d otherwise have to delete by hand.
- No configuration. The behavior is automatic for the Claude Code and OpenCode adapters — no flags, no opt-in.
- Bounded to each adapter. Pruning stops at the adapter’s own root, so it can never walk into the rest of your project.
@agent-facets/adapter@0.26.0,
@agent-facets/adapter-claude-code@0.7.0, and
@agent-facets/adapter-opencode@0.8.0. Run
facet self-update to pick it up.CLIImprovementBreaking
Server-side search for facet search; asset names now follow the Agent Skills grammar
Server-side search for facet search
facet search now forwards your query term to the registry as the
?q= parameter on the facets endpoint and renders whatever the server
returns, in order. The registry — not the CLI — owns relevance
ranking, sorting, and paging.- Results match the web UI. Ordering is consistent with what agentfacets.io shows, because both surfaces read the same server-ranked list.
- Better matching, no upgrade required. Improvements to registry search (typo tolerance, ranking, new sort orders) take effect immediately — the CLI just displays what the server sends.
- Old behavior removed. The client-side case-insensitive name substring filter is gone. If a term returns no matches on the server, the CLI now shows an empty result instead of falling back to local filtering.
facet search reference for usage.Asset names now follow the Agent Skills grammar
Breaking: skill, command, and agent names declared infacet.json
are now validated against the Agent Skills name
grammar at both
build and install time. Each /-separated segment must be:- 1–64 characters long
- lowercase ASCII letters, digits, and hyphens only
- no leading, trailing, or consecutive hyphens
2fa are now accepted; previously they were
rejected. Non-conforming names like MySkill or foo_bar are now
rejected — previously they slipped past the looser kebab-case check.
Namespaced names like viper-plans/planning validate per segment."must be at most 64 characters") instead of a generic kebab-case hint.If you have a facet with a legacy non-kebab asset name, facet modify --update and facet modify --remove still accept the old name so you
can rename or drop the asset without a chicken-and-egg problem. See
the manifest schema and facet modify reference.CLINew FeatureImprovementFix
Agent-friendly CLI: instructions, modify, headless create, build --verify; TypeScript 7 support; trailing newlines on generated JSON
TypeScript 7 support
The public@agent-facets/* packages now declare their typescript
peer dependency as ^5 || ^6 || ^7, so they install cleanly on
projects that have upgraded to TypeScript 7. Consumers still on
TypeScript 5 or 6 are unaffected — no action needed.This applies to:@agent-facets/protocol@agent-facets/adapter@agent-facets/brand@agent-facets/adapter-claude-code@agent-facets/adapter-codex@agent-facets/adapter-opencode
Trailing newlines on generated JSON
Every JSON file the CLI writes now ends with exactly one trailing newline and uses consistent 2-space indentation:facets.lock- install receipts and parallel-install lock payloads
- build manifests inside the
.facetarchive - scaffolded
facet.json(fromfacet create) - cache integrity sidecars
facets.json continues to be written through the comment-preserving
serializer (so your hand-edited comments survive) and now upholds the
same trailing-newline invariant.The CLI is now agent-friendly
Every interactive authoring flow now has a non-interactive, scriptable path, and the CLI can describe itself to an AI agent on demand. Three themes: built-in instructions, headless authoring, and machine-readable output.New command: facet instructions
facet instructions [topic] prints agent-oriented usage guidance — how to
author and use facets, written for an autonomous agent to read before it
acts. It is workflow guidance, not per-flag help.manifest topic appends the facet.json JSON Schema generated live
from the schema definition — a single source of truth, never a
hand-maintained copy. See facet instructions.New command: facet modify
facet modify is the scriptable counterpart to the interactive
facet edit wizard: one headless, flag-driven edit
to a facet.--adapter-<name> '<json>' sets a block (replacing it wholesale),
and --remove-adapter-<name> deletes one. Add --json for a structured
change summary. Exactly one lifecycle action (--add, --remove, or
--rename) is allowed per call; illegal flag combinations are rejected up
front. See facet modify.facet create gains headless flags
Pass authoring flags to scaffold a facet without the interactive wizard:--skill/--agent/--command for multiple assets; --private
marks the facet private, --force overwrites an existing facet.json
(required in headless mode), and --json prints a structured result. See
facet create.facet build --verify and --json
facet build --verify runs the full validation pipeline without writing
any output — a no-op build that confirms facet.json and every asset are
valid and buildable. --json emits a machine-readable result and works with
or without --verify.facet build.Fix: subcommand --version is no longer shadowed
The global --version flag now applies only before the command name, so
facet modify facet --version 1.2.3 sets the facet’s version instead of
printing the CLI version.New command: facet remove
facet remove <facet> [more facets...] is the inverse of facet add: it
takes facets back out of a project. In one command it removes the named
facets from facets.json, deletes their assets from every connected
adapter, and rewrites facets.lock without them.facet add, so it is
transactional: any failure restores facets.json byte-for-byte and
leaves the project unchanged. Removing multiple facets is all-or-nothing —
if any name is not declared in facets.json, nothing is removed. Every
facet you don’t name is left untouched.See the facet remove reference for details.CLIBreakingNew FeatureFix
Bearer-token auth for the registry; new login/whoami/logout commands; FACET_REGISTRY_API_KEY removed; install now re-resolves a stale lockfile; new --frozen-lockfile flag
Registry authentication is now bearer-token based
Breaking: theFACET_REGISTRY_API_KEY environment variable has been
removed — there is no fallback or deprecation shim. The CLI now sends an
Authorization: Bearer <token> header, where the token is a you mint in the web UI.Provide the token one of two ways:FACET_TOKEN is set it takes precedence over the saved file. Read-only
commands like facet search and facet add send the token too when one is
available (earning a higher rate-limit tier) and work anonymously otherwise.New commands: login, whoami, logout
facet login— guided sign-in. Paste a PAT; the CLI verifies it against the registry before saving it, so a typo or expired token fails fast instead of surfacing later at publish time. A browser sign-in option is shown as “coming soon”.facet whoami— prints the signed-in username, email, and tier, and notes whenFACET_TOKENis the active credential.facet logout— removes the saved credentials file. It makes no server call; revoke PATs in the web UI. IfFACET_TOKENis still set, it tells you so.
facet publish takes an optional directory
facet publish now accepts a directory argument and defaults to the current
directory, matching facet build, facet edit, and facet create:Registry errors render verbatim
When the registry rejects a request, the CLI now shows the registry’s own message and suggested fix rather than translating the error code through a local table. The registry is the single source of truth for what an error means — so error guidance stays accurate as the registry evolves, with no CLI release required.See the Publish Flow spec for the full authentication model.Editing a version in facets.json now takes effect
Fix: facets.json is the source of truth, but facet install was
ignoring an edited version when the lockfile still pinned the old one. If you
bumped a facet to a version that didn’t exist, install “succeeded” and wrote a
self-contradictory lockfile entry instead of failing.Now facet install compares each lockfile entry against its manifest
specifier. A locked version that no longer satisfies the manifest is treated
as stale and re-resolved:1.*, lock 1.2.3) is
unaffected — it stays pinned and reproducible. See resolution semantics.New: facet install --frozen-lockfile
For reproducible CI installs, --frozen-lockfile makes the lockfile the
source of truth: install never re-resolves or writes the lockfile, and fails
if the lockfile is missing, omits a manifest facet, or has drifted out of sync
with facets.json.--frozen-lockfile from npm and bun. See frozen
lockfile semantics.CLIBreaking
Consolidate everything under FACET_DIR; new FACET_BIN_OVERRIDE; lock moves out of project root
One directory, one override
The facet CLI used to spread its state across four near-identical locations and five separate environment variables. State for the cache, installed adapters, the curl-installed binary, and parallel- install coordination all lived in different places with different overrides. This release collapses everything into a single root: one directory, one environment variable.The new shape
Everything the CLI writes to disk now lives under$FACET_DIR:$FACET_DIR is ~/.facet/. Setting FACET_DIR IS
the override — there is no separate variable per subsystem. Curl
installs put the binary at $FACET_DIR/bin/facet; facet add and
facet install resolve cache and adapters relative to the same root.What changed
FACET_CLI_REGISTRY (npm registry URL override) and FACET_VERSION
(used by install.sh) are unchanged.FACET_BIN_OVERRIDE, by name
The launcher’s binary override gets a new name that carries its own
semantics: FACET_BIN_OVERRIDE. Setting it means you’ve taken control
of which binary the launcher executes. facet self-update continues
to refuse while it’s set, because if you’ve overridden the binary
path, self-update has no business writing over whatever you pointed
it at. The refusal is coupled to the override on purpose.Unset FACET_BIN_OVERRIDE to re-enable self-update for a real install.Project root: clean
The install advisory lock no longer touches your project root. Previously,facet install materialized .facets/.install.lock next
to facets.json — a project-local directory that wasn’t tracked
anywhere and could be left behind on crashes. The lock now lives at
$FACET_DIR/locks/<basename>-<sha256(realpath)[:16]>.lock, keyed by
the project’s canonical path so two checkouts of the same repo at
different paths (git worktrees, Conductor workspaces) get distinct
locks.No .facet.lock file, no .facets/ directory, no untracked entry
next to your facets.json. The project root stays as clean as
facets.json itself.Breaking: No automatic migration. The new code reads $FACET_DIR
only — existing cached payloads and adapters at ~/.facets/ are not
detected, copied, or warned about. Old env vars (FACETS_CACHE_DIR,
FACETS_ADAPTERS_DIR, FACET_CACHE_DIR, FACET_ADAPTERS_DIR,
FACET_INSTALL_DIR, FACET_BIN_PATH) are silently ignored — anyone
who had them set in shell rc files or CI configs must rename to
FACET_DIR / FACET_BIN_OVERRIDE or the values stop taking effect.
Existing ~/.facets/ data can be deleted at any time; the new code
will rebuild cache and adapters on first use.See the environment variables reference and the
facet install page for the updated paths.CLIBreakingImprovement
@agent-facets/core split into protocol (public, Node-native) and engine (private, Bun-native)
Three layers, honestly named
@agent-facets/core was always two things: the facet artifact specification (schemas, integrity rules, deterministic archive format, hash algorithm) and the Bun-native CLI implementation of that specification (subprocess-driven adapter bundling, registry HTTP client, install pipeline, scaffold, edit, self-update). The first set is portable Node-runnable data + cryptography that any third party — a registry server, a future alternative CLI, an offline .facet linter — needs to honor. The second is intrinsically Bun-native and runs only on a developer’s machine.Splitting them produces three honest layers:@agent-facets/protocol(NEW, public, Node-native, Node 22+) — the TypeScript reference implementation of the facet artifact specification. Schemas, bytes-validators, integrity verification, content hashing, deterministic tar layout, version-spec grammar, front-matter encoding, build validators. Pure data + cryptography. No subprocesses, no network, no developer-machine state.@agent-facets/engine(RENAMED from@agent-facets/core, made private) — the Bun-native CLI machinery. Install pipeline, registry HTTP client, adapter machinery, source resolvers, manifest mutations, cache, scaffold, edit, self-update, build pipeline orchestrator, gzip compression, path-based loaders. Internal to the monorepo; never published.agent-facets(the CLI binary, unchanged) — argv parsing, Ink TUI, error formatting, exit codes.
@agent-facets/core is no longer published. The package is frozen at v0.9.1 on npm; existing pins continue to resolve, but there will be no further versions. New consumers (registry servers, third-party tooling) MUST use @agent-facets/protocol. There is no deprecation message on the legacy package — closed-alpha, no known external consumers.No CLI behavior change. Every @agent-facets/core import in the CLI was redirected to either @agent-facets/protocol (data primitives) or @agent-facets/engine (orchestrators). User-visible commands, flags, and output are unchanged.CLINew FeatureBreaking
facet add now installs in one step; new source grammar; lockfile-driven install
facet add and facet install converge
facet add now does everything end-to-end. Resolve, fetch, verify integrity, materialize into adapters, write the lockfile — all in a single command. There is no separate facet install step after facet add.facet install is still there, and it’s the right command after a fresh git clone or after pulling teammate changes that updated facets.json. It honors any pinned versions in facets.lock verbatim and only resolves entries that don’t have a lockfile entry yet — making installs reproducible across machines without a separate facet update command.If a project has no adapters installed, both facet add and facet install now auto-launch the adapter picker on a TTY, so first-run experience is a single command from a cold start.New source grammar
facet add accepts a richer set of sources, aligned with what npm and bun users already expect:facets.json — so facet add viper-plans produces viper-plans@1.2.3 in the manifest, the same way npm install and bun add pin lockable defaults.Lockfile-driven, with bootstrap
facets.lock is now the single source of truth for what gets installed:- When a lockfile entry exists, that exact version is fetched. The manifest’s range is not re-resolved.
- When a lockfile entry doesn’t exist (first run, or a freshly-added manifest entry), the manifest specifier is resolved fresh.
- When
facets.lockdoesn’t exist yet,facet installbootstraps it — the same waybun installcreatesbun.lock.
Three-check integrity protocol
Every fetched facet is verified before any asset is written:- Registry sources run three independent checks: cache vs. registry metadata, archive manifest vs. registry metadata, computed content vs. archive manifest. Each defends against a distinct adversary.
- Git sources run a single check: computed content vs. lockfile integrity. Defends against tag-move attacks.
- Local sources are trust-by-path.
Cache
Resolved facet content is cached at~/.facets/cache/<name>@<version>/. Subsequent installs of the same identity hit the cache instead of the network. Override with the FACETS_CACHE_DIR environment variable.Repaired outcome
If you delete a materialized asset by hand and re-runfacet install, the affected facet now reports as repaired in the summary — the adapter file is restored without bumping the version. This makes self-heal explicit instead of silent.Breaking changes
git+prefix is removed. Use plainhttps://...gitorgit@host:owner/repoinstead. The new grammar accepts everythinggit+did, just without the prefix.- Caret, tilde, and comparator version ranges are rejected. Use
1.*for major-pinned,1.2.*for minor-pinned,*orlatestfor unpinned, or1.2.3for exact. The@latestalias and bare-name form both produce the same result as*. facet install --dry-runis gone. No replacement;facet installalways commits.facet installrejects positional arguments. To add a new facet to the project, usefacet add.
Publish pipeline fixed across all packages
Recent releases ofagent-facets and the supporting packages had been failing or shipping inconsistently due to issues in the publish pipeline. All affected packages have been republished from a known-good state:agent-facets— the CLI@agent-facets/coreand@agent-facets/adapter— authoring and adapter SDKs@agent-facets/adapter-claude-code,@agent-facets/adapter-opencode, and@agent-facets/adapter-codex— first-party adapters
facet add, facet install, and the adapter commands all behave the same as before.Mobile-responsive landing page
The agentfacets.io landing page is now fully responsive. If you previously visited on a phone or tablet, the experience was broken — the scroll-linked demo, navigation, and layout all assumed a desktop viewport. That’s fixed.Here’s what changed:- Mobile navigation — the nav bar collapses into a slide-down menu on screens ≤ 1024 px wide, with all links accessible from a single tap.
- Adapted CLI demo — the interactive terminal demo skips the widest step on small screens so it fits without horizontal scrolling.
- Stacked sections — the explainer, hero, and footer all reflow into a clean single-column layout on narrow viewports.
- Registry CTA — on mobile, the install command is replaced with a link to agentfacets.io so you can browse facets without needing a terminal.
agentfacets.io landing page
The Agent Facets website now has a proper landing page at agentfacets.io. It walks you through what facets are, shows a live CLI demo, and makes it easy to get started with a single install command:New docs URL
Documentation has moved to its own subdomain at docs.agentfacets.io. The main domain atagentfacets.io now serves the landing page, and the CLI installer lives at agentfacets.io/install. Existing docs links have been preserved — you’ll just land on the new URL. Update any bookmarks accordingly.facet add and facet install
You can now add facets from external sources and install them into your AI coding tools end-to-end.facet add resolves a facet from GitHub, a Git URL, or a local path and writes it to your project’s facets.json, preserving any hand-edited comments:facet install reads facets.json, builds each facet, and materializes its assets into every adapter you’ve connected. The pipeline is built for iteration:- Lockfile diffing — only changed assets are written on each run.
- Rollback on failure — if something goes wrong mid-install, changes are reversed automatically.
- Concurrent safety — an atomic install lock prevents two
facet installruns from interfering with each other. --verbose— full pipeline trace for debugging.
New install URL
The CLI installer has moved to its own home atagentfacets.io/install. If you previously bookmarked the install URL, update it to:Self-contained adapter bundles
Adapters now ship as fully self-contained bundles with all dependencies inlined. When you runfacet adapter install, the CLI uses a prebuilt fast path that skips the build step entirely — falling back to a full rebuild only if the prebuilt bundle is missing or incompatible.This also means adapter installs no longer leave build artifacts in your source tree.See the environment variables reference for configuring the adapter install location with FACETS_ADAPTERS_DIR.Adapter SDK and first-party adapters
Adapters are the bridge between facets and your AI coding tool — each adapter knows where and how to write assets for a specific tool. The first three first-party adapters ship today:- Claude Code
- OpenCode
- Codex (early access — installable, but asset materialization via
facet installis coming soon)
facet install, the CLI writes your facet assets into the correct locations for every adapter you’ve installed. Third-party adapters use the same installation and loading mechanism as first-party ones — install via npm, Git URL, or local path.Manage adapters with:facet install, an interactive picker appears so you can select which AI tools to connect.See the adapter CLI reference for full usage, including all built-in adapter names.Self-contained .facet archives
The.facet build output is now a single self-contained archive. The build manifest is embedded inside the archive rather than shipped as a separate file, making distribution simpler. You can extract the manifest for debugging with --emit-manifest during build.See the facet build CLI reference.