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

# The development lifecycle

> From scaffolding through publishing your integration

# The development lifecycle

Building an integration follows a repeatable cycle: init → develop locally → validate → test → publish.

## 1. Initialize (`ekanos init`)

```bash theme={null}
ekanos init --slug my-integration --yes
```

Creates:

* `src/integration.ts` — a starter definition with one widget, one tool, and a commented-out example action — plus `src/integration.test.ts`
* `ekanos.json` pointing to your entry file
* `package.json` with the published `@ekanos/*` dependencies
* `tsconfig.json` (with `noUncheckedIndexedAccess`), `vitest.config.ts`, and `.gitignore`
* A pre-commit hook (`scripts/setup-hooks.mjs`, wired through `prepare`) that runs `ekanos validate`; `SKIP_EKANOS_HOOK=1` skips it
* Agent-context files: `AGENTS.md`, `CLAUDE.md`, a Claude Code skill, `docs/api-notes.md`, `.mcp.json`

`harness.config.ts` is not created by `init` — the first `ekanos dev` writes it.

<Note>
  `init` never prompts for the slug: `--slug <name>` is required, and a missing slug is a usage error. In a real terminal it shows an interactive summary; CI, `--json`, and piped output are unaffected. Use `--dir .` to scaffold in the current directory instead of creating `./<slug>`.
</Note>

## 2. Develop locally (`ekanos dev`)

```bash theme={null}
ekanos dev
```

Scaffolds `.ekanos/harness/` (regenerated on every run) and runs it with your project's own Next, on `http://localhost:3100` by default. The harness:

* **Renders your surfaces in real Ekanos chrome** — the dashboard grid, the marketplace tile, the activation form, and Triggers
* **Serves in fixtures mode by default** — requests are answered from your recorded fixtures; an unrecorded request is refused, never sent
* **Optionally runs live mode** — an entry with a `live` block can switch the toolbar to Live API and reach your vendor's real API

### Fixtures mode (default)

Declare HTTP exchanges in `harness.config.ts`:

```ts theme={null}
export const harnessIntegrations = defineHarnessConfig([
  {
    slug: 'my-integration',
    name: 'My Integration',
    description: '…',
    definition: asHarnessDefinition(integration), // powers Triggers
    fixtures: {
      default: [
        {
          request: 'GET https://api.example.com/data',
          response: {/* … */},
        },
      ],
    },
    widgets: [/* … */],
  },
]);
```

`defineHarnessConfig` comes from `@ekanos/harness/config` and `asHarnessDefinition` from `@ekanos/harness/registry`. Variants are `default`, `empty`, and `error`; an omitted variant is not a fallback to `default`. A request with no matching fixture rejects with `NoRecordedResponseError`, whose message quotes the fixture line to paste.

### Live mode (opt-in)

Add a `live` block to your harness entry:

```ts theme={null}
{
  slug: 'my-integration',
  // …
  live: {
    // No `egress` here when `definition` is set — the harness reads it off the definition.
    seeds: [ /* react-query keys that stay mocked in live mode */ ],
  },
}
```

Switch the toolbar's **Data** dropdown to **Live API** — widgets' queries run their real functions, and handlers call the real network under your definition's `egress` allowlist. An entry with a `live` block still opens in fixtures mode unless it declares `live: { default: 'live' }`.

### Local OAuth

For an integration whose definition declares `oauth`, live mode runs the complete authorize → callback → `onTokens` loop against your own developer app (no Ekanos host required).

1. Switch the toolbar to **Live API** (the entry needs a `live` block)
2. On the Activation or Triggers surface, open the **Local OAuth** panel and follow its checklist for your provider's developer console, including the redirect URI `http://localhost:3100/api/integrations/<slug>/oauth/callback`
3. Paste the client id and secret into the panel's form and **Save credentials** — they are written to `.ekanos/local-secrets.json` (gitignored, never packed by `ekanos publish`)
4. Click **Connect** in the activation dialog — the flow runs on localhost, and `onTokens` then `onActivate` run on the live context

The connection itself is memory-only: restarting the dev server forgets it.

## 3. Validate (`ekanos validate`)

```bash theme={null}
ekanos validate
```

Checks:

* Strict schema adherence (unknown keys are errors)
* Naming rules for slugs, widget ids, tool names, webhook/schedule/action names, and storage keys
* No duplicate ids within one integration, and no collisions across all integrations in the project's `ekanos.json`
* OAuth endpoint origins covered by your `egress` list, and cron syntax
* `project.slug-agreement` — the `ekanos.json` slug matches the definition's
* `project.vitest-inline-sdk` — the vitest config inlines `@ekanos/sdk`
* `project.host-compiler-rules` (warning) — `tsconfig.json` sets `strict` and `noUncheckedIndexedAccess`. `validate` does not compile your code; `publish` escalates this finding to an error
* Advisory warnings such as `icons/pro-only` and `docs/missing-file`

Common exit codes:

