Skip to main content
Run ekanos dev at the root of an Ekanos repo and you get repo mode: one harness for every package, at http://localhost:3100 unless you pass --port.
Run it inside one package instead and the harness serves only that package, exactly as a single project.

The repo home

/ is “This repo”. Along the top, five counts: Integrations, Experiences, Connected, No connection needed and Need connecting. Integrations lists one card per integration package:
  • its name, version and contract version;
  • a connection chip (below) and, if it is not connected yet, the kind of connection it needs: API keys, OAuth or Shipped config;
  • After publishing: the levels it can be connected at once published (Source, Team, Each person), from the integration’s declared levels;
  • Local store: where its credentials live, repo-relative;
  • a health cell with Check health (an integration that is not connected yet says “Not checked locally”), the connection controls, and Open console.
Experiences lists one card per experience package: its name and version, the integrations it uses with each one’s connection chip, a View button and a Connect checklist button. The old /connections page is folded into this home. /connections redirects to /. Each integration package keeps its console at /integrations/<name>, and each experience its view at /experiences/<name> with Summary, Widgets, Workflows, Review queue, Run log and Connect tabs.

One word for connection

Every screen in the harness (the repo home, the Connect tab, the experience checklist, the activation page, the OAuth panel) states a connection the same way, from one function that reads the contract’s auth, the keys the code declares, and OAuth. Next to the status, Live or Fixtures says what the integration answers from right now.

Connecting integrations

Connect an integration from wherever you are working. An experience’s Connect checklist (/experiences/<name>/connect) has one row per integration it uses; Connect and Edit open the integration’s form in a dialog (the activation form, the keys form, or the OAuth start), and Disconnect removes the stored values. The same controls are on the repo home and on an integration’s own Connect tab.

Where credentials are stored

Credentials are stored per integration, in the package’s own .ekanos/local-secrets.json:
  • The file is gitignored (.ekanos/ is), never packed by ekanos publish, and written with mode 0600.
  • An experience never gets a copy. It reaches the integration through its operations, and the harness runs the integration’s code with the credentials in the integration’s folder.
  • They last until you Disconnect. They survive a harness restart, a browser reload, and ekanos dev regenerating .ekanos/harness. Saving again replaces the old values.
  • For an integration with OAuth, the tokens go in the same file and are replayed through your onTokens handler when the harness starts, so you are not asked to authorize again. They are not replayed if the OAuth app’s client id changed.
  • Disconnect removes only that integration’s stored activation fields and API keys. It keeps the OAuth app’s own keys and the file’s 0600 mode, and leaves the form ready for new values.
Treat .ekanos/local-secrets.json as a secret. Don’t copy it into an issue or a chat, and never commit it.

OAuth on localhost

For an integration that declares oauth, register this redirect URL with the provider’s developer app:
<port> is the harness port (3100 by default) and <slug> is the integration’s slug. The Local OAuth panel on the Connect tab shows the URL with a Copy button, together with the scopes your definition declares. Save the client id and secret in the panel, then click Connect. See Live mode for the full loop.

Live or fixtures, per integration

There is no global Data selector in repo mode. Each integration decides for itself. Fixtures are fixtures/<integration>/<kind>-<op>.<default|empty|error>.json for the scenario you pick, and the example in the contract when there is none. On an experience view, every integration shows a chip such as acme-cms · live, acme-social · fixtures (not connected) or acme-news · live (no connection needed), with the matching controls. Pin to fixtures keeps an integration on fixtures even when it is connected, so you can build against stable data without disconnecting. The chip then reads “Fixtures · pinned” with “Saved for this repo”, and the button becomes Unpin. The pin is stored in .ekanos/local-state.json next to the integration’s other local files:
It is gitignored, separate from credentials, and survives a restart and the regeneration of .ekanos/harness. Disconnect does not clear it. Unpin removes it.
Live writes are real. On Live, a write operation approved in the approvals tray calls the real service: a draft is created, a post is published. Reads run live without asking; writes are always held for your approval first. Pin an integration to fixtures, or keep it unconnected, while you are building a workflow that writes.

Provenance

Each integration also says where it runs from:
  • Local · this repo: a package of this repo. It is not an override, and it never blocks publishing.
  • A local override in the experience’s ekanos.local.json: an integration folder outside the repo. The harness warns, because publishing is refused while one is active.
  • Registry: a published integration, resolved from the catalog or from a contracts folder.
See One repo, many packages.

Next steps