CLI reference

The kya-os commands and flags for setting up Checkpoint, how --project resolves, and the environment variables and files the CLI reads and writes.

CommandWhat it does
kya-os setupSign in, choose the project, link the repository, and install Detect for the app in this directory
kya-os loginSign in as yourself, in this machine's browser or with --device for a code
kya-os logoutRevoke this machine's sign-in on Checkpoint, then delete it locally
kya-os whoamiWho is signed in, the organization, and the projects the sign-in covers (* marks this repository's)
kya-os projects listThe projects the sign-in covers
kya-os projects use <id or name>Link this repository to a project
kya-os detect installAdd Detect (pixel, beacon, or server SDK) to the app in this directory
kya-os detect doctorCheck a live page: its Content-Security-Policy, the beacon files it loads, and whether its origin can carry browser posture
kya-os mcp create <name>Scaffold a KYA-OS MCP server for Cloudflare Workers, tied to the linked project, with its own key
kya-os govern install|uninstallReport a coding agent's tool calls in this repository to the project's Activity feed
kya-os checkpoint key set|show|clearStore, check, or remove the project's runtime key (CHECKPOINT_API_KEY) in .env.local
kya-os checkpoint credentials …The management sign-in (status, login, logout, session) and, for owners and admins, runner workload keys, task grants, the organization's own model provider keys (model-keys), legacy delegations and reviewed identity changes
kya-os doctorCheck system health and compatibility

kya-os --help and kya-os <command> --help list everything the installed version supports.

setup

FlagEffect
--project <id or name>The project to link. See How --project resolves.
--surface <surface>pixel (default: no key, no dependency), beacon, or sdk (server middleware; mints the app's key if it has none)
--deviceApprove the sign-in from another device with a short code, instead of this machine's browser
--skip-installSign in and link the project; install nothing. Posture still runs
--dry-runPrint what would change and change nothing
-y, --yesApply without asking. Without a terminal, nothing is applied unless this is given. --non-interactive is an alias.
--origin <url>The Checkpoint to sign in to. Defaults to CHECKPOINT_API_URL, then https://kya.vouched.id. This is not a page origin; see --origins.
--origins <list>Comma-separated page origins allowed to carry posture besides the project's domain. The list replaces the project's, so an origin you leave out is removed, and the CLI reports what it added and removed. A bare host such as shop.example.com becomes https://shop.example.com, and a path or query is dropped. Wildcards, the apex rule, and the limit of 20 are under Verifying the posture token.
--proxy <path>Beacon only. Serve the beacon and its ingest through your own domain under this path, for example /_cp, so a strict Content-Security-Policy needs only 'self'. Mints a forward-only key and writes the proxy for Next.js, or prints the nginx, Cloudflare, and Akamai config.
--jsonPrint one JSON document on stdout; progress goes to stderr

A live sign-in on the same Checkpoint is reused, so a second run doesn't open the browser. If the project you name isn't part of that sign-in, setup signs in again with it preselected so you can grant it. A name no project has yet is offered on the consent page instead, to create and grant in one step. With nothing named, the offer is this repository's name, and a granted project by that name is linked without asking.

detect install

FlagEffect
--surface <surface>pixel (default), beacon, or sdk
--project <id or name>The project, when this repository isn't linked yet
--dry-runPrint the plan and change nothing
-y, --yesApply without asking
--origins <list>, --proxy <path>As for setup. detect install has no --origin.
--jsonPrint one JSON document on stdout

Without a sign-in, detect install uses the project you name as given, since the pixel and beacon need only the project ID; it says so. What it writes:

Stackpixelbeaconsdk
Next.js, App Router<Script> before </body> in the root layout, plus its importthe package, a 'use client' component, mounted in the layoutthe package, then proxy.ts (Next.js 16+) or middleware.ts at the root or in src/
Next.js, Pages Routera script tag before </Head> in _documentthe package, plus the line to add to your client entryas App Router
Vite SPA, static site, SvelteKitthe loader before </head> in index.html or src/app.htmlthe CDN script tag before </head>none; use the pixel or the Gateway
Express 4printed, for the HTML you renderthe package, plus the line to addthe package, plus the mount lines to add
Express 5printedthe package, plus the line to addrefused: the SDK's peer dependency is Express 4
ASP.NET Core (net8.0+)printed, for the page <head> (see below)printeddotnet add <project> package KyaOs.Checkpoint, plus the Program.cs lines to add
.NET Framework 4.6.2 to 4.8.1printed, for the page <head> (see below)printedthe Web.config settings and module to add
Java 21+ (Maven, Gradle)printed, for your page templateprintedthe dependency to add; below Java 21 it's refused

On .NET, the page <head> is in a different file for each project type:

  • Blazor Web App: Components/App.razor
  • Blazor WebAssembly: wwwroot/index.html
  • Blazor Server upgraded from .NET 7 or earlier: Pages/_Host.cshtml (Pages/_Layout.cshtml if it started on .NET 6)
  • MVC: Views/Shared/_Layout.cshtml
  • Razor Pages: Pages/Shared/_Layout.cshtml
  • Web Forms (.NET Framework): Site.Master

With --surface sdk and no runtime key where the app reads it, a signed-in detect install offers to mint the app's key. It asks first; --yes skips the prompt, and a dry run only says it would. The key is named kya-os CLI · sdk · <host> - <repository>, is returned once, and has read permission. The plan's API key limit applies, as it does to dashboard keys.

  • Next.js and Express: the CLI adds the env file to .gitignore, then writes the key to .env.local (Next.js) or .env (Express).
  • ASP.NET Core: the CLI runs dotnet user-secrets init first, then stores the key and the project ID as Checkpoint:ApiKey and Checkpoint:ProjectId in the project's user secrets, outside the repository. The key reaches dotnet on stdin, never its command line. In production, set Checkpoint__ApiKey and Checkpoint__ProjectId in the host's environment.
  • Java: the CLI prints where the key goes.

Signed out, detect install says to sign in with kya-os login and re-run it, which mints the key.

Existing files only ever gain one block, marked Checkpoint Detect. A file that already has it is left alone, so a second run changes nothing. An existing middleware.ts or proxy.ts is never overwritten; the lines to compose into it are printed instead. A failed package install stops the run before anything that imports the package is written.

Browser posture

--surface beacon installs a beacon the CLI has checked, and every project already has the posture key behind the signed token your server verifies. Set up browser posture walks through the whole path.

StackBeaconPosture wiring
Next.js, App Router with a root layoutThe package, and checkpoint-detect.tsx next to the layout, mounted before </body>beacon-lazy-signals.min.js and beacon.worker.js in public/_checkpoint/<version>/; checkpointPostureHeaders() exported from checkpoint-detect.tsx
Next.js Pages Router, Express, and other Node apps with no single HTML fileThe package, plus a snippet to start the beacon once in your client entryThe same two files in your static directory or public/; the snippet exports checkpointPostureHeaders()
Vite SPA, static site, SvelteKitA pinned CDN script tag with integrity, and an inline script that starts the beacon, in a block marked Checkpoint Detect before </head>beacon.worker.js in <static directory>/_checkpoint/<version>/ when there is one, otherwise useWorker: false; window.checkpointPostureHeaders()
.NET, Java, and other stacksA snippet to add to your page templateThe worker handled as above

Before it installs, the CLI resolves the latest @kya-os/checkpoint-beacon on npm, verifies the tarball against the sha512 integrity the registry lists, and hashes beacon.min.js with sha384 for the script tag. It then fetches the same file from jsDelivr and installs nothing unless the bytes match. A script tag gets a versioned URL with integrity and crossorigin="anonymous".

The beacon version decides how much posture wiring you get:

Beacon versionPackage installScript tagPosture wiring
1.4.3 or laterExact-pinnedPinnedAdded
Below 1.4.3A plain addStays pinnedNone. The CLI prints a note that posture forwarding needs 1.4.3.

A run at 1.4.3 or later upgrades an earlier install in place.

Generated itemRule
checkpointPostureHeaders()Returns the beacon's getPostureHeaders(): KYA-Posture-Session always, and KYA-Posture while the latest token hasn't expired.
workerUrl, lazySignalsUrlThe CLI sets workerUrl to the self-hosted worker, and lazySignalsUrl to the self-hosted chunk for package installs. An HTML page loads the chunk from beside its CDN script.
basePath (Next.js App Router)A basePath the CLI can read as a string literal prefixes the endpoint, workerUrl, and lazySignalsUrl, while the proxy file keeps the path without it. A basePath set any other way leaves the endpoint unprefixed, and with --proxy the CLI prints a note to add it. The Pages Router snippet prefixes the endpoint only.

The CLI decides file ownership by comparing a file's whole text with what it generates, not by a marker:

  • A generated Checkpoint Detect block or checkpoint-detect.tsx is replaced or updated on the next run.
  • Files under _checkpoint/<version>/ are rewritten when they differ.
  • Anything you edited, and any beacon install the CLI didn't write, is left alone with the reason.
  • A run stops at its first failed step, so a page never references a file that wasn't written.

Configuring posture

Every project has a posture key, so there is nothing to turn on. On every surface the CLI calls Checkpoint's management posture API: it reads the project's posture (the first read creates the key, and an existing key is never rotated) and, with --origins, replaces the additional origins. All of it needs a sign-in, and setup signs you in as part of the command.

The posture calls run even when the install plan isn't applied, because there's no terminal and no --yes, or you answered No. --origins still changes Checkpoint.

SituationResult
A terminal, no --yes, no --originsAsks Other page origins allowed to carry posture, prefilled with the current list. A terminal means both stdin and stderr are terminals
No terminal, or --yesAsks nothing; changes the origins only with --origins
Signed out, detect installNotes that browser posture was not configured and asks you to run kya-os login, then finishes the install. With --origins it then exits non-zero, because the origins were not applied
--dry-runDoesn't ask Checkpoint for posture, because the first read creates the key. Reports that it would read and confirm the key, and previews what --origins would replace
No project domain and no --originsSays no token can be issued: set the project's domain, or pass --origins
Only wildcard originsSays the verifier needs one exact page origin: set the project's domain, or add an exact origin with --origins
No domain but an additional originUses the first additional origin as the page origin in the snippets and says so
A domain the Java and .NET verifiers can't useThe note names the domain and uses the first additional origin instead
The pixel or sdk surface, or no surfacePosture is still configured, and the CLI says browser posture needs the beacon on your pages: run kya-os detect install --surface beacon
An origin that isn't validRefused before anything is installed. The error reads Error: --origins, then Caused by: origin 1: Only https:// origins are supported, with the origin's position. The terminal prompt shows the reason and asks again
--origins ""Refused before anything is installed: --origins needs at least one origin; leave the flag out to keep the current list
A blank answer at the origins promptRemoves all additional origins (the prompt says "blank for none")

The CLI checks the key and prints the configuration:

OutputWhat it is
Key checkFetches the keys URL the project reports, retrying up to three times, two seconds apart, on 404, and compares the key id and public key with the project's. It fetches only a URL on the sign-in origin or https://kya.vouched.id, at the path /api/v1/beacon/keys with projectId=<this project> as the sole query parameter. For any other URL it fetches nothing, reports key: not confirmed, and drops the Java block.
Result linekey: confirmed at the keys endpoint or key: not confirmed, with a note that says why
Server configurationBlocks for the stacks it detects (Next.js, Express, ASP.NET Core, Java). The Next.js, Express, and ASP.NET Core blocks carry the key id and public JWK. The Java block carries the keys URL only. No block prints without a usable page origin.
CORS lineAccess-Control-Allow-Headers: KYA-Posture, KYA-Posture-Session, for cross-origin APIs
CSP directivesThe Content-Security-Policy directives the page needs. They print on every run, and --dry-run previews them.

Origins the Java and .NET verifiers would reject are left out of the config blocks, with the note These origins are left out of the verifier config because Java and .NET would reject them: .... They are empty labels, odd characters, labels over 63 characters or edged by -, and single-label extras. A single-label primary domain such as https://localhost:3000 is accepted. Additional origins need two labels, and --origins refuses single-label hosts.

Proxy targets

--proxy <path> takes letters, digits, _, -, and /, up to 64 characters including a leading /, with no trailing /, no //, and no empty segment. The beacon's endpoint becomes <path>/api/v1/beacon, prefixed by a Next.js basePath when the CLI can read one.

When you're signed in, the CLI mints a project API key with the proxy purpose and the forward permission only, and stores it as CHECKPOINT_PROXY_KEY. Minting needs a project owner or admin, and the key counts against the plan's API key limit. The key is shown once and never printed. Signed out, the CLI asks you to sign in and re-run, or to set the variable yourself. Forward edge evidence covers what the key can do.

TargetWhat the CLI does
Next.jsWrites a helper, checkpoint-beacon-proxy.ts, and one entry file whose matcher lists only <path>/api/v1/beacon: proxy.ts on Next.js 16 and later, middleware.ts before that, under src/ when the app uses src/app or src/pages. An existing entry file the CLI didn't write is never overwritten; the lines to add are printed.
nginxPrints a location block that proxies to https://kya.vouched.id/api/v1/beacon, starts with include /etc/nginx/checkpoint-proxy-key.conf; (a file you create with the key), and sets X-API-Key and KYA-Forwarded-IP from $remote_addr.
CloudflarePrints a Worker to route at your domain and path, and the wrangler secret put CHECKPOINT_PROXY_KEY command. The Worker reads cf-connecting-ip, answers 502 without the key or the IP, forwards kya-forwarded-ja4 from Cloudflare bot management when present, and removes X-API-Key, Cookie, Authorization, and every KYA-Forwarded-* header the visitor sent.
AkamaiPrints a property rule for your default rule that sets X-API-Key from the sensitive user variable PMUSER_CHECKPOINT_PROXY_KEY and KYA-Forwarded-IP from AK_CLIENT_IP. Checkpoint hasn't verified the rule against a live property.

The nginx block and the Akamai rule clear Cookie, Authorization, and the JA4, challenge, and challenge-id headers by name. Delete any other KYA-Forwarded-* header yourself. For nginx, Cloudflare, and Akamai, nothing is applied.

The generated Next.js proxy behaves like this:

BehaviorDetail
Missing dataAnswers 502 when it has no key or can't read the visitor's IP, which it takes from x-real-ip, else the first x-forwarded-for hop.
HeadersRemoves x-api-key, cookie, authorization, and kya-forwarded-* from the request before setting its own.
KeySet CHECKPOINT_PROXY_KEY in your host's environment as well, since .env.local isn't deployed. A CHECKPOINT_PROXY_KEY you've already stored is kept, and no key is minted.
PathThe helper accepts a trailing slash and passes the query string to Checkpoint.
Re-runsThe CLI recognizes your helper when its BEACON_PATH matches, even after a formatter requotes it. A helper you edited for a different path stops the run with an error that says to set BEACON_PATH to the new endpoint or delete the file.

The Content-Security-Policy directives the CLI prints depend on whether the proxy landed and how the script is delivered:

DirectiveValue
connect-src'self' https://kya.vouched.id, or 'self' when the proxy is in place
script-src'self' when the script is self-hosted: a Next.js App Router install, a package install, an HTML page with --proxy and a static directory, or a non-Node stack with --proxy and a static directory (wwwroot, src/main/resources/static). https://cdn.jsdelivr.net for a CDN script tag.
worker-src'self'
  • It always lists base-uri 'none' (add it with a nonce-based policy) and trusted-types checkpoint-beacon (add it when the page enforces Trusted Types). Add them only if they apply.
  • A project with no static directory still loads the script from jsDelivr, so script-src keeps the CDN, and the CLI says so.
  • The CLI reports the collapsed policy only when every step landed. A skipped or failed step counts as not in place.
  • With --proxy and a static directory, an HTML page's script tag also points at a self-hosted beacon.min.js, written to the same _checkpoint/<version>/ directory.

posture in --json

Both setup and detect install add a posture object to their report. Outer keys with no value are left out. Inside state, primaryOrigin is null when the project has no domain.

FieldValues
statusconfigured, dryRun, unavailable (this Checkpoint doesn't serve browser posture, or reading it failed; nothing changed)
statekeyId, publicJwk, primaryOrigin, origins, keysUrl
keyConfirmedWhether the keys endpoint confirmed the project's key. It is present whenever the check ran, so not on a dry run or when posture was unavailable.
config{ title, snippet } server configuration blocks
cors, cspThe Access-Control-Allow-Headers line, and the directives for the Content-Security-Policy
originsChange, originsError{ added, removed } after --origins, or why the list wasn't changed
error, notesA refusal from Checkpoint, and non-fatal notes

The proxy key's value is never in the report. A minted key appears in keys by keyId, name, and preview, and the plan lists a writeSecret action for where it was stored.

detect doctor

kya-os detect doctor --url <page> fetches a page and checks that the beacon and its posture path can work there. It reads the HTML, then probes the files and headers the beacon needs. When the page has no beacon.min.js tag, it also reads up to 20 same-origin scripts to find a beacon inside a bundle.

FlagEffect
--url <page>The http or https page to check. Required. A malformed value stops with the --url is not a valid http(s) URL, without echoing the input.
--project <id or name>The project for the posture checks. Defaults to KYA_OS_PROJECT, then the repository's link.
--jsonPrint { url, checks: [{ name, status, detail, fix? }] } on stdout. status is ok, info, warn, or fail.

It exits 1 when any check is fail, and 0 for warn and info.

LimitValue
RequestTimes out after 10 seconds, reads at most 5 MiB, and follows up to 10 redirects
A file on another originIsn't fetched when it points to a private or local address, and that shows as a warn
A file on the page's own originIs fetched
The --url pageCan be at a private or local address, so you can check a local server. A redirect from a public page to another origin that is or resolves to a private or local address is refused, and so is a redirect from a same-origin file
CheckWhat it reports
page, page size, page nesting, page complexityfail when the page can't be fetched or doesn't answer 200. A page over the scan limits is warn, and only the start of it is read. A page too deeply nested or too complex to scan stops the scan with a warn, and beacon then reports warn, not fail.
beaconfail when no beacon script tag or configuration is found, with the fix kya-os detect install --surface beacon. warn when the scan was cut short and it wasn't found in the part read. info when it's found inside a bundled script. warn also when a script it needed to read couldn't be read, or when the page has more than 20 same-origin scripts.
beacon configinfo when the scan was cut short and no endpoint was found, so the default https://kya.vouched.id/api/v1/beacon is assumed.
beacon script, lazy signals chunk, workerok on a 200 served as JavaScript. fail or warn on another status, an unreachable file, or a type a browser refuses. A worker on another origin fails, because it must be served from the page's origin. A worker the doctor derived rather than read from the page is warn; a derived lazy chunk that fails is fail. No worker check runs when the beacon config sets useWorker: false. Only false, !1, true, and !0 count, the last duplicate wins, and keys inside workerOptions are ignored.
beacon script integrityok when the served bytes match the tag's integrity hash (sha256, sha384, or sha512, the strongest listed). fail when they differ, because browsers refuse to run the script. info when the tag has no usable hash
beacon script corsfail when a cross-origin beacon script tag has integrity but no crossorigin, or the host's response headers don't fit the tag: anonymous needs Access-Control-Allow-Origin of * or the page's origin, and use-credentials also needs Access-Control-Allow-Credentials: true
content-security-policy, csp report-onlyok when the page sets none. A report-only policy is info and isn't checked. Header and <meta> policies, several policies, nonces, hashes, and 'strict-dynamic' are read. A tag whose integrity lists several hashes passes a hash-based policy only when the policy lists every one.
csp script-src: init script, csp script-src: beacon script, csp script-src: lazy signals chunk, csp worker-src: worker, csp connect-src: ingestfail when the policy blocks that file or the beacon's endpoint (ingest is checked for a proxy path too); a blocked worker the doctor derived rather than read from the page is warn. The fix names the source to add
csp base-uriok for 'none' or 'self'; warn under a nonce or hash policy with none. The beacon still works
csp trusted-typesfail when the page requires Trusted Types and doesn't allow the checkpoint-beacon policy that beacon 1.4.3 and later create. ok when the beacon's policy is allowed.
proxy preflightinfo when the endpoint is on the page's origin. Otherwise it sends an OPTIONS request with Access-Control-Request-Method: POST and the beacon's headers, and reports ok, warn for a private endpoint, or fail when it's unreachable. It doesn't check KYA-Posture headers
posture, posture origin, posture key, posture projectinfo (not checked: <reason>) when you're not signed in, the project can't be resolved, or Checkpoint doesn't serve posture. Otherwise: whether the page's origin may carry posture (fail for an http page, with the fix Browser posture needs an https page origin, and for an origin that isn't allowed, with a fix that runs kya-os detect install ... --origins '<list>'), whether the keys endpoint serves the project's key, and whether the page's beacon uses the project you compared (warn on a mismatch only). The posture checks run even when no beacon is found.

login, logout, whoami, projects

CommandFlags
kya-os login--device, --project <id or name> (an ID is preselected on the consent page; a new name is offered for creation), --origin <url>, --json
kya-os logout--json. Revokes the session on Checkpoint first; if Checkpoint can't confirm, the local copy is kept.
kya-os whoami--json. Exits non-zero when nobody is signed in.
kya-os projects list--json
kya-os projects use <id or name>--json. Writes .kya-os/project.json where the nearest link already is, otherwise at the repository root.

The sign-in is a management session for a person. It lists your projects and links repositories to them, and Checkpoint's runtime API refuses it, so it can never stand in for an app's API key. Access tokens last 15 minutes and renew silently; the session ends after 30 days without use, and after 90 days regardless. On Linux the session needs a Secret Service keyring (GNOME Keyring or KWallet); see Troubleshooting for machines without one.

mcp create

kya-os mcp create <name> runs @kya-os/create-mcpi-app for Cloudflare Workers, the runtime that pulls per-tool protection from Checkpoint. It's pre-filled with the linked project and your repository's package manager, and runs with no prompts. When you're signed in, it then mints the server's key (read and write, for proofs and tool discovery) into the new server's gitignored .dev.vars. The key never goes on the scaffolder's command line.

FlagEffect
--project <id or name>The project, when this repository isn't linked yet
--skip-installScaffold without installing the server's dependencies
--dry-runPrint the scaffolder command and run nothing
-y, --yesMint the server's key without asking
--no-keyScaffold without minting a key
--jsonPrint one JSON document on stdout

Without a terminal, pass --yes or --no-key: the key is decided before anything is scaffolded, so a server is never left half set up. The scaffolder needs Node.js 22.12 or newer.

Then run it locally with npm run dev (the CLI prints your package manager's form). Before the first npm run deploy, sign wrangler in once with npx wrangler login, then upload the server's secrets, the key among them, with npx wrangler secret bulk .dev.vars.

govern

kya-os govern install --agent claude adds a Claude Code PostToolUse hook to this repository. After every tool call, Claude Code runs kya-os hook post in the background, and the call appears in the project's Activity feed as an observed verdict. Nothing is blocked.

  • Sent: the tool's name, the session, and the call's ID. The tool's input and output are never sent, since they can hold file contents and secrets.
  • Never in the way: the hook runs asynchronously, gives up after three seconds, and exits 0 on any failure.
  • Key: the project's read-only runtime key, read from the repository's gitignored .env.local or .env. If the key is only in your shell's CHECKPOINT_API_KEY, install saves it to .env.local, because the hook runs inside Claude Code, which may not see your shell. When there's no key and you're signed in, install mints one.
  • Origin: the hook reports only to the Checkpoint it was installed for (hook post --origin …), so a later edit to the committed link can't redirect the key.
FlagEffect
--agent claudeThe agent to hook (Claude Code)
--scope localDefault. .claude/settings.local.json: you only, gitignored, pinned to this binary
--scope project.claude/settings.json: everyone who clones the repository, so each needs kya-os on their PATH
--scope user~/.claude/settings.json: every repository you open; reports only from linked ones
--dry-run, --yes, --jsonAs for setup

Your other hooks and settings are kept, and a second install changes nothing, unless the hook points at another Checkpoint or another kya-os binary: then it's replaced, and the state is updated. kya-os govern uninstall --scope <scope> removes only the kya-os hook.

How --project resolves

Every command that needs a project takes the first of:

  1. the --project flag;
  2. the KYA_OS_PROJECT environment variable;
  3. the nearest .kya-os/project.json, from the current directory up to the repository root;
  4. the only project the sign-in covers.

A value matches a project by ID, or by exact name, ignoring case. A name shared by several projects is refused with the list of matches, and with several projects and nothing selected, setup asks, offering a new project too (or, without a terminal, lists them and stops). Only a project ID preselects a project on the consent page; any other value is matched there by name, or offered as the name of a new project.

Environment variables

VariableEffect
KYA_OS_PROJECTSelects the project, after --project
CHECKPOINT_API_URLThe Checkpoint origin the CLI signs in to (default https://kya.vouched.id). The CLI reads it from its own environment; the SDK setting of the same name lives in your app's env file.
CHECKPOINT_PROXY_KEYThe forward-only key your proxy sets as X-API-Key. --proxy writes it to .env.local (Next.js) or .checkpoint-proxy.env, and it belongs in your host's environment too.
MCPI_CHECKPOINT_CONFIG_PATHWhere the CLI keeps its sign-in metadata (default ~/.mcpi/checkpoint.json)

The installer's own variables are on Installation.

Files

FileWhereHoldsCommit it?
.kya-os/project.jsonyour repositoryThe project link: origin, organization, project ID and name. No secret.Yes
.env.local or .envyour appCHECKPOINT_API_KEY and CHECKPOINT_PROJECT_ID, written by detect install --surface sdk (a minted key) or kya-os checkpoint key setNever
~/.mcpi/checkpoint.jsonyour home directorySign-in metadata. The tokens themselves are in the OS keychain: Keychain on macOS, the Secret Service on Linux.Not in a repository
~/.kya-os/bin/kya-osyour home directoryThe CLI, from the curl installerNot in a repository
checkpoint-detect.tsxnext to your Next.js layoutThe beacon component and checkpointPostureHeaders(), from detect install --surface beaconYes
_checkpoint/<version>/your static directorybeacon-lazy-signals.min.js and beacon.worker.js (and beacon.min.js with --proxy), from the verified npm tarballYes
checkpoint-beacon-proxy.ts, middleware.ts or proxy.tsyour Next.js appThe beacon proxy, from --proxyYes
.checkpoint-proxy.envyour app, non-Next.jsCHECKPOINT_PROXY_KEY, from --proxy (Next.js uses .env.local)Never
.claude/settings.local.jsonyour repositoryThe govern hook, with --scope localNever (gitignored)
<server>/.dev.varsa server from mcp createThe server's CHECKPOINT_API_KEY for wrangler devNever (gitignored)
.kya-os/project.json
{
  "schema": "kya-os.project-link.v1",
  "origin": "https://kya.vouched.id",
  "organizationId": "5b1f3a9e-…",
  "projectId": "9c2d7e41-…",
  "name": "acme-web"
}

A link that names another Checkpoint origin (staging, a local server) is ignored, with a message, rather than resolved against the wrong one.

JSON output

With --json, a command prints one JSON document on stdout, and progress, prompts, and package-manager output go to stderr. setup reports the link and what Detect did:

{
  "origin": "https://kya.vouched.id",
  "signedInNow": true,
  "organizationId": "5b1f3a9e-…",
  "project": { "id": "9c2d7e41-…", "name": "acme-web" },
  "link": { "path": "/home/me/acme-web/.kya-os/project.json", "state": "written" },
  "detect": {
    "status": "applied",
    "report": {
      "surface": "pixel",
      "outcomes": [{ "outcome": "applied", "description": "edit app/layout.tsx (before </body>)" }],
      "notes": ["…"]
    }
  }
}
FieldValues
link.statewritten, unchanged, wouldWrite (dry run)
detect.statusapplied, upToDate, planned (dry run), needsConfirmation (no terminal and no --yes), declined, skipped (--skip-install)
runtimeKeyPresent when a key was minted: its keyId, name, preview, and the file it was written to. Never the key.
detect.report.outcomes[].outcomeapplied, alreadyPresent, skipped, manual (with a title and snippet to add by hand), failed (with an error)

Exit codes

CodeMeaning
0Success, including a dry run
1An error: a failed step, a run that installed nothing, a plan left unapplied because there was no terminal and no --yes, a project that doesn't resolve, nobody signed in (whoami, projects), a detect doctor check that failed, posture that couldn't be read when you passed --origins, or additional origins that couldn't be saved (the report prints first). A posture read that fails when you passed no --origins is reported as unavailable and exits 0
2A usage error: an unknown flag or a missing argument