> ## Documentation Index
> Fetch the complete documentation index at: https://docs.deploybaseline.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Provider packages

> Publish an emulator as an npm package that the CLI runs in its own process, and run packages other people publish.

A provider package is an emulator published to npm that the CLI runs the way it runs the built-in providers: in its own process, on its own port, with seed config, saved state, snapshots, faults, and the control API. Anyone can publish one. Users name it in their config with `provider:`, and the CLI asks them to trust it before it runs.

Choose a provider package when an emulator should be shared across projects and versioned on its own. For an emulator that lives in one project, a [custom emulator](/custom-emulators.md) is simpler.

## Run a provider package

```json baseline.config.json theme={null}
{
  "services": {
    "billing": {
      "provider": "npm:@acme/baseline-billing@^1.2.0",
      "port": 4100,
      "seed": {
        "plans": [
          {
            "id": "pro"
          }
        ]
      }
    }
  }
}
```

* `provider:` is `npm:<package>@<range>`. The range takes the same forms as `version:` on a built-in service, and defaults to `*`.
* `port:` is required, because a provider package has no port slot. It must not be another service's port or the console port.
* The service name (`billing`) is yours to choose, but it cannot be a built-in service's name. `seed`, `baseUrl`, and `faults` work as they do for built-in services.
* `@deploybaseline/*` packages are the built-in providers: use `emulator: stripe` with `version:` for those.

The package is found the way built-in providers are ([Provider versions](/provider-versions.md)): from the project's `node_modules`, then the version `baseline.lock` pins, then the provider cache, then a pull from the npm registry your `.npmrc` names.

### Trust

A provider package runs with your permissions: it can read and write your files, reach the network, and start processes. Its own process keeps it from crashing other services, but it is not a sandbox. So it runs only once you have trusted that exact version:

1. The first `start` that resolves it prints the package, version, source, integrity, and where it was built, and asks:

   ```text theme={null}
     billing: @acme/baseline-billing 1.2.0 (pull)
       Integrity: sha512-...
       Built from: https://github.com/acme/baseline-billing at 3f2c1e9
       Workflow: .github/workflows/release.yml
     It is not built into Baseline and runs with your permissions: your files, the network, and child processes.
     Trust this version and pin it in baseline.lock? [y/N]
   ```

2. Answering yes pins it in `baseline.lock` before it runs:

   ```yaml theme={null}
   providers:
     billing:
       package: "@acme/baseline-billing"
       version: 1.2.0
       integrity: sha512-...
       trusted: true
   ```

3. Commit the lockfile. Without a terminal, or with `CI` set, `start` asks nobody: it refuses a provider package that the lockfile does not trust, and names the command that grants it.

`npx @deploybaseline/cli trust [services...]` grants trust without a prompt, for every `provider:` service or the ones named, and prints the same details. Trust covers one version and tarball. A new version, from `update` or a changed range, is asked about again, and a tarball that does not match the lockfile's integrity is refused.

`Built from` comes from the version's npm provenance attestation, and only when it is for that exact tarball. npm checks the attestation's signature when the version is published; the CLI shows what it says. A version published without provenance shows `Provenance: none`.

## Write a provider package

Start from the template in the repository, [`examples/provider-template`](https://github.com/deploybaseline/cli/tree/main/examples/provider-template): a notes API with seed config, saved state, and a test that drives the built entry over the provider protocol.

| File | What it is |
| - | - |
| `src/index.ts` | The plugin: routes on a Hono app, state in the store, and `seedFromConfig` |
| `src/manifest.ts` | What the CLI knows without loading the plugin; `load()` imports `./index.js` |
| `src/provider.ts` | The entry the CLI forks: `runProvider(manifest, { packageUrl })` |
| `package.json` `baseline` | The manifest's data, read before anything runs |
| `api-reference.json` | The OpenAPI document shown at `/docs` on the console port |

```typescript theme={null}
// src/provider.ts
import { runProvider } from "@deploybaseline/core";
import { manifest } from "./manifest.js";

runProvider(manifest, { packageUrl: new URL("../package.json", import.meta.url) });
```

### The baseline field

```json theme={null}
{
  "name": "baseline-provider-notes",
  "version": "1.0.0",
  "keywords": ["baseline-provider"],
  "files": ["dist", "api-reference.json"],
  "baseline": {
    "protocol": 1,
    "entry": "./dist/provider.js",
    "name": "notes",
    "seedKey": "notes",
    "aliases": [],
    "stateVersion": 1,
    "label": "Notes API emulator",
    "endpoints": "notes: list, create, read, delete",
    "identities": false,
    "apiReference": "./api-reference.json"
  }
}
```

| Key | Meaning |
| - | - |
| `protocol` | The provider protocol version the entry speaks. `1` today |
| `entry` | The file the CLI forks, inside the package |
| `name`, `seedKey`, `aliases`, `label`, `endpoints` | The same values as the manifest. The template's test checks they match |
| `stateVersion` | The shape of saved state. Raise it when that shape changes |
| `identities` | `true` when the provider seeds shared `identities:` as users (built-in providers only, for now) |
| `apiReference`, `init` | Optional paths inside the package |

### Rules

* **Self-contained entry.** The CLI unpacks the tarball and runs `entry` with nothing installed next to it, and runs no install scripts. Bundle every runtime dependency, `@deploybaseline/core` included, into `dist/` (the template's `tsup.config.ts` does, and copies core's fonts next to the bundle).
* **One port.** Listen only on the port the CLI gives you; `runProvider` does this.
* **State in the store.** Everything in the store is saved, restored, and snapshotted by the CLI. Keep `stateVersion` honest, and migrate or refuse older state.
* **Files.** Write only to the system temp directory and to paths your seed config names.
* **Names.** `baseline-provider-<name>` or `@scope/baseline-<name>`, with the `baseline-provider` keyword so people can find it. The `@deploybaseline` scope is for built-in providers.
* **Provenance.** Publish from CI with `npm publish --provenance`, so users see the repository and commit before they trust it.

### What you can rely on

* The protocol version you build against keeps working for at least a year of CLI releases.
* SDK upgrades are yours to take: your package bundles the core it was built with.
* The CLI passes your service its seed, tokens, faults, base URL, and saved state, and handles persistence, secrets output, the console, and the control routes.

### Test it

The template's test forks `dist/provider.js` with `spawnProvider` from `@deploybaseline/core`, the same client the CLI uses, and checks the handshake, seed config, HTTP, and a save and restore. To try the package in a project before publishing, install it as a dev dependency: a `provider:` service resolves from `node_modules` first, and still asks for trust.

```bash theme={null}
npm pack
cd ../my-app && npm install -D ../baseline-provider-notes/baseline-provider-notes-1.0.0.tgz
npx @deploybaseline/cli start
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.