HarborHarbor
DocumentationGuidesPlugins

createHarborClient

Create the Promise-first TypeScript client and choose the right SDK layer.

The public application entrypoint is createHarborClient from @hrbr/client. @hrbr/sdk is the composite system facade for Harbor-owned runtime, platform, plugin, protocol, registry, Orbit, and control-plane contracts.

App client

Most application code should import from @hrbr/client:

api-key-client.ts
import { createHarborClient } from '@hrbr/client'

const harbor = createHarborClient({
  baseUrl: 'https://api.tryharbor.ai',
  workspaceId: process.env.HARBOR_WORKSPACE_ID!,
  auth: { kind: 'api_key', key: process.env.HARBOR_API_KEY! },
})

const workspaces = await harbor.workspaces.list({ limit: 25 })
const run = await harbor.runtime.execute({
  code: 'return { ok: true }',
})

console.log(workspaces.data.length)
console.log(run.run_id)

API-key clients require workspaceId at construction because the API key is workspace-scoped. Bearer clients can list visible workspaces first and bind a workspace later:

bearer-client.ts
const harbor = createHarborClient({
  baseUrl: 'https://api.tryharbor.ai',
  auth: {
    kind: 'bearer',
    tokenProvider: async () => await getCurrentAccessToken(),
  },
})

const selected = await harbor.workspaces.list({ limit: 10 })
const workspace = harbor.workspace(selected.data[0]!.id)
const sources = await workspace.sources.list({ limit: 25 })

The SDK does not persist browser cookies, refresh tokens, or local CLI auth state. The host app owns login/session storage and passes the current credential into the client.

Effect variant

Effect-native hosts import the explicit subpath:

effect-client.ts
import { Effect } from 'effect'
import { HarborClient, createHarborEffectClient } from '@hrbr/client/effect'

const harbor = createHarborEffectClient({
  baseUrl: 'https://api.tryharbor.ai',
  workspaceId: process.env.HARBOR_WORKSPACE_ID!,
  auth: { kind: 'api_key', key: process.env.HARBOR_API_KEY! },
})

const run = await Effect.runPromise(
  harbor.runtime.execute({ code: 'return { ok: true }' })
)

const layer = HarborClient.layer({
  baseUrl: 'https://api.tryharbor.ai',
  workspaceId: process.env.HARBOR_WORKSPACE_ID!,
  auth: { kind: 'api_key', key: process.env.HARBOR_API_KEY! },
})

Promise-only apps do not need Effect. The peer dependency is optional unless you import the Effect subpath.

Raw protocol access

The composed resource groups are the normal SDK surface. Use harbor.api or @hrbr/client/generated/harbor when you need direct protocol-level access:

generated-protocol.ts
import type { Workspace } from '@hrbr/client/generated/harbor'

const openapi = await harbor.api.getHarborOpenApi()
const workspaces = await harbor.api.listWorkspaces({
  limit: 25,
  include_total: true,
})

const selected: Workspace = workspaces.data[0]!
const detail = await harbor.api.getWorkspace({
  workspace_id: selected.id,
})

System facade

Use @hrbr/sdk when you are building Harbor system surfaces, publish pipeline checks, local platform adapters, or code that needs stable Harbor namespaces:

system-surface.ts
import { Agents, Core, Orbit, Platform, Plugins, Protocol, Registry, Runtime } from '@hrbr/sdk'
import { ROUTES } from '@hrbr/sdk/core/control'

console.log(ROUTES.exec)
console.log(Core.ROUTES)
console.log(Runtime.Core.RuntimeExecutionMode)
console.log(Platform.Local.LOCAL_HARBOR_FRONTEND_SCRIPT_PATH)
console.log(Protocol.harborOpenApiDocument.info.title)