Skip to content

SDK download & install

Available SDK artifacts, the MCP server and the conformance badge are hosted as downloads on the CloakAPI site rather than public code registries. SDK artifact and installation status varies by language; check the table below before choosing an archive. This is consistent with CloakAPI’s local-first architecture and means you can build on CloakAPI without an npm / PyPI / crates.io / Packagist / RubyGems / NuGet account when an artifact is listed.

Need the browser extension or desktop app instead of an SDK? Install the extension from the Chrome Web Store or load the zip from Downloads (install steps). The Windows and Linux desktop builds are on the same page (Desktop); macOS is still coming.

Where to download

All artifacts live under app.cloakapi.io/downloads/sdks/. The human-readable SDK downloads page lists tip packages; the machine-readable manifest.json is the source of truth for every file, URL and sha256. The same files are linked from the portal Developers page.

Native engine platform support (measured 2026-09-30)

The source archives and language bindings do not mean that a native engine for each host is available. For SDKs that use libcloak_engine, this is the measured artifact boundary:

Host/runtimeCurrent engine artifactResult
Linux x86-64, glibcStandalone engine/libcloak_engine.so, ELF x86-64; loaded by the Python source SDK on Ubuntu glibc 2.39.Python source can use it through CLOAKAPI_ENGINE_LIB on that host. Other FFI bindings and glibc floors were not executed.
Linux aarch64, glibc ≥ 2.39Served Python 0.4.0 wheel has superseded engine c135d3f8…. The build tool refuses it, but the hosted runtime may load it. No current standalone ARM engine was found.Source 0.4.1 refuses the digest at runtime. File/image calls include it in EngineError; text raises ReducedCoverageError by default. Version 0.4.1 is not built or released.
macOS, Windows, Linux musl/Alpine, other CPU architecturesNo compatible shared library in the manifest.FFI text and file/image features cannot claim a working native engine. The SDKs report their engine-unavailable fail-closed error.
Browser TypeScriptTypeScript 1.3.29 includes the browser WASM asset and no shared library.Browser uses the WASM build; this is separate from Node FFI.

The served Ruby 1.3.0 gem also contains an embedded shared library with digest c965a946…, listed as withdrawn by the current Python wheel builder. Ruby source version 1.3.1 refuses to package that digest, but the hosted 1.3.0 gem remains stale. Do not use its bundled engine for engine-backed features. The Ruby source loader accepts CLOAKAPI_ENGINE_LIB, but that path was not executed here; the listed Linux x86-64 library was loaded only through the Python source SDK. A listed artifact is not evidence that its embedded native binary is current.

When the shared engine is unavailable, maintained source returns these file-call errors. The Python failure path was executed here; the other rows were checked in source and were not run on each target host:

SDKMissing-engine result
Python 0.4.1 sourceEngineError, starting CloakAPI cannot tokenise a file or image on-device on this platform (...); it names the checked paths, CLOAKAPI_ENGINE_LIB, download/build steps, and confirms that file/image bytes were not sent.
Goerror.Error() and %v return cloakapi/engine: operation failed. The longer install sentence is stored on EngineError.Msg and is not what Error() prints.
Java, PHP, Ruby, .NETEngine-specific error beginning client-side engine (libcloak_engine) not available — refusing to send the raw file/image to the gateway.
TypeScript / NodeEngineError: client-side engine (libcloak_engine) not available.
Rust regex-fallback buildEngineError::Refused: native engine not built — on-device file tokenisation is unavailable in the regex-fallback build; suggests rebuilding with --features native-engine.

Read-only registry GETs on 2026-09-30 returned HTTP 404 ×3 for PyPI cloakapi, npm @cloakapi/sdk, Go proxy github.com/cloakapi/cloakapi-go, Maven io.cloakapi:cloakapi-sdk, Packagist cloakapi/cloakapi-php, RubyGems cloakapi, crates.io cloakapi, and NuGet CloakAPI.Sdk.

JSON tool-call argument values

