@axtary/cli
v0.6.1
Published
Axtary CLI for local enforcement, agent hooks, MCP governance, policy testing, and verifiable ledger evidence.
Downloads
1,017
Maintainers
Readme
@axtary/cli
Axtary's content-authorization CLI: local proxy, agent hooks, MCP wrapper, policy testing, and ledger verification in one binary.
Early 0.x release: the runtime path is real and tested, but the API is not stable yet and may change between minor versions.
The source repository is currently private. Public product documentation and runnable guides are at axtary.com/docs.
Quickstart
npm install -g @axtary/cli # or: npx @axtary/cli <command>
axtary init # scaffold a starter axtary.yml
axtary demo # run credential-free GitHub/Slack/Linear demo actions through the proxy + ledgerinit then demo shows allowed, denied, and approval-required actions in
under a minute with no credentials. The Quickstart
then connects the same checks to a supported agent hook or MCP wrapper.
To start from a scoped policy, use one of the PRD templates:
axtary init --template repo-only-coding
axtary policy test .axtary/policy-tests/repo-only-coding.policies.test.yml --config axtary.yml
axtary demo --config axtary.yml --template repo-only-codingAvailable templates: repo-only-coding, staging-reads, incident-investigation, ticket-updates, doc-search, and guarded-prod.
Commands
axtary init [--template repo-only-coding|staging-reads|incident-investigation|ticket-updates|doc-search|guarded-prod]
axtary demo --config axtary.yml --json
axtary demo --config axtary.yml --template repo-only-coding
axtary doctor connectors --config axtary.yml --json
axtary proxy --config axtary.yml
axtary login [--endpoint https://app.axtary.com] [--no-browser]
axtary account [--json]
axtary whoami [--json]
axtary logout [--local-only] [--json]
axtary revoke ap_<id> [--reason "..."] [--by user:operator]
axtary revocations [--json]
axtary issuer-keys [--rotate] [--retire-after 1200]
axtary status [--json]
axtary caep-map --issuer https://idp.example --subject '{"format":"opaque","id":"session"}' --root ap_<id>
axtary smoke --config axtary.yml
axtary policy simulate action.json --config examples/axtary.policies.yml
axtary policy test examples/policies.test.yml --config examples/axtary.policies.yml
axtary test-policy --config axtary.yml --fixtures examples/policy-fixtures
axtary test-policy --parity --json
axtary acs conformance
axtary run workflow github-pr-review --real --config examples/axtary.real.yml [--tamper]
axtary run workflow github-depth --real --config examples/axtary.real.yml --repo org/repo
axtary run workflow postgres-read --real --config examples/axtary.postgres.yml --database appdb --statement 'SELECT id FROM public.items WHERE tenant_id = $1' --parameters '["tenant-a"]'
axtary hook install claude --owner user:operator --repo org/repo
axtary hook install cursor --owner user:operator --repo org/repo
axtary hook install codex --owner user:operator --repo org/repo
axtary hook claude-code --proxy http://127.0.0.1:7331
axtary hook cursor --proxy http://127.0.0.1:7331
axtary hook codex --proxy http://127.0.0.1:7331
axtary mcp serve --config axtary.yml [--wrap '<upstream mcp command>' | --wrap-url https://host/mcp]
axtary mcp login --wrap-url https://host/mcp [--scope 'a b']
axtary mcp sessions [--json]
axtary mcp logout --wrap-url https://host/mcp
axtary mcp pins [--pins axtary.mcp-pins.json] [--json]
axtary mcp trust-publisher --publisher mcp-publisher://acme --jwks publisher.jwks.json
axtary mcp publishers
axtary mcp verify-definition --definition tool.json --statement tool.jwt --publisher mcp-publisher://acme
axtary mcp review --wrap-url https://host/mcp [--signed-definitions .axtary/mcp-signed-definitions.json] [--accept]
axtary mcp conformance --wrap-url https://host/mcp --tool read_tool --arguments '{}' [--accept]
axtary mcp drift-demo [--json]
axtary connect linear [--client-id <id> | --client-id-env NAME]
axtary connect slack --redirect-uri https://<tunnel>/callback
axtary connect jira --redirect-uri https://<tunnel>/callback [--cloud-id ID]
axtary connect drive --redirect-uri https://<tunnel>/callback
axtary connections [--json]
axtary disconnect <provider>
axtary run workflow drive-read --real --config examples/axtary.drive.yml
axtary attest-ledger --ledger .axtary/actions.jsonl --out attestation.json
axtary verify-export attestation.json
axtary prove-equivalence --ledger .axtary/actions.jsonl --out equivalence.json
axtary prove-inclusion attestation.json --record ap_<jti> --out proof.json
axtary prove-consistency first.json second.json --out proof.json
axtary verify-proof proof.json --bundle attestation.json
axtary forensics attestation.json
axtary export-ledger --format siem-jsonl
axtary sync-ledger --endpoint https://app.example/api/ledger/sync
axtary export-otel --endpoint http://127.0.0.1:4318/v1/tracesinitscaffolds a starteraxtary.ymland prints the quickstart rail (docs/quickstart.md).--template <name>applies one of the six reusable scope templates and writes.axtary/policy-tests/<name>.policies.test.ymlso the scaffold can be tested immediately.demoloads config, creates an ephemeral signing key, runs deterministic credential-free GitHub, Slack, Linear, and Jira demo actions through the proxy, writes the local JSONL ledger, and prints a structured result.demo --template <name>is policy-only: it runs the template's representative allow/deny fixtures and makes no provider calls.demo --approve-step-up [--approved-by user:x]attaches a local exact-payload approval so step-up actions execute and each execution record carries the approved/executed payload-hash pair (provable withprove-equivalence).doctor connectorsreports per-provider readiness — mode, missing env names, required scopes, smoke commands — without leaking secret values. Jira and Linear, Postgres, and Google Drive plans are generated by their native connector descriptors; current reported scopes are Jiraread:jira-work/write:jira-workand Linearread/write.proxystarts a long-running local HTTP enforcement point withGET /health,GET /state,GET /revocations,GET /.well-known/jwks.json,GET /.well-known/axtary-trust-root.json,GET /statuslists/actionpasses,POST /ssf/events,POST /actions(authorize + execute), andPOST /authorize(decision, ActionPass, and ledger record without execution — the agent-hook path). It uses deterministic credential-free SaaS demo adapters by default and routes GitHub, Slack, Linear, Jira Cloud, AWS, GCP, and local docs actions when their live modes are enabled. File-backed configs are cached and policy is reloaded when the config file changes.loginopens a one-time browser confirmation for an already-provisioned dashboard account and stores an origin- and tenant-bound, approval-only session in the local credential broker.account/whoamishow safe metadata only;logoutrevokes the hosted session before removing it locally. If a saved endpoint has been permanently retired,logout --local-onlyremoves only the local credential and truthfully leaves the remote session unrevoked. The local CLI remains fully usable without an account. Add--hosted-approvaltoproxyor a supported workflow so onlystep_updecisions use the dashboard; normal allows and denies stay local.revokewrites a durable local revocation for one ActionPassjti;revocationslists that state. Both share.axtary/actionpass-trust-store.jsonwith the proxy and MCP wrapper by default, or an explicit--trust-storepath. Running processes re-check the source on every pass presentation, so revocation takes effect without a restart; unreadable or corrupt state blocks execution.- With
runtime.status.enabled(the default), the proxy issues ActionPass v2, persists a private issuer keyring and status allocation store, publishes public JWKS, a public Axtary trust-root descriptor, and a signed freshness-bounded status list, and updates that list whenrevoketargets an allocated pass.issuer-keys --rotatechanges the durable active key; restart the proxy to begin issuing with it. CLI and HTTP metadata never return private keys. npm run demo:cross-issuerstarts two isolated local Axtary org instances, fetches each org's published trust root over HTTP, has each org verify the other's ActionPass, ledger attestation, inclusion proof, and live status list, and proves a swapped trust root fails. This is a founder-operated local proof, not an external public trust network.runtime.caep.enabledopts into a generic final SSF/CAEP receiver. Configure transmitter issuer, audience, and JWKS URI, then usecaep-mapto associate an exact SSF subject with live root pass IDs. Validsession-revokedevents invalidate those roots; duplicate deliveries are idempotent. This is not a claim of vendor-specific IdP support.smokevalidates configured providers without writes: GitHub REST calls/user, Slack Web callsauth.test, Linear GraphQL queriesviewer, Jira REST calls/myself, AWS calls STSGetCallerIdentity, GCP checks project access, and local docs checks configured roots.policy simulatedry-runs one normalized action and reports the selected decision, determining rule, every rule match/miss, and attached obligations.policy testruns apolicies.test.ymlfixture harness and exits non-zero on a decision, reason, or determining-rule mismatch, making the policy file directly CI-testable.test-policyevaluates JSON fixtures against the loaded YAML policy and fails when an expected decision or reason differs.--parityadditionally runs the same fixtures through executable Cedar and OPA/Rego engines, includes an offline AgentCore Cedar-shaped Gateway request mapping, and fails on any cross-engine disagreement (seeexamples/policies/README.md).acs conformanceruns credential-free Agent Control-stylepre_tool_callvectors through Axtary policy, ActionPass issuance, and the local ledger. It proves the thin shim route; it does not claim hosted ACS certification.run workflow github-pr-review --realexecutes the design-partner workflow (Linear read → docs search → GitHub branch/file/PR → approved Slack post) through proxy-compatible wiring;--tampermutates the approved payload and proves the block (seedocs/sandbox-runbook.md).run workflow github-depth --realis GitHub-only depth: it opens a draft PR, then writes an inline review comment, a check run, and an issue comment — each step governed and ledgered.run workflow postgres-read --realruns one parameterized SELECT through policy, ActionPass, a read-only transaction, and RLS checks; writes are denied before execution.connect <linear|slack|jira|drive>runs the provider's browser OAuth flow and stores the token in the local credential broker (macOS keychain or a0600file) — tokens are never pasted or printed.connectionslists connected providers (metadata only);disconnect <provider>removes a stored credential.hook install <claude|cursor|codex>writes the project runtime hook config (.claude/settings.json,.cursor/hooks.json, or.codex/hooks.json) with the resolved local CLI path. It is idempotent and preserves unrelated hooks.hook claude-code,hook cursor, andhook codexread their runtime's pre-tool payload from stdin, normalize supported file operations into content actions, and return the runtime-specific decision from the running proxy.mcp serveruns a stdio MCP server whose stdio or Streamable HTTP upstream tools are policy-gated at persisted definition hashes (seedocs/mcp-wrapper.md).mcp trust-publisherregisters public JWKS in the local owner-readable publisher trust store;mcp publisherslists identities and key ids;mcp verify-definitionverifies one statement against the exact definition.mcp reviewcompares a live server's advertised definitions with persisted pins and an optional signed-definition registry. It displays verified publisher/semver evidence and the version-chain verdict (continuous,broken_chain, orversion_not_incremented); untrusted or invalid signatures cannot be accepted.mcp conformanceexecutes one explicitly selected live tool through pins → policy → ActionPass v1/DPoP → ledger, proves a labeled synthetic pin mismatch is quarantined, independently verifies a signed ledger export, and writes a secret-free per-server receipt for the dashboard.mcp drift-demoreproduces the tool-poisoning block in one command: the definition mutates after review, the hash drifts, and the identical call is denied before the upstream invoker runs — approved and attempted hashes land in the ledger.mcp loginruns OAuth 2.1 discovery + PKCE consent for an OAuth-protected remote MCP server and stores the bearer in the local broker;mcp sessionslists sessions (resource/issuer/scopes/expiry, never tokens);mcp logoutdeletes one;mcp pinslists the persisted tool-definition pins.export-ledger/sync-ledgerexport verified ledger records locally or upload them to the hosted control plane with signed sync tokens.attest-ledger/verify-exportcreate and independently verify signed, self-contained ledger evidence, including approval↔execution equivalence: an execution record whose approved and executed payload hashes disagree fails the whole export.prove-equivalenceemits the per-executionapproved_payload_hash == executed_payload_hashproof as a queryable report (proved/unproven/failed, exportable with--out), exiting non-zero if any approved execution broke its binding.prove-inclusion/prove-consistency/verify-proofproduce and independently verify RFC 6962 Merkle inclusion and consistency proofs over attested exports, so a third party can check one record or two heads without trusting Axtary.forensicsreconstructs an incident offline from the ledger: authority attenuation, reconstructibility, and cascade containment.export-otelposts a verified ledger segment to an OTLP/HTTP trace endpoint as payload-free GenAIexecute_toolspans.proxy --otlp-endpointstreams the same projection after each durable append. These spans carry decisions, reasons, hashes, and audit dimensions, never payload bodies, tokens, file contents, result rows, or raw shell commands.
Real Provider Smoke Test
Set adapter modes and token environment variables in axtary.yml, then run:
GITHUB_TOKEN=... SLACK_BOT_TOKEN=... LINEAR_API_KEY=... \
AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... GCP_ACCESS_TOKEN=... \
axtary smoke --config axtary.ymlCredential-free demo adapters and disabled connectors are skipped. Missing token environment variables, provider auth failures, or missing local docs roots return a non-zero exit code.
Design Notes
The CLI currently proves the local product loop. Real provider modes are opt-in through config and read tokens from configured environment variables, so demos remain deterministic and do not accidentally touch production providers.
