# CLI and SDK

Extend your engineering tools through the same typed platform operations used by the application.

Source: https://docs.openeng.io/developers/overview/

Use the CLI for interactive work and coding agents. Use the platform SDK's typed modules for an integration or automation.

Both operate on the shared engineering model. The platform authorizes each operation and validates the data it changes.

For your own hosted interface, see [Host your own app](https://docs.openeng.io/developers/external-apps.md). To use a coding agent to set up a model and demo data, follow [Bootstrap a tool with an agent](https://docs.openeng.io/agents/bootstrap-your-tool.md).

## Work with a coding agent

The CLI exposes help, input shapes and examples. Start with:

```sh
oe2 help
oe2 skill
```

The skill describes the workflow for orienting, defining types and writing data. Help supplies exact command shapes.

A coding agent can use these to help construct a programme model and populate an example. Give it the desired engineering workflow, then review the resulting definitions and changes.

## Local development checkout

With the repository's demo stack running:

```sh
pnpm dev:demo
```

In another terminal:

```sh
pnpm oe2 login
pnpm oe2 org list
pnpm oe2 org attach <organisation-id>
pnpm oe2 types list --project <project-id>
```

The local wrapper discovers the running demo stack. The CLI explicitly attaches to an organisation before working in it.

These commands describe the local checkout. Deployed-host CLI sign-in has a separate release dependency; check the CLI's help and package documentation for supported transports.

## What the SDK provides

The SDK is a set of TypeScript client modules for calling OpenEngineering's platform operations from your own code. Use it to build a custom interface, import engineering data, automate a workflow or connect another system. Calls use the same authorization, validation and change control as the workspace.

| Module | Repository package | Example operations |
|---|---|---|
| Objects | `@oe2/objects-sdk` | Read and query objects, traverse relationships, read structures and history, mutate data, execute verbs |
| Branches | `@oe2/branches-sdk` | Create branches, read diffs, submit proposals and merge |
| Ontology | `@oe2/ontology-sdk` | Open, revise, validate and accept type and view change sets |
| Administration | `@oe2/admin-sdk` | Manage organisations, projects, membership and service identities |
| Agents | `@oe2/agents-sdk` | Work with agent conversations and plans |

These are the current repository packages. A published installation guide depends on package distribution; the examples assume access to these workspace modules.

## Make an SDK call

For a Node backend, create an HTTPS transport and a module client with the API host origin and a platform access token. The client sends the protocol headers and serializes typed requests for you.

An object request separates **where to work** from **what to do**. The `selector` names the project and branch; `input` holds the operation's arguments. The server checks access using the token, including whether the caller may read that project and object.

```ts
import {
  createHttpsTransport,
  createObjectsTransportClient,
} from "@oe2/objects-sdk";

export async function readObject(config: {
  origin: string;
  accessToken: string;
  projectId: string;
  ref: string;
  objectId: string;
}) {
  const transport = createHttpsTransport(config.origin);
  const objects = createObjectsTransportClient(
    transport,
    config.origin,
    config.accessToken,
  );

  const answer = await objects.readObject({
    selector: { projectId: config.projectId, ref: config.ref },
    input: { objectId: config.objectId },
  });

  if ("refusal" in answer) {
    throw new Error(`Object read refused: ${answer.refusal.kind}`);
  }
  if ("replayed" in answer) {
    throw new Error("Expected an object read response");
  }
  return answer.result;
}
```

Use `main` to read accepted engineering data, or an accessible working branch ref to read proposed changes. Obtain the token through a supported platform session; [Host your own app](https://docs.openeng.io/developers/external-apps.md#authenticate-a-backend-integration) shows the service-identity exchange for a backend. Keep backend credentials and tokens in server-side code.

To work with another module, use its factory with the same transport, origin and token: `createBranchesClient`, `createOntologyClient`, `createAdminClient` or `createAgentsClient`, imported from that module's package.

## Discover operation shapes

The CLI also exposes the SDK's operation descriptions, input schemas and examples:

```sh
oe2 help objects-sdk readObject
oe2 help objects-sdk queryObjects
oe2 help objects-sdk mutate
oe2 help branches-sdk createBranch
oe2 help branches-sdk readBranchDiff
oe2 help ontology-sdk validateChangeSet
```

Use the client method's TypeScript types and the matching CLI help together. The module clients expose platform operations; the CLI supplies both convenience commands, such as `types draft`, and access to SDK operation descriptions.

The Objects module also has a `generate` utility that produces TypeScript source from a published catalogue snapshot. It creates model-specific property types and helpers for objects, edges and verbs. This is useful when you want code that knows your organisation's Requirement or Part fields. Its generated helpers use the Objects capability interfaces; the transport-client example above uses the general platform request shapes. Local schema validation and generated types help catch mistakes before submission, while the server remains responsible for accepting a change.

## Write through a branch

Start an integration with reads. For edits, create a branch through the Branches client, send mutations through the Objects client using that branch's ref, inspect the diff, and submit a proposal. Merge only when the platform's review and protection rules permit it. Configure types and views through the Ontology change-set workflow.

Handle each response according to the operation's contract:

- A confirmed result supplies the authoritative data for your app.
- A refusal explains why the platform rejected the request; preserve the user's draft and show the reason.
- An idempotent write may return a replay of a previously recorded outcome.
- An uncertain write needs recovery or inspection using its correlation identity before another attempt.

Transport failures can also throw. A failed connection is not evidence that a write had no effect. Preserve the operation's idempotency key and correlation information so you can resolve its outcome.

[Branching and change control](https://docs.openeng.io/guides/change-control.md) explains the review workflow. [Host your own app](https://docs.openeng.io/developers/external-apps.md) covers backend authentication and external hosting.