OpenAI tool_calls[].function.arguments carries JSON as a string. The literal integer spelling {"card":4111111111111111} and string spelling {"card":"4111111111111111"} are handled differently across the SDKs. These results were measured on 2026-09-30 with the 4111111111111111 card test value; they describe the observed request transformation and do not promise that other PII values will be detected.

Known limitation for Python, PHP, and Ruby: the measured literal integer {"card":4111111111111111} stayed unchanged as a number. If the tool accepts a string, send {"card":"4111111111111111"}; this same test value was tokenised in the string form and the argument JSON stayed valid, but the tool receives a string. The result covers only the integer spelling shown.

SDKCard as the literal JSON integerSame card as a literal JSON string
Python, PHP, RubyThe number stays unchanged and reaches the gateway raw; argument JSON remains valid.A detected value is tokenised inside the quotes; argument JSON remains valid and the tool receives a string.
TypeScript / Node, Java, .NETA detected value is replaced by an unquoted token; the argument string is invalid JSON.The token remains inside the quotes; argument JSON remains valid and the tool receives a string.
Go, RustCurrent typed request models do not expose tool_calls[].function.arguments; this vector cannot be sent through those APIs.Current typed request models do not expose tool_calls[].function.arguments; this vector cannot be sent through those APIs.

The numeric results cover only the literal integer spelling shown in the table. Separate decimal and exponent spelling probes produced different outcomes across SDKs and are not represented here.

The .NET result uses its ChatMessage.ToolArguments SDK field, serialized as tool_arguments; it is not the standard OpenAI tool_calls structure. The TypeScript result covers the Node entry; the browser entry was not tested for this vector in this pass. An additional wire spelling was measured three times per SDK: the same card string with its digits written as JSON Unicode escapes (\u0034...). Python, PHP and Ruby decoded and tokenised that value, keeping the argument JSON valid. TypeScript/Node, Java and .NET forwarded the escapes unchanged; the argument JSON stayed valid but decoded to the raw card value. This does not change the literal string results in the table above. The .NET path still uses its SDK-specific ChatMessage.ToolArguments field. For Python, PHP and Ruby, encode the value as a JSON string if the tool accepts that type; number leaves are not tokenised by those SDKs. In TypeScript, Java and .NET, string form keeps the argument JSON valid, but changes the value type the tool receives. The gateway does not detect or tokenise these values.

For each package there is a native installable (where the toolchain produces one cleanly) and a universal source .zip fallback. Verify any download against the sha256 in manifest.json:

Terminal window
sha256sum ./cloakapi-go-1.2.0-src.zip
# compare against the value in manifest.json — only hash a file you actually downloaded

Per-language install

TypeScript / Node.js

Tip 1.3.29 is live on the downloads page and listed under languages.typescript in manifest.json (measured from the wire 2026-09-26; http_status: 200):

PackageDownloadSHA-256Install
npm tarballcloakapi-sdk-1.3.29.tgzf92c4bffd8a506c30b8745655626e2a9cc4a83b2ce3c423b85dcb2079469f269npm install ./cloakapi-sdk-1.3.29.tgz
Source zipcloakapi-sdk-typescript-1.3.29-src.zipeef07766be5ec091bbf66a166a34f7b33438bce75e3ef8e1517ec4a8a6082dc2unzip … && cd typescript && npm install && npm run build
Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/typescript/cloakapi-sdk-1.3.29.tgz
# verify sha256 against manifest.json, then:
npm install ./cloakapi-sdk-1.3.29.tgz

Withdrawn tip predecessor: /downloads/sdks/typescript/cloakapi-sdk-typescript-1.2.2-src.zip answers HTTP 410 Gone (measured from the wire 2026-08-24; still 410 on 2026-09-26). Do not curl -O that URL, and do not build from a copy you already have: the engine it bundles (sha256 5590766a…) uses an ASCII-only class for personal names. ⛔ An earlier line on this page said “HTTP 404, measured 2026-08-20”. That measurement is left standing rather than rewritten (Q64) — it was true on its date, and the file was republished and served 200 before it was withdrawn. It remains under the top-level withdrawn key of manifest.json.

