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:
| Flag | Description |
|---|---|
--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
| Flag | Description |
|---|---|
--name (required) | Display name |
--local-only | Save 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
| Flag | Default |
|---|---|
--limit | 10 |
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
| Flag | Default | Description |
|---|---|---|
--relying-party (required) | — | DID of the party requesting auth |
--purpose | login | Human-readable purpose string |
--mode | identity_proof | identity_proof or access_attestation |
--callback | — | Webhook URL called when user responds |
--qr | false | Print 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
| Flag | Default |
|---|---|
--challenge (required) | Challenge ID from auth request |
--persona | Active 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
| Flag | Default | Description |
|---|---|---|
--challenge (required) | — | Challenge ID |
--wait | false | Poll 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
| Flag | Description |
|---|---|
--author | DID of the author (defaults to active persona) |
--submitter | DID of the submitter if different from author |
--content-type | MIME type override |
--verbose | Print 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:
- Requests a challenge from the server
- Fetches the document hash
- Signs both challenge text and document hash with the private key
- 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
| Path | Contents |
|---|---|
~/.451/keys/<did>.key | P-256 private key (raw bytes, base64) |
~/.451/personas.json | List 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