@sanctix/client
Sanctix Client
Governed edge client for Claude Code, Codex and Cursor.
Install
npm install -g @sanctix/client
Quick start
sanctix init --hosted --invite
Terms: https://mcp.sanctix.ai/terms
Self-hosted init
For a self-hosted audit service, point the CLI at your audit URL:
sanctix init --audit-url https://audit.example.com
Interactive users should run the command without --api-key and supply the
key at the password prompt — the value is never echoed or logged.
--api-key <key> is for non-interactive / CI use only. Never pass an
API key as a shell argument in shared, recorded, or logged environments
(CI logs, terminal recordings, shell history). Use the prompt instead.
sanctix init validates the audit URL and key against /auth/check before
writing any config, env, or hook files. A bad key or unreachable audit
service exits non-zero and leaves the repo untouched.
What this package contains
- sanctix CLI (init, check, status, uninstall)
- Hook shims for Claude Code, Codex and Cursor
- Runtime templates
What this package does NOT contain
Scoring engine, failure memory, trust capability profiles, audit chain internals, governance policy logic or commercial adapter code. All governance runs server-side.
Agent identity registry
sanctix init discovers named agents declared by your runtime and assigns
each one a stable UUID in .sanctix/agents.json. The UUID is preserved
across repeated sanctix init runs so trust signals can be aggregated per
agent over time.
Discovery sources:
- Claude Code:
Agent(<name>)entries in.claude/settings.jsonpermissions.allow[]. - Cursor:
.cursor/rules/*.mdcfiles. The parser is intentionally conservative: an.mdcfile becomes an agent only when its YAML frontmatter declares one explicitly (agent: <name>, orname: <name>alongsidekind: agent/type: agent), or when the frontmatter contains a recognizable Cursor rule key (description,globs,alwaysApply) — in which case the filename is used. Ambiguous files create no agents. Sanctix-managed files (e.g.sanctix-governance.mdc) are skipped.
Spawn and subagent-start hooks stamp event_data.agent_id_stable on every
audit event by looking the role up in .sanctix/agents.json. A missing or
malformed registry never crashes a hook — the field is null and the
hook continues.
SANCTIX_USER_ID_ENV
In environments where the runtime user differs from the human responsible
for the session (CI, build runners, shared service accounts), set
SANCTIX_USER_ID_ENV to the name of another env var that holds the
declared human:
export SANCTIX_USER_ID_ENV=BUILDKITE_BUILD_CREATOR_EMAIL
sanctix start resolves this and posts the value as
event_data.declared_user_id on sanctix.session.started. This is a
hint, not authoritative. The audit service (SEC-9) derives the
authoritative user_id from the API key's bound human on every event
write. A divergence between declared_user_id and the SEC-9 user_id is
intentional signal — the dashboard can flag "ran under a service account
but declared as ". When SANCTIX_USER_ID_ENV is unset, points to
an unset variable, or resolves to an empty value, declared_user_id
falls back to process.env.USER / USERNAME.
High-risk approval (two-phase HITL)
When sanctix start --risk high (or any task classified as high-risk) runs,
the CLI records a pending session and waits for a server-authoritative
approval. No local "yes" answer can substitute for the server's
hitl.gate.resolved event — --yes is no longer accepted as approval for
high-risk sessions.
The CLI prints a curl command another human can run to record the decision:
curl -X POST '<audit-url>/hitl/approve' \
-H 'X-Sanctix-API-Key: <your-approver-key>' \
-H 'Content-Type: application/json' \
-d '{"correlation_id":"<id>","decision":"approve"}'
Send "decision":"reject" to reject. The approver key must be a full
(non-readonly) key with a linked human identity. Self-approval is accepted
for v1 but logged on the audit-service for review.
If the gate is not resolved before the timeout, the CLI exits non-zero and
does not write .sanctix/session.env. Pressing Ctrl+C abandons the wait
with the same effect; the underlying gate stays open on the chain.
SANCTIX_APPROVAL_TIMEOUT_SECONDS
Override the default 300-second (5 min) wait for high-risk approval:
export SANCTIX_APPROVAL_TIMEOUT_SECONDS=600 # 10 min
The CLI polls GET /session/:correlation_id every ~3s while waiting. Values
that are zero, negative, or not a positive integer fall back to the 300s
default.
Docs: https://sanctix.ai