⛔ CORRECTION BESIDE — 2026-09-26. A paragraph above this section previously said there was no longer a typescript entry in manifest.json and told you to install only from the source tree. That was true when 1.2.2 was the last offered build and had been withdrawn. 1.3.29 restored a languages.typescript entry (tarball + source zip). Prefer the tip files above; the source-tree fallback (cd sdk/typescript && npm install && npm run build) remains valid for contributors who already have the repo.

After the m970 patch lands, the TypeScript request path will also tokenise messages[].name, stop, stop_sequences, and JSON Schema prose in response_format.json_schema (name, description, and schema descriptions), alongside its existing system, tool_calls, and metadata handling. The patch is not in this checkout, so this is not a claim about the currently listed 1.3.29 archive. It also does not establish the same field coverage in other SDKs.

Custom relays — the mandatory residual scan

The supported browser path is createFailClosedRelay(), which performs the whole Level-1 round-trip (tokenise/splice → cloak-disclosure → pre-tokenised MAC → blind relay → on-device detokenise) and, on the final egress bytes, runs residualRawPII() plus a raw-card backstop. If either finds something, the relay throws and nothing is sent.

import { createFailClosedRelay } from "@cloakapi/sdk/browser";
declare const engine: unknown;
declare const messages: unknown;
declare function showReviewDialog(egressBody: string): Promise<boolean>;
declare const review: {
spans: unknown;
ner: { status: "ok"; person: "ran"; org: "ran"; loc: "ran" };
surrogateMode: { mode: "balanced"; continuity: "single-message" };
};
const relay = createFailClosedRelay({
baseUrl: "https://api.cloakapi.io",
apiKey: "cloak_…",
engine,
reviewedSpans: review.spans, // the ONE reviewed detection pass
detectionCoverage: review.ner,
surrogateMode: review.surrogateMode,
reviewRequest: async (egressBody) => {
const approved = await showReviewDialog(egressBody);
return { approved: approved === true, text: egressBody };
},
});
const reply = await relay.messages.create({ model: "claude-sonnet-4-6", messages });

Many real apps cannot use it verbatim — they stream SSE, or they POST to their own server route so the browser never holds the API key. That is fine, but the residual scan is not optional. Re-implement it explicitly, immediately before the send:

import { residualRawPII } from "@cloakapi/sdk/browser";
declare function showReviewDialog(egressBody: string): Promise<boolean>;
// `reviewedSpans`: the spans from the SAME detection pass whose surrogates you
// spliced — each carries its raw `original` and the reviewed `surrogate`.
const bytes = JSON.stringify({ model, messages }); // EXACTLY what you will POST
const residual = residualRawPII(bytes, reviewedSpans);
if (residual.length > 0) {
// FAIL CLOSED — refuse the send, tell the user honestly.
return { ok: false, reason: "A sensitive value survived the on-device cloak, so nothing was sent." };
}
const approved = await showReviewDialog(bytes);
if (approved !== true) {
return { ok: false, reason: "The exact egress string was not approved, so nothing was sent." };
}
const resp = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: bytes,
});

Why this is the last line of defence: detection can miss a value, a value-based splice can fail to match after the text was re-framed, and a stale or half-loaded engine can leave a raw card in place. Every one of those failures is invisible at the UI layer and shows up only in the bytes that leave the device.

  • Scan the final serialised body, not one message’s content and not the pre-splice text — a leak arriving via the system prompt, an attachment or a tool-call argument is only visible there.
  • Refuse to send; do not warn and continue.
  • Surrogates are masked out first, so a raw value that appears only inside a surrogate you just wrote is never a false positive.
  • Pass the spans from the same reviewed pass — scanning against an empty span list proves nothing.

Python

The latest measured files are:

