Quick Start

# Create a persona and set it as active
451 persona create --name "Alice Smith"
451 persona use did:451:<hash>

# Submit a document
451 write --file report.pdf

# Sign a document someone sent you
451 document pending
451 document sign doc-<uuid>

# Authenticate as a relying party
451 auth request --relying-party did:451:<hash> --purpose "login"
451 auth status --challenge <id> --wait

Global Flag

All commands accept:

FlagDescription
--server <url>Override the configured S451 server base URL

persona — Manage Identities

Personas are DID-backed identities. Keys are P-256 software keys stored locally; they are never sent to the server.

persona create --name <name>

Generates a P-256 key pair, derives a DID, saves the key to ~/.451/keys/, and registers the persona with the server via the canonicalize → finalize two-step flow.

451 persona create --name "Alice Smith"
451 persona create --name "Alice Smith" --local-only   # skip server registration
FlagDescription
--name (required)Display name
--local-onlySave locally only, do not register with server

persona list

Prints all local personas with the active one marked ⭐.

persona use <did>

Sets the named DID as the active persona (used as the default for document, sign, auth commands).

persona remove <did>

Removes a persona from the local store. Does not decommission it on the server.

persona get <did>

Fetches the full PersonaProfile from the server.

persona search <query>

Full-text persona search via Meilisearch.

451 persona search "alice"
451 persona search "university.edu" --limit 20
FlagDefault
--limit10

persona resolve <identifier>

Resolves a handle (e.g. alice.451.info) or DID to a full profile.

persona verify <did>

Returns the background-verification status for a persona.

persona update <did>

Updates display name or address. Requires the private key to be present in ~/.451/keys/.

451 persona update did:451:abc123 --name "Alice B. Smith"
451 persona update did:451:abc123 --address "123 Main St"

persona delete <did>

Decommissions a persona on the server. The DID remains on-chain but is marked inactive.

451 persona delete did:451:abc123 --reason "Account closed"

auth — Sign in With 451

auth request

Creates an authentication challenge as the relying party. Prints a challenge ID and a signator:// deep link.

451 auth request --relying-party did:451:abc123 --purpose "login"
451 auth request --relying-party did:451:abc123 --purpose "access:doc:xyz" \
                 --mode access_attestation \
                 --callback https://yourapp.example/auth/callback \
                 --qr
FlagDefaultDescription
--relying-party (required)DID of the party requesting auth
--purposeloginHuman-readable purpose string
--modeidentity_proofidentity_proof or access_attestation
--callbackWebhook URL called when user responds
--qrfalsePrint ASCII QR code (requires qrencode in PATH)

auth respond

Responds to a challenge using a CLI persona's private key.

451 auth respond --challenge <challengeId>
451 auth respond --challenge <challengeId> --persona did:451:xyz789
FlagDefault
--challenge (required)Challenge ID from auth request
--personaActive persona

Prints the issued JWT token on success.

auth status

Polls whether a challenge has been completed and prints the JWT token.

451 auth status --challenge <challengeId>
451 auth status --challenge <challengeId> --wait     # poll up to 5 minutes
FlagDefaultDescription
--challenge (required)Challenge ID
--waitfalsePoll every 5 s until completed or expired

document — Document Lifecycle

document submit <filePath>

Uploads a file to S3 and records a blockchain block. Uses the active persona as author unless overridden.

451 document submit report.pdf
451 document submit report.pdf --author did:451:abc --submitter did:451:xyz
451 document submit data.json --content-type application/json --verbose
FlagDescription
--authorDID of the author (defaults to active persona)
--submitterDID of the submitter if different from author
--content-typeMIME type override
--verbosePrint detailed progress

Supported extensions (auto-detected): pdf, txt, md, json, jpg, png, mp4, mov

document sign <documentId>

Signs a document using the challenge-response flow:

  1. Requests a challenge from the server
  2. Fetches the document hash
  3. Signs both challenge text and document hash with the private key
  4. Submits both signatures
451 document sign doc-abc123
451 document sign doc-abc123 --persona did:451:xyz

Prints signaturesCollected / signaturesRequired on completion.

document head <documentId>

Shows the head pointer record for a document: status, latest event type, blockchain reference.

document signatures <documentId>

Lists all collected signatures with signer DID, role, status, and timestamp.

document pending

Lists documents waiting for your signature.

451 document pending
451 document pending --signer did:451:abc123

write — Quick Document Submission

A shortcut for single-file document submission.

451 write --file report.pdf
451 write --file image.jpg --author did:451:abc123

Equivalent to 451 document submit but with a simpler interface.

sign — Low-Level Signing

Signs a document or arbitrary payload using the active persona's private key. Use document sign for the full challenge-response workflow.

451 sign <documentId>
451 sign <documentId> --persona did:451:abc123

verify — Signature Verification

Verifies a document's blockchain block and signature chain.

451 verify <documentId>
451 verify <documentId> --server https://s451.example.com

blockchain — Audit the Chain

blockchain latest

Shows the most recent blockchain block.

blockchain get <blockId>

Fetches a block by numeric index or hash.

451 blockchain get 42

blockchain bydid <did>

Fetches all blockchain blocks associated with a DID.

451 blockchain bydid did:451:abc123

blockchain validate <blockId>

Validates the hash integrity of a block.

451 blockchain validate 42

blockchain search --query <text>

Full-text search across the blockchain index.

451 blockchain search --query "contract"

proposal — Signing Invitations

Proposals represent an invitation to join a document workflow (e.g. as a co-signer or participant).

proposal create

Creates a proposal from one persona to another.

451 proposal create --from did:451:abc --to did:451:xyz --role participant

proposal get <proposalId>

Fetches proposal details.

proposal accept <proposalId>

Accepts a proposal, enrolling the persona as a participant.

451 proposal accept <proposalId>
451 proposal accept <proposalId> --persona did:451:abc123

witness — Witness Attestation

Records a witness attestation against a document or event on the blockchain.

451 witness <documentId>
451 witness <documentId> --persona did:451:abc123

stream — Data Repository Ingest

Manages data ingest streams for registered repositories. Used by instrument operators.

Open / close pattern (continuous instruments)

# Open a stream
451 stream open --repository repo_<uuid> --api-key <key> --instrument-type weather_station

# Close a stream and commit to blockchain
451 stream close --repository repo_<uuid> --api-key <key> \
                 --stream stream_<uuid> \
                 --s3-bucket my-bucket \
                 --s3-key readings/2026-04-06/data.json \
                 --s3-etag "abc123" \
                 --data-hash <sha256>

Single-shot record

451 stream record --repository repo_<uuid> --api-key <key> \
                  --s3-bucket my-bucket \
                  --s3-key readings/snapshot.json \
                  --data-hash <sha256>

Local State

PathContents
~/.451/keys/<did>.keyP-256 private key (raw bytes, base64)
~/.451/personas.jsonList of local personas, active flag

Keys are software-generated and can only be used from the CLI. Keys generated by the Signator iOS app are hardware-bound (Secure Enclave) and cannot be imported into the CLI.

Configuration

The CLI reads server configuration from environment or a config file.

# Override server for a single command
451 persona get did:451:abc123 --server https://s451.example.com

# Set permanently (example — check CLIHTTPClient.swift for actual config mechanism)
export S451_SERVER=https://s451.example.com