---
title: "Eject"
description: "Leave MainSDK for one interface or all of them. mainsdk eject writes plain provider SDK code in place of MainSDK calls and keeps your tests passing."
section: "guides"
status: "Planned for 0.3"
spec: "eject"
canonical: "https://mainsdk.dev/docs/guides/eject"
updated: "2026-10-28"
---

# Eject

> Leave MainSDK for one interface or all of them. mainsdk eject writes plain provider SDK code in place of MainSDK calls and keeps your tests passing.

Status: Planned for 0.3 · Canonical: https://mainsdk.dev/docs/guides/eject · Updated: 2026-10-28

Replace MainSDK calls for one interface, or all of them, with the provider's own SDK. `mainsdk eject` keeps your tests passing, writes a report of the guarantees you give up, runs offline and sends nothing anywhere. No lock-in, by design.

> **Note:** Eject ships in phase 1, milestone 0.3, with recipes for the reference architecture drivers first. Still open: which interfaces have recipes in 0.3 (the proposal is email, pay, auth and db), and whether interfaces with a built-in driver vendor its library code or target a named outside provider.

**Before you start:**

- A clean git working tree, so you can review and revert the change.
- Your test suite passing, so you can compare the count after eject.

## 1. See the plan

Eject always plans first. `--dry-run` lists every file it would change and changes none.

```bash
npx mainsdk eject email --dry-run
```

```text
$ npx mainsdk eject email --dry-run
eject email · driver resend
  app/lib/receipts.ts      email.send() → resend.emails.send()
  app/lib/newsletter.ts    email.marketing() → resend.emails.send()
  tests/receipts.test.ts   @mainsdk/testing fake → plain mock
  main.yaml                email.key secret:RESEND_API_KEY → process.env.RESEND_API_KEY
no files changed (dry run)
```

## 2. Eject one interface

```bash
npx mainsdk eject email
```

Before:

```ts title="app/lib/receipts.ts"
import { email } from "mainsdk";

export async function sendReceipt(to: string, orderId: string) {
  await email.send({ to, template: "receipt", data: { orderId } });
}
```

After, with the Resend driver:

```js title="app/lib/receipts.js"
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendReceipt(to: string, orderId: string) {
  await resend.emails.send({
    from: "orders@pinecart.dev",
    to,
    subject: "Your receipt",
    html: renderReceipt({ orderId }),
  });
}
```

How the template is rendered (`renderReceipt` here) depends on each driver's recipe.

What eject changes:

- Every call to that interface becomes idiomatic code for the provider SDK named by the driver in `main.yaml`.
- `secret:` references become plain environment variable reads.
- Tests that used `@mainsdk/testing` fakes are rewritten to the provider's test mode or a plain mock. They are never deleted.
- `EJECT-REPORT.md` lists each guarantee that no longer holds.

A partial eject keeps every other interface working.

## 3. Verify it worked

Run your tests. They pass, with the same test count as before.

```bash
node --test
```

Then read the report and decide how you replace each guarantee:

```md title="EJECT-REPORT.md"
# Eject report: email (resend)

No longer enforced by MainSDK:
- Unsubscribe link on marketing email (was enforced by types)
- Suppression list checked before every send
- Idempotency keys on sends (retries may send twice)
```

## Eject everything

```bash
npx mainsdk eject --all --dry-run
npx mainsdk eject --all
```

After the last interface, `main.yaml`, the gates and every `mainsdk` and `@mainsdk/*` dependency are removed from the project. Interfaces with a built-in driver, such as Cedar for `policy` or built-in `webhooks`, eject to the open-source library code they use.

> **Tip:** Want a different provider rather than no MainSDK? Swap the driver instead and keep the guarantees. See [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver).

## Next

- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
- [Interfaces and drivers](https://mainsdk.dev/docs/concepts/interfaces-and-drivers)
- [CLI reference](https://mainsdk.dev/docs/reference/cli)