* `0` — No error-severity findings
* `2` — Usage error
* `3` — Error-severity validation findings (warnings alone do not fail)
* `9` — Precondition failed (for example, the project's `@ekanos/integration-schema` is newer than the CLI's)

Fix every error-severity finding before publishing — `publish` refuses to submit otherwise.

## 4. Test (`ekanos test`)

```bash theme={null}
ekanos test
```

Runs your project's own `test` script through its package manager. For a vitest script, failures get a curated `FAILURES` appendix; `--raw` skips that.

The SDK provides testing utilities:

```ts theme={null}
import { invokeWebhook } from '@ekanos/sdk/testing';

it('handles payment webhook', async () => {
  const { result, ctx } = await invokeWebhook(integration, 'payment-updated', {
    payment: { id: 'pay_123', status: 'succeeded' },
  });

  expect(result.status).toBe('processed');
  // ctx records fetchCalls, logs, and storage (ctx.dumpStorage()) for assertions
});
```

The host gate's `checks/tests` stage runs your packed test suite, so keep it green locally.

## 5. Publish (`ekanos publish`)

First, authenticate:

```bash theme={null}
ekanos login --host https://your-ekanos-host
```

Then list your access:

```bash theme={null}
ekanos sources
```

Set your target (`use` refuses a slug you hold no seat on):

```bash theme={null}
ekanos use my-source
```

Submit:

```bash theme={null}
ekanos publish
```

This:

1. Runs the same findings pass as `ekanos validate`, refusing with `gate_failed` (exit 10) on any error-severity finding
2. Packs `ekanos.json`, `package.json`, `README.md`, `src/**`, and your root `tsconfig*.json` and vitest/vite config
3. Submits the archive to the host
4. Exits once the submission is accepted — the gate runs asynchronously

`publish` does not run your tests locally. With several seats and a target taken implicitly from `ekanos.json`, a terminal run asks you to confirm; a scripted or JSON run needs `--source` or `--yes`. The first successful publish saves `host` and `source` to `ekanos.json`.

Watch progress:

```bash theme={null}
ekanos status --watch
```

The host gate runs stages against the archive's own config, including:

* `checks/typecheck` — your `tsc` against your packed `tsconfig.json`
* `checks/typecheck-host-rules` — a second pass under the host's stricter compiler rules
* `checks/tests` — your packed test suite

`status --watch` polls every 30 seconds and exits `0` when the version reaches `gated` or `dev`, or `10` (`gate_failed`) with the findings when it is `rejected`. `ekanos status --findings` shows every finding.

<Note>
  **The gate is not instant.** It runs asynchronously. Watch with `ekanos status   --watch` or come back later.
</Note>

## 6. Keep the toolchain current

Check whether a newer toolchain exists (read-only):

```bash theme={null}
ekanos upgrade --check
```

Upgrade with automatic rollback:

```bash theme={null}
ekanos upgrade
```

This:

1. Resolves a coherent target version set — from your logged-in host when available, else the npm registry
2. Snapshots `package.json` and the lockfile
3. Installs the target versions
4. Verifies with `ekanos validate` and your test script (`--no-verify` skips this)
5. Rolls back `package.json`, the lockfile, and `node_modules` if any step fails

`--yes` skips the interactive confirm and is required outside a real terminal.

## Common lifecycle issues

<AccordionGroup>
  <Accordion title="Definition validation throws at import time">
    This is correct behavior. `defineIntegration()` validates when the module is imported. The error message names the invalid path and what's wrong.
  </Accordion>

  <Accordion title="Harness won't start after scaffolding">
    Run `pnpm install`. The scaffold creates a `package.json` that needs a full
    install before `ekanos dev` passes its precondition check.
  </Accordion>

  <Accordion title="The ekanos.json slug disagrees with the definition">
    `ekanos validate` reports a `project.slug-agreement` error. The slug appears in two places and must agree:

    * In `ekanos.json`: `{ "slug": "my-integration" }`
    * In your definition: `defineIntegration({ slug: 'my-integration', … })`

    Make them match, then run `ekanos validate` again.
  </Accordion>

  <Accordion title="Validation passes locally but fails the host gate">
    Common causes: - **TypeScript rules drift** — `checks/typecheck-host-rules`
    compiles under stricter rules than a lax local `tsconfig.json`. Set `strict`
    and `noUncheckedIndexedAccess` to `true`. - **Config missing from the
    archive** — CLI versions before 0.1.10 did not pack `tsconfig.json` or the
    vitest config. Upgrade and republish. - **Toolchain skew** — Run `ekanos
          upgrade --check`.
  </Accordion>

  <Accordion title="I want to develop without publishing">
    Use `ekanos dev` to iterate locally, and skip `publish` until you're ready.
  </Accordion>
</AccordionGroup>

## Flow diagram

```
ekanos init
     ↓
    dev (loop: edit → reload → test)
     ↓
ekanos validate (check all rules)
     ↓
ekanos test (run your tests)
     ↓
ekanos publish (submit to host)
     ↓
host gate (typecheck, tests, …)
     ↓
users connect and use
```


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