integrity cli - XibalbaTechSol/integrity-core GitHub Wiki
title: integrity-cli created: 2026-07-07 updated: 2026-10-05 type: entity tags: [sdk, identity] confidence: high source_files:
- integrity-cli/integrity_cli/main.py
- integrity-cli/integrity_cli/identity.py
- integrity-cli/integrity_cli/wallet.py
- integrity-cli/integrity_cli/chain.py
- integrity-cli/integrity_cli/bcc.py
- integrity-cli/integrity_cli/config.py
- integrity-cli/integrity_cli/vault.py
- integrity-cli/integrity_cli/hooks.py
- integrity-sdk/integrity_sdk/hook_runner.py
- integrity-cli/tests/test_register_oracle_e2e.py
- integrity-cli/tests/test_chain.py
- integrity-cli/tests/test_hooks.py
- integrity-cli/integrity_cli/verify.py
- integrity-cli/tests/test_verify.py
- integrity-cli/tests/test_verify_decision_trace.py
Table of contents
Overview
Developer CLI (Python/Typer) โ the human-driven counterpart to integrity-sdk, carrying its own copy of the identity/wallet/ chain logic (no sibling-import) but kept wire-compatible byte-for-byte.
integrity agent register runs the real self-sovereign on-chain sequence โ
fund the agent's own EVM wallet โ mint testnet $ITK โ deploy SovereignAgent +
StateAnchor โ grant anchor role via execute โ
AgentPrimitivesFactory.registerPrimitives โ POST to the oracle. It is a
multi-transaction, multi-second command, not a single HTTP POST. See
agent primitives.
Other commands: identity keygen/show (Ed25519 DID, full
sha256(pubkey) fingerprint), agent show/ais (oracle lookups), and
agent intercept --covered-entity (build a signed BCC commitment
and POST it to the policy gate; exit 1 on a policy rejection, so it's scriptable).
vault command group, added 2026-07-30 (sync), bridging the CLI with the
Trust Vault primitive-level persistent memory architecture (mirrors integrity_sdk/memory.py).
Allows local tools to directly parse session facts (e.g. from transcript.jsonl) into the
MemoryBackend (default: JSONLBackend), calculate a new cryptographic state root, and
anchor it on-chain to the agent's StateAnchor contract.
xns command group, added 2026-07-11 (register/resolve/primary-handle/
set-primary/release), covering the new XibalbaNameService
contract. All three writes route through SovereignAgent.execute โ calling
XNS directly with the controller EOA as signer makes msg.sender the wrong
address (XibalbaAgentRegistry.isRegisteredAgent only recognizes the
SovereignAgent contract address), a real bug an early version of this
work shipped and only caught via the real anvil end-to-end test in
test_chain.py, not the Solidity-side unit tests (which correctly vm.prank
the SovereignAgent address directly and so never exercised the CLI's own
calling convention). register/set-primary/release resolve the caller's
own SovereignAgent address via a GET /v1/agent/{did} oracle lookup first
(that mapping isn't persisted locally by agent register). Superseded as the
primary handle system as of 2026-09-26 (PRODUCTION_GAPS.md #71): these five
subcommands still operate the on-chain XibalbaNameService singleton, now
scoped to optional alias listing rather than an agent's primary identity โ
see the two new subcommands below for the actual primary path.
xns available/xns claim, added 2026-09-26, cover the new Oracle-local
xns_handles directory (see integrity-oracle's "XNS
handle directory" section) โ no chain write, no gas, no wallet required.
agent_register also gained a mandatory --handle option (auto-derived from
--alias when omitted), validated client-side by
_validate_xns_handle_format() before the oracle POST, since registration
now claims a handle transactionally alongside primitive registration.
Security: no insecure default auth token (the old prototype's "mock_demo_token"
is gone); placeholder tokens are refused outside ENVIRONMENT=local.
57 tests (pytest, incl. 1 opt-in ORACLE_E2E test): CliRunner + httpx-mock unit
tests, a real anvil integration test (test_chain.py) that spins up a live
chain, runs the real Deploy.s.sol, and exercises the CLI's on-chain code
for real โ including, as of 2026-07-11, the new xns commands and a
negative test proving isRegisteredAgent rejects a real-but-unindexed
SovereignAgent โ plus test_register_oracle_e2e.py (opt-in via
ORACLE_E2E=1, see below).
Resolved gap (found 2026-07-09, fixed 2026-07-09): main.py's
agent register command hand-builds its own oracle POST body (it does not
call integrity_sdk.registration.register_agent, per this page's "carrying
its own copy" note above) โ it used to send {"agent_id": agent_did, "alias", "description", "did_document": doc, "primitives": registration.to_dict()},
the exact same schema drift integrity-sdk/integrity_sdk/registration.py had
until 2026-07-09 (see integrity-sdk's fix note and
docs/INTERFACE_CONTRACT.md ยง6.3's documented real schema): missing the
required did field (sent as agent_id instead) and never sending
eth_address_hex/ed25519_pubkey_hex, so integrity agent register without
--skip-oracle 422/400'd against a real oracle the same way the SDK used to.
Fixed the same day by rewriting the payload in main.py's agent_register to
send {"did", "did_document", "primitives": {the 7 real fields, built explicitly rather than via registration.to_dict()}, "ed25519_pubkey_hex":
"0x"+private_key.public_key().public_bytes_raw().hex(), "eth_address_hex":
evm_account.address, "alias", "description"}โalias/descriptionare kept as CLI-only metadata the oracle's struct has nodeny_unknown_fieldsfor, so it silently ignores them, same reasoningintegrity-sdkused. Verified for real against a live localcargo runoracle (fresh anvil +Deploy.s.sol/DeployMarkets.s.sol, ephemeral Postgres/Redis via Docker): integrity agent register --alias verify-cli-bot ...(no--skip-oracle) printed "Oracle accepted the registration", and a real GET /v1/agent/{did}on that same oracle returnedhas_ed25519_key: true, has_eth_address: truewith matching primitives, and the DID appeared in a realGET /v1/agents. New regression test integrity-cli/tests/test_register_oracle_e2e.py(opt-in viaORACLE_E2E=1, same gate name integrity-oracle/backend/tests/e2e.rsandintegrity-sdk/tests/test_registration_oracle_e2e.pyuse, mirroring that SDK test'soracle_backend` fixture pattern โ ephemeral Docker Postgres/Redis
- real
cargo run) drives the CLI's actualagent registerTyper command viaCliRunner, asserts success, and independently re-confirms via realGET /v1/agent/{did}+GET /v1/agentscalls. Ran green standalone (ORACLE_E2E=1 uv run pytest tests/test_register_oracle_e2e.py) and as part of the full suite (skipped whenORACLE_E2Eunset, as designed).
hooks install/hooks uninstall, added 2026-10-05 (B3): installs
marker-tagged (# integrity-hooks:v1, carried in the command string itself,
not a side-car manifest) PreToolUse/PostToolUse hook entries into a harness's
settings.json, plus a public agent.did.json in the harness root with the
private key stored outside it (integrity_sdk.did's harness-root layout).
This is the one command in this package that imports integrity_sdk (did, and for
--gate shield hook_runner.default_shield_socket_path; neither loads the connector stack) --
a deliberate, owner-approved exception to the "no sibling dependency" rule
the rest of this file documents, because this command's whole job is to
install the SDK's own identity layout (see hooks.py's module docstring for
the full rationale). Installed hooks invoke
python -m integrity_sdk.hook_runner out-of-process (--gate bcc: a real
signed BCC commitment POSTed to bcc_middleware; --gate shield: a digest of the
tool input sent to Shield's local gate daemon over a Unix socket โ accepted since
2026-10-06, and install then reports whether a daemon is actually listening and
which DID to register with it, because the runner fails open when the daemon is
unreachable and an unserved hook enforces nothing; --memory cortex: a redacted event POSTed to Cortex's
/api/otel/batch). Idempotent (reinstall leaves settings.json JSON-equal);
uninstall removes exactly the marked entries and never touches the DID file
or key. 22 new tests across both packages (integrity-sdk/tests/unit/test_hook_runner.py,
integrity-cli/tests/test_hooks.py).
integrity verify --decision-trace/--trace-evidence, added 2026-10-05 (B4): the
existing verify command (main.py, verify.py -- signature/chain/checkpoint/
inclusion/anchor, independently reimplemented with no SDK import per the convention
above) gained a second, explicitly SDK-backed path for B4's DecisionTrace evidence:
integrity_sdk.core.verify_decision_trace_offline checks parent links and
domain-separated Merkle inclusion, and any carried Jev advisory status is reported as
its own advisory_status field (available/unavailable/rejected/not_present)
that never fails the command by itself (C11: advisory, never authoritative). Also
fixed a bug this session's bcc_middleware change exposed: --anchor-contract used to
require the supplied root equal StateAnchor.latestRoot(), which only ever held for a
per-agent anchor -- now relies on verifyLeaf's own isAnchoredRoot check, the real
guarantee, so it works correctly against B4's shared evidence anchor too.
tests/test_verify_decision_trace.py (5/5).
Related: integrity-sdk, agent primitives, BCC, DID.