Protocol Reference
All messages are UTF-8 JSON text frames unless noted as binary. Fields marked ? are optional.
Client → server messages
Section titled “Client → server messages”compile.start
Section titled “compile.start”Opens a compile session. Must be the first message sent on a new connection.
{ "type": "compile.start", "api_key": "pk_live_...", "entry": "src/main.ts", "release": true, "target": "binary"}| Field | Type | Description |
|---|---|---|
api_key | string | Your Pure API key. See Authentication. |
entry | string | Relative path within the tarball to the TypeScript or JavaScript entry point. |
pre_command? | string | Shell command to run before compilation (e.g. pnpm install --frozen-lockfile). Runs inside the extracted tarball directory. If omitted, Pure auto-detects the right install command from your lockfile — see Default install command below. |
release? | boolean | true for an optimized release build; false (default) for a debug build. |
target? | "binary" | "node-addon" | Output format. "binary" (default) produces a standalone native executable. "node-addon" produces a Node.js native addon (.node) packaged as an installable npm tarball — see Node addon target below. |
env? | object | Environment variables passed into the compile sandbox (key/value strings). Reserved keys like PATH, HOME, LD_PRELOAD, NODE_OPTIONS are rejected. Max 64 vars, 32 KB total, 4 KB per value. |
sandbox_mem_gib? | number | Memory ceiling for the compile sandbox (GiB). Clamped to the platform maximum if exceeded. |
Default install command
Section titled “Default install command”If you don’t supply pre_command, Pure inspects the root of your tarball and runs the right install command for the package manager whose lockfile is present:
| Lockfile | Command |
|---|---|
bun.lockb or bun.lock | bun install --frozen-lockfile (requires bun in your pre_command — Pure does not pre-install it) |
pnpm-lock.yaml | pnpm install --frozen-lockfile |
yarn.lock | yarn install --frozen-lockfile |
package-lock.json | npm ci |
package.json only | npm install |
| (none) | nothing — installation is skipped |
Submit your own pre_command whenever you need a different command (e.g. enabling optional flags, installing bun, running a build step before Pure compiles, or pulling private deps with a token). Your custom pre_command has full outbound internet access, so curl | bash-style installers from any origin work.
Node addon target
Section titled “Node addon target”When target is "node-addon", Pure produces a Node.js native addon instead of a standalone binary. The artifact returned via download_url is an npm tarball you install with:
npm install ./your-package-0.1.0.tgzThe package has the same name and version as the package.json at the root of your uploaded tarball, plus a .node file and a thin index.js shim that re-exports its surface. Your existing TypeScript types (*.d.ts) are preserved.
Use this when you want to ship a Pure-compiled module that other Node code can require() — without rewriting consumers around a separate binary.
Binary frames
Section titled “Binary frames”After compile.start and before compile.upload.done, send the source tarball as one or more binary WebSocket frames. The server concatenates all frames in order.
The tarball must be a .tar.gz (gzipped tar archive) containing your project at the root level, not wrapped in an extra directory.
You may split the tarball across any number of frames. Typical usage is a single frame for small projects and multiple 64 KiB frames for larger ones.
compile.upload.done
Section titled “compile.upload.done”Signals the end of the tarball upload.
{ "type": "compile.upload.done", "total_bytes": 81920, "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}| Field | Type | Description |
|---|---|---|
total_bytes | number | Total byte count of the uploaded tarball. |
sha256 | string | Lowercase hex SHA-256 of the complete tarball. |
Sending compile.upload.done a second time on the same session is a no-op — the server ignores duplicate signals.
jobs.list
Section titled “jobs.list”Request a list of recent jobs for an organization.
{ "type": "jobs.list", "org_id": "org_abc123", "limit": 20}| Field | Type | Description |
|---|---|---|
org_id | string | Organization ID (visible in the dashboard under Settings). |
limit? | number | Maximum jobs to return. Defaults to 20; maximum 100. |
jobs.subscribe
Section titled “jobs.subscribe”Subscribe to real-time events for a specific job. If the job is already finished, the server replays stored events immediately.
{ "type": "jobs.subscribe", "job_id": "job_xyz789"}Server → client messages
Section titled “Server → client messages”compile.queued
Section titled “compile.queued”Sent when the job is accepted and placed in the compile queue.
{ "type": "compile.queued", "job_id": "job_xyz789", "position": 2}| Field | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this compile job. Use it for jobs.subscribe and jobs.list. |
position | number | 1-based position in the queue. Position 1 means the job is next to run. |
compile.started
Section titled “compile.started”Sent when a worker picks up the job and begins processing it.
{ "type": "compile.started", "job_id": "job_xyz789", "step": "compiling"}| Field | Type | Description |
|---|---|---|
job_id | string | Job identifier. |
step | "pre_command" | "compiling" | "pre_command" if the worker is running the pre-compilation shell command; "compiling" when the actual compilation is underway. |
compile.log
Section titled “compile.log”A line of compiler output. Emitted zero or more times during compilation.
{ "type": "compile.log", "job_id": "job_xyz789", "line": "Compiling pure_hello v0.1.0", "ts": 1714000012345}| Field | Type | Description |
|---|---|---|
job_id | string | Job identifier. |
line | string | One line of compiler output (no trailing newline). |
ts | number | Unix timestamp in milliseconds when the line was emitted. |
compile.done
Section titled “compile.done”Sent when compilation succeeds.
{ "type": "compile.done", "job_id": "job_xyz789", "download_url": "https://...", "expires_at": 1714003600000, "work_units": 1280}| Field | Type | Description |
|---|---|---|
job_id | string | Job identifier. |
download_url | string | Presigned URL to download the compiled binary. |
expires_at | number | Unix timestamp (ms) when download_url expires. |
work_units | number | Metered usage consumed by this job. See Billing. |
compile.error
Section titled “compile.error”Sent when compilation fails or an error occurs during the session.
{ "type": "compile.error", "job_id": "job_xyz789", "message": "human-readable description", "code": "JOB_FAILED"}| Field | Type | Description |
|---|---|---|
job_id? | string | Job identifier, if a job was created before the error. |
message | string | Human-readable error description. |
code? | string | Machine-readable error code. See Errors. |
jobs.list.result
Section titled “jobs.list.result”Response to a jobs.list request.
{ "type": "jobs.list.result", "jobs": [ { "id": "job_xyz789", "org_id": "org_abc123", "status": "succeeded", "entry": "src/main.ts", "created_at": 1714000000000, "finished_at": 1714000030000, "work_units": 1280 } ]}Job status is one of: queued, running, succeeded, failed.
auth.error
Section titled “auth.error”Sent when authentication fails. The connection is closed immediately after.
{ "type": "auth.error", "message": "key has been revoked", "code": "KEY_REVOKED"}See Authentication for all auth error codes.
Message ordering
Section titled “Message ordering”Client Server │──── compile.start ──────────▶│ │──── [binary frame(s)] ───────▶│ │──── compile.upload.done ─────▶│ │ │◀── compile.queued │ │◀── compile.started (step: pre_command) [optional] │ │◀── compile.started (step: compiling) │ │◀── compile.log [0..N] │ │◀── compile.done OR compile.error │ (close or start new job)The server may send compile.error at any point — including before compile.queued if the tarball is malformed or exceeds size limits.