HostCurrently served 0.4.0 filesSource changes for 0.4.1 (not released)
Linux x86-64, glibcNo x86-64 wheel (expected URL HTTP 404 ×3). The sdist has no engine. Separate x86-64 libcloak_engine.so loaded on Ubuntu glibc 2.39; set CLOAKAPI_ENGINE_LIB to use it.Without an engine, text raises ReducedCoverageError by default. tokenize_file() raises an actionable EngineError with platform and fix steps, and confirms bytes were not sent.
Linux aarch64, glibc ≥ 2.39Served 0.4.0 wheel contains superseded digest c135d3f8…; the build tool refuses it, but hosted 0.4.0 may load it. No standalone current ARM engine is listed.Source 0.4.1 refuses this digest. Text raises ReducedCoverageError by default; tokenize_file() raises EngineError with the rejected digest and fix steps.
macOS, Windows, musl/Alpine, other CPU architecturesNo compatible engine was listed or verified. In served 0.4.0, attachments= with CLOAKAPI_ALLOW_REDUCED=1 forwards raw file bytes; do not use that path.Source 0.4.1 makes attachments= raise AttachmentReviewRequiredError before a request. Use tokenize_file(), review returned text, then send it in messages.

The source distribution can be installed without an engine. For a measured Linux x86-64 host, download and verify the .so against manifest.json, then:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/python/cloakapi-0.4.0.tar.gz
curl -O https://app.cloakapi.io/downloads/sdks/engine/libcloak_engine.so
pip install ./cloakapi-0.4.0.tar.gz
export CLOAKAPI_ENGINE_LIB="$PWD/libcloak_engine.so"

The exact error for an unavailable file engine begins CloakAPI cannot tokenise a file or image on-device on this platform (...). It reports that no compatible libcloak_engine was found, tells you where the SDK looked, provides the download page and setting name, and confirms: File and image bytes were not sent. CLOAKAPI_ALLOW_REDUCED affects text only.

Source version 0.4.1 makes the convenience attachments= argument raise AttachmentReviewRequiredError before sending because it has no step to expose tokenised text for review. Served 0.4.0 with CLOAKAPI_ALLOW_REDUCED=1 forwards raw attachment bytes. Avoid that path. Use client.tokenize_file(...), review the returned text, then send that reviewed text in messages.

Historical measurements (kept with their dates, Q64): the 2026-08-20 request observed 404 for the Python wheel, sdist and source zip. The 2026-09-25 request observed 200 for the aarch64 wheel, sdist and source zip, and 404 for the expected x86-64 wheel. On 2026-09-30 the served aarch64 wheel was inspected; its engine binary does not match the current accepted engine identity. These dates are separate observations, not a claim that the earlier 404 persists.

Withdrawn: cloakapi-0.3.1-py3-none-any.whl and every earlier py3-none-any wheel are withdrawn and removed. They installed cleanly on macOS, Windows and Linux/ARM, could not load the engine there, and ran the reduced lane without saying so.

Go

Go is source-based — there is no binary artifact. Download the source zip and use a local module replace directive:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/go/cloakapi-go-1.2.0-src.zip
unzip cloakapi-go-1.2.0-src.zip # yields ./go
go.mod
module example.com/app
go 1.22
require github.com/cloakapi/cloakapi-go v1.2.0
replace github.com/cloakapi/cloakapi-go => ./go

Then go mod tidy && go build. Vendoring the ./go directory works too.

Rust

The crate has a workspace path dependency, so it ships as a source zip and is used as a path dependency rather than a .crate:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/rust/cloakapi-rust-1.2.0-src.zip
unzip cloakapi-rust-1.2.0-src.zip # yields ./rust
Cargo.toml
[dependencies]
cloakapi = { path = "./rust" }

Java

Java ships as a source zip with the bundled build.gradle.kts. It depends on Jackson (databind) and JNA; build it with Gradle in your own environment:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/java/cloakapi-java-1.2.0-src.zip
unzip cloakapi-java-1.2.0-src.zip # yields ./java
cd java && ./gradlew build # produces the jar under build/libs/

(No pre-built jar is shipped because the box that packages the SDKs has no Gradle/Maven to resolve those third-party dependencies — build it where your toolchain lives.)

.NET

A .nupkg is shipped. Add the folder you downloaded it to as a local NuGet source:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/dotnet/CloakAPI.Sdk.1.2.0.nupkg
dotnet add package CloakAPI.Sdk --source $(pwd)

Source fallback: cloakapi-dotnet-1.2.0-src.zip → unzip, then dotnet add reference dotnet/src/CloakAPI.Sdk/CloakAPI.Sdk.csproj.

