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/runtime | Current engine artifact | Result |
|---|---|---|
| Linux x86-64, glibc | Standalone 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.39 | Served 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 architectures | No 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 TypeScript | TypeScript 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:
| SDK | Missing-engine result |
|---|---|
| Python 0.4.1 source | EngineError, 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. |
| Go | error.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, .NET | Engine-specific error beginning client-side engine (libcloak_engine) not available — refusing to send the raw file/image to the gateway. |
| TypeScript / Node | EngineError: client-side engine (libcloak_engine) not available. |
| Rust regex-fallback build | EngineError::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.
| SDK | Card as the literal JSON integer | Same card as a literal JSON string |
|---|---|---|
| Python, PHP, Ruby | The 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, .NET | A 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, Rust | Current 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:
sha256sum ./cloakapi-go-1.2.0-src.zip# compare against the value in manifest.json — only hash a file you actually downloadedPer-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):
| Package | Download | SHA-256 | Install |
|---|---|---|---|
| npm tarball | cloakapi-sdk-1.3.29.tgz | f92c4bffd8a506c30b8745655626e2a9cc4a83b2ce3c423b85dcb2079469f269 | npm install ./cloakapi-sdk-1.3.29.tgz |
| Source zip | cloakapi-sdk-typescript-1.3.29-src.zip | eef07766be5ec091bbf66a166a34f7b33438bce75e3ef8e1517ec4a8a6082dc2 | unzip … && cd typescript && npm install && npm run build |
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.tgzWithdrawn 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
contentand 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:
| Host | Currently served 0.4.0 files | Source changes for 0.4.1 (not released) |
|---|---|---|
| Linux x86-64, glibc | No 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.39 | Served 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 architectures | No 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:
curl -O https://app.cloakapi.io/downloads/sdks/python/cloakapi-0.4.0.tar.gzcurl -O https://app.cloakapi.io/downloads/sdks/engine/libcloak_engine.sopip install ./cloakapi-0.4.0.tar.gzexport 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.whland every earlierpy3-none-anywheel 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:
curl -O https://app.cloakapi.io/downloads/sdks/go/cloakapi-go-1.2.0-src.zipunzip cloakapi-go-1.2.0-src.zip # yields ./gomodule example.com/app
go 1.22
require github.com/cloakapi/cloakapi-go v1.2.0replace github.com/cloakapi/cloakapi-go => ./goThen 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:
curl -O https://app.cloakapi.io/downloads/sdks/rust/cloakapi-rust-1.2.0-src.zipunzip cloakapi-rust-1.2.0-src.zip # yields ./rust[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:
curl -O https://app.cloakapi.io/downloads/sdks/java/cloakapi-java-1.2.0-src.zipunzip cloakapi-java-1.2.0-src.zip # yields ./javacd 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:
curl -O https://app.cloakapi.io/downloads/sdks/dotnet/CloakAPI.Sdk.1.2.0.nupkgdotnet 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:
curl -O https://app.cloakapi.io/downloads/sdks/php/cloakapi-php-1.3.1-src.zipunzip cloakapi-php-1.3.1-src.zip # yields ./php{ "repositories": [{ "type": "path", "url": "./php" }], "require": { "cloakapi/cloakapi-php": "*" }}Then composer install.
Ruby
curl -O https://app.cloakapi.io/downloads/sdks/ruby/cloakapi-1.3.0.gemgem install ./cloakapi-1.3.0.gemSource 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.
Name detection: baseline list + the recommended neural model
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_onnxfeature / with the NER model present, and pointCLOAKAPI_ENGINE_LIBat 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:
curl -O https://app.cloakapi.io/downloads/sdks/mcp/cloakapi-mcp-server-0.4.1.tgznpm install -g ./cloakapi-mcp-server-0.4.1.tgzThen 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:
curl -O https://app.cloakapi.io/downloads/sdks/conformance/cloakapi-conformance-0.1.0.tgznpm install ./cloakapi-conformance-0.1.0.tgzSee 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-closedconfirm()that returns{ body, map, receipt }and never egresses unsafe. Peer-depends on@cloakapi/sdk.@cloakapi/review-ui— pure view + event wiring overreview-core: a<cloak-review>/<cloak-receipt>custom element plus React and Svelte reference components and thereview-ui.cssclass contract. Ships as TypeScript source (compiled by your bundler — Vite, esbuild, webpack with a TS loader); React, Svelte and@cloakapi/sdkare optional peers,review-core+veil-tokensare 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.
curl -O https://app.cloakapi.io/downloads/sdks/review-core/cloakapi-review-core-0.1.1.tgzcurl -O https://app.cloakapi.io/downloads/sdks/review-ui/cloakapi-review-ui-0.1.2.tgzcurl -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.tgzimport { 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.