---
title: "SDK"
url: "https://control.actana.ai/docs/reference/sdk"
description: "@actana/sdk: CoreClient, CoreSession, the durable client, pairing, and the file routes."
updated: 2026-09-01T09:03:22+00:00
---

[`@actana/sdk`](https://www.npmjs.com/package/@actana/sdk) is the Core client for Actana Control, and the core-link wire protocol it speaks: frame schema, protocol version, codec, transport. Node **22 or newer**. Published with provenance on the same tag as the images — the SDK, CLI, and images of one release move together.

```bash
npm install @actana/sdk
```

Source and the longer README: [github.com/actana/control/tree/main/packages/sdk](https://github.com/actana/control/tree/main/packages/sdk).

**Never log credentials.** A registration blob holds `clientKey`, PEMs, and the bearer. Treat it like a private key. The blob is what a paired client *holds*, not what a human carries.

## Pairing

Enrollment is a short pairing code from `actana pair new` on the Core — not a pasted blob. `pairWithCore` from `@actana/sdk/core-pairing` redeems it: fingerprint compared before the code is sent, private key generated locally and never sent. The full walkthrough, including `fetchCorePairingIdentity` for showing a fingerprint before anything is spent, is [SDK Pairing](/docs/pairing/sdk-pairing).

## Two layers, one socket

```js
import { CoreClient } from "@actana/sdk/core-client";
import { CoreSession } from "@actana/sdk/core-session";

const client = CoreClient.fromRegistrationBlob(blob, { connectTimeoutMs: 15_000 });
await client.connect();

const session = await CoreSession.start(client, {
  projectId,
  cwd,
  harness: "claude-code",
  prompt: "summarise this repo",
});
await session.waitForIdle({ timeoutMs: 300_000 });
console.log(session.screen());
```

`CoreClient` connects, authenticates, and correlates frames. It reconnects nothing. A long-lived consumer wants `@actana/sdk/durable-core-client` (heartbeat, backoff, event cursor). `CoreSession` starts a Session, lets the Core deliver the prompt, and reads the result. I/O is programmatic — `send(text)`, `onData(…)`, `screen()` — never a TTY.

Project files are `project.files.list` / `.upload` / `.download`: HTTPS on the same origin, certificate, and bearer as the socket, not the socket itself. Ask `client.canUseFileRoutes()` first.

## See also

- [Core link](/docs/architecture/core-link) — mTLS + bearer `auth` frame.
- [Filesystem](/docs/architecture/filesystem) — `project.files.*`.
- [HTTP surfaces](/docs/reference/http-surfaces) — no public REST write API.
- [Pairing](/docs/pairing) — mint the code this function redeems.