PHP

Install via a Composer path repository:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/php/cloakapi-php-1.3.1-src.zip
unzip cloakapi-php-1.3.1-src.zip # yields ./php
{
"repositories": [{ "type": "path", "url": "./php" }],
"require": { "cloakapi/cloakapi-php": "*" }
}

Then composer install.

Ruby

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/ruby/cloakapi-1.3.0.gem
gem install ./cloakapi-1.3.0.gem

Source fallback: cloakapi-ruby-1.3.0-src.zip → unzip, then cd ruby && bundle install && gem build cloakapi.gemspec.

File and image inputs

The SDK attachment types and helpers are request-shape utilities in TypeScript and Rust; they do not extract, tokenise, or review file content. Those helpers encode bytes and apply local size and extension checks. They are for the local-proxy attachments[] shape, not a gateway file-processing API. The gateway does not convert or tokenise raw attachment bytes, and a proof header does not show that a client processed them. Do not send raw attachments directly to api.cloakapi.io.

The .NET TokenizeFile helper is available for local file processing. It returns a content candidate but does not require an application to display or approve the exact text before sending. Detection can miss details; review the content before egress.

The separate browser SDK exposes extractFileForReview for supported file types. It returns a local candidate; it does not force an application to display that content or to send only the text a user approved. An application using it must show the prepared content and enforce approval of the exact text sent. The local proxy attachment path has no review screen or approval gate, so it does not meet that requirement by itself. See the file and image handling guide for the limits and current client paths.

CloakAPI’s structured detectors (email, phone, card, government IDs, …) are exact and always on. Person names are detected in two layers:

  • Built-in name list (baseline, always on, free). The engine ships an embedded name dictionary — the same one the browser SDK loads as its enhanced list (26,420 given names and 13,045 surnames) — with strict precision guards. On our detection benchmark (one synthetic corpus: 320 texts, 40 languages, 320 gold person names; run 2026-07-25 on engine 1.4.29) it caught 52.2% of person names at 84.8% precision (it does not mis-tokenise capitalised non-names like “Monday”, “London” or “United Nations”). No model, no network, no download.
  • Neural name model (recommended for best coverage). Loading the optional on-device NER model raised name recall to 95.3% (precision 88.9%) in the same run, including many non-Latin and uncommon names the list misses. We recommend enabling it for any workload where names matter. It runs fully on-device (multilingual BERT, ONNX, ~178 MB, download-on-first- use); enable it by using an engine built with the ner_onnx feature / with the NER model present, and point CLOAKAPI_ENGINE_LIB at that engine.

MCP server

The @cloakapi/mcp-server exposes CloakAPI’s tool surface to any MCP host (Claude Desktop, Cursor, agent frameworks). Install the packed tarball:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/mcp/cloakapi-mcp-server-0.4.1.tgz
npm install -g ./cloakapi-mcp-server-0.4.1.tgz

Then reference it in claude_desktop_config.json (point command at the installed cloakapi-mcp binary, supply your CLOAKAPI_API_KEY). See Choose your integration for the config block. A source zip (cloakapi-mcp-server-0.4.1-src.zip) is also available. Version 0.4.0 is withdrawn and its URL answers HTTP 410 (measured from the wire 2026-09-25).

Conformance badge

@cloakapi/conformance checks the signed receipts and declared metadata your integration submits. A passing result does not inspect the deployed client or prove that tokenisation ran before you display the “Verified by CloakAPI” badge:

Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/conformance/cloakapi-conformance-0.1.0.tgz
npm install ./cloakapi-conformance-0.1.0.tgz

See Verify + get the badge for the governance rules.

Starter-kit

The forkable private-AI chat starter-kit (Apache-2.0) is intended to be distributed the same way — a self-contained tarball that vendors the WASM engine, the shared receipt + patterns packages and the TypeScript SDK, so npm install needs no registry.

See the quickstart in Choose your integration → Starter-kit.

