Skip to main content
nativeharness is parts that compose, not a framework that composes them. There is no Harness.create(); you construct each layer and hand it the ones below. This is what the assembly looks like, and then what each line is for.
Construct one of each per process. The store holds open database handles; the provider holds an engine connection and a reap timer; two of either is two of everything.

Four contracts nothing else tells you

These were found by writing the CLI — the first consumer to assemble the layers from outside a test. Every one is a compile error in TypeScript and a confusing runtime failure without it. Events takes the store. It has no useful default. Miss it and the failure is Cannot read properties of undefined (reading 'appendEvents') from inside an emit, several layers below your code. Actor is a string. Not an object. Pass { kind: "user", id } to a store method and better-sqlite3 reads it as a named-parameter binding, and fails with an arity error that names nothing. A commit is credited to a FileCommitAuthor. { by: { kind: "actor", id: "user-42" } } — or execution, or import. Not a name. A workspace whose permissions do not name the actor cannot run commands in it. That is correct — it is how one user’s agent is kept out of another user’s workspace — but it means creating a workspace is not enough. Grant the actor at creation:

Mapping to your users

The harness has no users table and wants none. An actor is whatever string identifies a principal in your system — a user id, a service account, a tenant. You decide the mapping:
  • one workspace per user, per project, or per conversation
  • which actors may work in each, with what scope and what mode
  • which connector credentials each actor holds
Your users covers this in detail.

Lifecycle

Call both at shutdown. A short-lived process — a CLI, a job — should pass reapIntervalMs: 0 to the provider so a timer never fires mid-command, and call sandbox.reap() by hand if it wants to.

Without a model

core has no LLM in it. If your application drives its own loop, or just wants sandboxed, versioned, auditable command execution, stop at BashTool:
Every guard, the sync report, the execution record and the events all still apply.

What you still own

The harness draws a line at product features: no billing, scheduling, notifications, retrieval, user management or domain validators. Those are yours, above the harness, and the approval policy and connector permissions are the hooks they attach to.