Getting Startedquickstart
Quickstart
Install the package, define the SDK once, and pick the correct runtime entry point before doing anything else.
`npm install clivly``connect()``start()` vs `runScheduled()`
Install
Install the package, define the SDK once, then pick the runtime entry point that matches your host.
terminal
npm install clivly
# optional peers, only when your app uses them
npm install drizzle-orm
npm install vite
npm install @clerk/backend
npm install @workos-inc/nodeterminal
npm create clivly- Install the default (`latest`) tag — that is the supported line these docs describe.
- `npm create clivly` scaffolds a fresh app and hands straight into `init`.
- Once installed locally, plain `npx clivly …` uses the workspace copy rather than re-fetching.
- `clivly@next` exists for prereleases. Only reach for it when you need something that has not shipped to `latest` yet.
Define the SDK once
Constructing the SDK is pure. Nothing connects until you call an entry point.
clivly.config.ts
import { createClivlySDK, defineClivlyConfig } from "clivly/sdk";
import { discoverFromDrizzle, fromDrizzle } from "clivly/drizzle";
import { db, participants, accounts } from "./db";
import * as schema from "./db/schema";
const entities = defineClivlyConfig({
entities: {
participants: {
concept: "contact",
source: "participants",
fields: { name: "full_name", email: "email" },
},
accounts: {
concept: "company",
source: "accounts",
fields: { name: "legal_name", domain: "website" },
},
},
});
export default createClivlySDK({
apiKey: process.env.CLIVLY_SECRET_KEY ?? process.env.CLIVLY_API_KEY!,
entities,
schema: discoverFromDrizzle(schema),
source: {
contacts: fromDrizzle(db, participants, {
entity: "participants",
cursorField: "updatedAt",
}),
companies: fromDrizzle(db, accounts, {
entity: "accounts",
cursorField: "updatedAt",
}),
},
syncTrigger: {
path: "/api/clivly/tick",
url: process.env.CLIVLY_SYNC_TRIGGER_URL,
secret: process.env.CLIVLY_SYNC_TRIGGER_SECRET,
},
});Choose the runtime entry point
The right call depends on whether the host is long-lived, request-scoped, or just validating credentials.
runtime.ts
const status = await clivly.connect();
if (!status.ok) throw new Error(status.reason);
await clivly.start(); // long-lived Node / Vite dev only
await clivly.runScheduled(); // one-shot cron/serverless run
export const POST = (request: Request) =>
clivly.createClivlyHandler()(request);- `connect()` is the one-shot health check and returns structured status.
- `start()` is for long-lived Node processes and Vite dev only.
- `runScheduled()` and `createClivlyHandler()` are the production path for serverless and edge runtimes.
Start of the docs flow
You are at the earliest guided section.
Next
CLI