The kit relays through its own /api/chat route rather than createFailClosedRelay(), so it ships the residual scan explicitly: src/lib/residual.ts (residualRawPII) is called in src/lib/relay.ts on the serialised body immediately before fetch, and a hit aborts the send. If you fork the kit and change the transport, keep that call — see Custom relays.

Veil review layer (review-core, review-ui, veil-tokens)

The pre-send cloaking review experience — “see exactly what leaves your machine, decide per span, then send” — is packaged as three small Apache-2.0 packages so an external app can offer the same review UX CloakAPI’s own surfaces use:

  • @cloakapi/review-core — the framework-agnostic review state machine over @cloakapi/sdk’s browser lane: a source-segmented review manifest, per-source / per-span keep/reveal decisions, the “exact assembled prompt” projection, and a fail-closed confirm() that returns { body, map, receipt } and never egresses unsafe. Peer-depends on @cloakapi/sdk.
  • @cloakapi/review-ui — pure view + event wiring over review-core: a <cloak-review> / <cloak-receipt> custom element plus React and Svelte reference components and the review-ui.css class contract. Ships as TypeScript source (compiled by your bundler — Vite, esbuild, webpack with a TS loader); React, Svelte and @cloakapi/sdk are optional peers, review-core + veil-tokens are required peers.
  • @cloakapi/veil-tokens — the semantic colour-token layer (--veil-*) for safety-critical states: green = cloaked, amber = leaving in the clear, pink = secret/can’t-reveal, purple = your action. Plain CSS custom properties + a tiny JS manifest; usable with no build step at all.
Terminal window
curl -O https://app.cloakapi.io/downloads/sdks/review-core/cloakapi-review-core-0.1.1.tgz
curl -O https://app.cloakapi.io/downloads/sdks/review-ui/cloakapi-review-ui-0.1.2.tgz
curl -O https://app.cloakapi.io/downloads/sdks/veil-tokens/cloakapi-veil-tokens-0.1.0.tgz
# TypeScript src zip is not currently served (HTTP 404, measured 2026-08-20).
# CORRECTION BESIDE, 2026-08-25: that URL answers HTTP 410 Gone, not 404.
# Measured from the wire (positive control 200 on manifest.json, negative
# control 404 on a nonexistent name, so the check distinguishes the two).
# 410 is not a milder 404 here: the file WAS published, and the engine it
# bundles (sha256 5590766a...) uses an ASCII-only class for personal names.
# So do not reuse a copy you already downloaded either.
# CORRECTION BESIDE, 2026-09-20: cloakapi-review-core-0.1.0.tgz and
# cloakapi-review-ui-0.1.1.tgz answer HTTP 410. Served tarballs (same
# measurement, POS 200 / NEG 404): review-core 0.1.1, review-ui 0.1.2,
# veil-tokens 0.1.0. Do not curl a 410 door.
# Build from the source tree: cd sdk/typescript && npm install && npm run build
npm install ./sdk/typescript ./cloakapi-veil-tokens-0.1.0.tgz \
./cloakapi-review-core-0.1.1.tgz ./cloakapi-review-ui-0.1.2.tgz
import { createCloakReview } from '@cloakapi/review-core';
import '@cloakapi/veil-tokens/tokens.css';
import '@cloakapi/review-ui/review-ui.css';
// then mount <cloak-review> (element), <CloakReview> (react/) or (svelte/)

review-core has a required peer dependency on @cloakapi/sdk, which is not offered as a download (see TypeScript). Without ./sdk/typescript in the same npm install, npm stops with ERESOLVE (measured 2026-09-25); veil-tokens installs on its own.

Only veil-tokens and review-core are needed if you build your own review UI — review-ui is the reference implementation. All three are listed with sha256 hashes in manifest.json.

Checking the SDK actually cloaks before egress

Do not take it on faith that a build tokenises before it sends — measure it. The same wire-level method we use on our own products, the results across every surface (SDK, local proxy, MCP server, gateway, products), the documented limits, and a defect the method caught are all written up in Verification & evidence.

Optional: public registries later

Publishing these packages to npm / PyPI / crates.io / etc. remains an optional future marketing/discoverability step. It is not required to build on CloakAPI today — the downloads above, plus the REST API, are the supported launch path.