Skip to main content
An teaches the facet CLI how to install assets into a specific AI coding tool. The first-party adapters cover Claude Code, OpenCode, and Codex; this guide shows how to build your own using the @agent-facets/adapter SDK. An adapter is a small TypeScript library. You write one file, build it, and install it locally — from a directory, from GitHub, or (once published) by name.

How an adapter fits in

When you run facet install, the CLI reads each facet’s assets and hands them to every installed adapter. The adapter decides where on disk each asset goes and how it’s formatted, so the target tool picks it up. That’s the entire job: translate a facet asset into files your tool understands.An adapter implements a small contract from the SDK. Two methods matter most:
  • buildAssetMetadata validates the per-asset metadata an author put in facet.json (the adapters.<name> block) and enriches it with your defaults.
  • installAsset writes the asset to disk. Its siblings readAsset and deleteAsset complete the lifecycle.

Scaffold the package

1

Create a package and add the SDK

The SDK is a leaf library with no heavy dependencies — @agent-facets/common (the shared types) is bundled into it, so you don’t install anything else.
2

Write the adapter

Create src/index.ts and default-export a defineAdapter call. Here is a minimal, working adapter that writes each asset to ~/.my-tool/<type>s/<name>.md:
src/index.ts
installAssetFile, readAssetFile, and deleteAssetFile are SDK helpers that manage YAML front-matter, create parent directories, and stay byte-stable across a write→read round-trip. Use them instead of hand-rolling file I/O so re-installs don’t report phantom drift.

The adapter contract

Everything an adapter can implement, from @agent-facets/adapter:
string
required
A unique id (e.g. my-tool). Users install and reference the adapter by this name.
Validated<AdapterMetadata>
required
Validate and enrich the per-asset metadata from a facet’s adapters.<name> block. Return { ok: true, data } or { ok: false, errors }. Runs during facet build, so bad config is caught early.
boolean
Set to true only when all three I/O methods below are implemented. It makes the adapter selectable in the install picker; a metadata-only adapter omits it and stays hidden.
Promise<string | undefined>
Write the asset to disk. Return the absolute path (for verbose logs) or undefined.
Promise<{ content, metadata }>
Read an asset back from disk.
Promise<string | undefined>
Remove an asset. Return its path or undefined.
Two shared argument types run through the I/O methods: scope is 'system', 'user', or 'project' (decide your on-disk layout per scope), and assetType is 'skill', 'agent', or 'command'.
You can ship a metadata-only adapter: implement just name and buildAssetMetadata, and omit supportsInstall. It validates manifest config during builds without materializing anything — useful while you’re still figuring out a tool’s on-disk layout.

Bundle it

facet adapter install re-bundles your adapter into a self-contained adapter.js, but it needs a clean single-module entry to start from. Compile your package first — for example with tsdown (what the first-party adapters use) or tsc:
Point your package.json exports/main at the compiled entry so the CLI can resolve it.

Install your adapter

facet adapter install accepts your adapter three ways:
The CLI downloads the source, bundles it into adapter.js, verifies it exports a valid adapter, and places it in $FACET_DIR/adapters/<name>/ (default ~/.facet). See facet adapter install for every specifier format.
During development, facet adapter install ./my-adapter picks up your latest local build immediately. Reinstall after each rebuild to test changes end-to-end.

Verify it works

Confirm the adapter is registered, then install a facet to see it materialize assets:
Check that files landed where your assetPath puts them. From here, harden buildAssetMetadata with a real schema and flesh out the on-disk layout your tool expects.

Share it upstream

Built an adapter for a major AI coding assistant? Contributions are welcome. If your adapter targets a widely used tool, open a pull request on the facets repository to share it upstream as a first-party adapter.A first-party adapter is installable by name (facet adapter install <name>) via the CLI, so everyone using that tool benefits.