Python CLI for peaqOS, the operating system for the machine economy — on-chain identity, credit rating, and omnichain infrastructure for robots and machines.
Project description
peaq-os-cli
Python CLI for peaqOS. Describes install and the console entry point.
Install
python3 -m venv .peaq-os-cli
source .peaq-os-cli/bin/activate
pip install -e ".[dev]"
Run Tests
pytest
Quality Gates
ruff check src tests
black --check src tests
mypy src
pytest -q --cov=src/peaq_os_cli --cov-fail-under=90
flake8 src tests
Console usage
The peaqos script invokes the Click root group in peaq_os_cli.main.
peaqos --help
peaqos --version
Authoritative option text for any subcommand is always available via built-in help:
peaqos <command> -h
peaqos qualify event -h
peaqos qualify mcr -h
peaqos stream grant -h
peaqos stream consume -h
peaqos stream distribute -h
peaqos stream pay -h
peaqos stream payproof -h
Commands
peaqos init
Interactive wizard that writes a .env file in the current working directory.
peaqos init # interactive (network, key, URLs, contract addresses)
peaqos init --non-interactive # read all values from environment variables
peaqos init --force # overwrite existing .env without confirmation
Example (interactive):
Network (mainnet, testnet) [mainnet]: mainnet
Private key source (paste, generate, wallet): generate
Address: 0xAbCd...1234
Key: 0xdeadbeef...
IMPORTANT: Save this private key securely. It will not be shown again.
RPC URL [https://peaq.api.onfinality.io/public]:
MCR API URL [https://mcr.peaq.xyz]:
Gas Station URL [https://depinstation.peaq.xyz]:
Event Registry address: 0xEe6f...78aB
Config: .env written to /home/operator/project/.env
Running whoami to verify...
Address : 0xAbCd...1234
Network : mainnet
RPC URL : https://peaq.api.onfinality.io/public
Chain ID: 3338
MCR API : https://mcr.peaq.xyz
Contracts:
IdentityRegistry: 0x9075...0B6A
IdentityStaking : 0x7d39...9B8E
EventRegistry : 0xEe6f...78aB
MachineNFT : 0xaF13...Bd61
DID Registry : 0x0000...0800
Batch Precompile: 0x0000...0805
peaqos whoami
Show the active wallet address, network, chain ID, and all contract addresses.
peaqos whoami
Example:
Address : 0xAbCd...1234
Network : mainnet
RPC URL : https://peaq.api.onfinality.io/public
Chain ID: 3338
MCR API : https://mcr.peaq.xyz
Contracts:
IdentityRegistry: 0x9075...0B6A
IdentityStaking : 0x7d39...9B8E
EventRegistry : 0xEe6f...78aB
MachineNFT : 0xaF13...Bd61
DID Registry : 0x0000...0800
Batch Precompile: 0x0000...0805
peaqos wallet
Manage OWS (Open Wallet Standard) wallets in the local encrypted vault (~/.ows/).
Requires the optional OWS dependency: pip install peaq-os-cli[ows].
peaqos wallet create <name> [--words 12|24] [--json]
peaqos wallet import <name> (--mnemonic | --private-key-file <path>) [--index <n>] [--json]
peaqos wallet list [--json]
peaqos wallet show <name-or-id> [--json]
peaqos wallet export <name-or-id>
peaqos wallet delete <name-or-id>
peaqos wallet use <name-or-id>
wallet create — Generate a new mnemonic-backed wallet. Displays addresses for all supported chains (peaq, Base, Ethereum, Solana, Bitcoin, Cosmos, etc.). The mnemonic is never shown; use wallet export to retrieve it.
peaqos wallet create my-machine
peaqos wallet create my-machine --words 24 # 24-word mnemonic
peaqos wallet create my-machine --json # JSON output
wallet import — Import an existing wallet from a BIP-39 mnemonic (hidden prompt) or a private key file.
peaqos wallet import recovered --mnemonic
peaqos wallet import from-file --private-key-file ./operator.key
wallet list — List all wallets in the vault. Shows Name, ID, peaq Address, Key Type, and Created date.
peaqos wallet list
peaqos wallet list --json # full WalletInfo array
wallet show — Display full wallet details with addresses for every supported chain family.
peaqos wallet show operator
peaqos wallet show operator --json
wallet export — Export the recovery phrase or private key (requires confirmation).
peaqos wallet export my-machine
wallet delete — Securely delete a wallet from the vault (requires confirmation).
peaqos wallet delete my-machine
wallet use — Set a wallet as the active default by writing PEAQOS_OWS_WALLET to .env. Subsequent commands use this wallet via load_client().
peaqos wallet use operator
Migration from raw keys:
peaqos wallet import my-operator --private-key-file ./operator.key
peaqos wallet use my-operator
peaqos whoami # address matches the original key
peaqos activate
Run the full machine onboarding flow end-to-end. Six steps: balance check →
2FA enrollment → gas-station funding → register on IdentityRegistry → mint
machine NFT → write DID attributes.
Two modes:
- Self-managed — no proxy flags. The caller's own key signs every step and holds the resulting NFT.
- Proxy-managed —
--for <machine-address> --machine-key <path>together. The operator funds and submits register / mint on behalf of the machine, then the machine key signs its own DID attributes (the peaq DID precompile enforcesmsg.sender == didAccount). The machine EOA holds the resulting NFT. Both flags are required together; supplying one alone is rejected with exit1.
peaqos activate # self mode
peaqos activate --for 0xMachine --machine-key ./m.key # proxy mode
Flags:
| Flag | Purpose |
|---|---|
--for |
Machine EOA address. Presence switches to proxy mode. |
--machine-key |
Path to a file with the machine's 0x-prefixed hex private key. |
--doc-url |
Documentation URL written to the machine DID. |
--data-api |
Raw data API URL written to the machine DID. |
--visibility |
public (default) / private / onchain. |
--skip-funding |
Skip balance check, 2FA, and gas-station funding (steps 1–3). |
Private keys must be supplied via file path (--machine-key). Inline
key flags are intentionally unsupported — reading from a file keeps the key
out of shell history and ps output.
Environment:
Connection / caller identity:
| Variable | Purpose |
|---|---|
PEAQOS_PRIVATE_KEY |
Operator private key (self or proxy mode caller). |
PEAQOS_NETWORK |
mainnet or testnet. |
PEAQOS_RPC_URL |
Override the default RPC endpoint for the network. |
PEAQOS_GAS_STATION_URL |
Gas-station base URL for steps 2–3. |
Contract addresses (all required — missing any yields exit 3):
| Variable | Contract |
|---|---|
IDENTITY_REGISTRY_ADDRESS |
IdentityRegistry (step 4 register). |
IDENTITY_STAKING_ADDRESS |
Identity staking contract. |
EVENT_REGISTRY_ADDRESS |
Event registry contract. |
MACHINE_NFT_ADDRESS |
Machine NFT (step 5 mint). |
DID_REGISTRY_ADDRESS |
DID registry contract. |
BATCH_PRECOMPILE_ADDRESS |
peaq batch precompile (step 6 batched DID writes). |
Idempotent rerun. Every mutating step does a read-before-write precheck:
registration consults machineIdOfOwner, mint consults token_id_of +
NFT ownerOf, DID writes consult readAttribute. Re-running activate
against on-chain state that is already complete submits no transactions
and exits 0. A TOCTOU revert (AlreadyRegistered / AlreadyExists)
is also recovered as skip rather than surfaced as a network error.
Proxy preconditions. Proxy mode requires the operator to already be
registered on IdentityRegistry (i.e. have called activate in self mode
first). If not, the command fails with exit 2 (network/chain error)
before spending any gas.
Output streams. The final summary (Machine ID, Token ID, DIDs; plus
Machine Address and Operator DID in proxy mode) is written to stdout
so it can be piped / captured. Progress lines ([1/6], [2/6], …) and
per-step info/warning messages go to stderr. Integration tests assert on
result.stdout.
Idempotency log. Every step appends a JSONL entry to ./peaqos.log
in the working directory with fields like step, status
(pending / skipped / failed / confirmed), mode, machine_id,
tx_hash, and (for DID writes) machine_did_tx_count=6 /
proxy_did_tx_count=2. This file is both a resume marker for partial
failures and the audit trail.
Example — first run (self mode):
$ peaqos activate > out.txt 2> err.txt ; echo "exit: $?"
exit: 0
$ cat out.txt
Machine activated successfully.
Machine ID: 42
Token ID: 11
Machine DID: did:peaq:0xDC5b20847F43d67928F49Cd4f85D696b5A7617B5
$ cat err.txt
[1/6] Balance check
Operator 0xDC5b...17B5: 1.0000 PEAQ (sufficient)
[2/6] 2FA enrollment - skipped (all wallets funded)
[3/6] Fund from Gas Station - skipped (all wallets funded)
[4/6] Register machine
Registered. machine_id=42
[5/6] Mint NFT
Minted NFT for machine_id=42 -> token_id=11 (tx 0xminttx...)
[6/6] Write DID attributes
Wrote 6 machine DID attributes (tx 0xdidtx...)
Example — rerun is a no-op (exit 0, no tx submitted):
$ peaqos activate 2>&1 1>/dev/null # stderr only, shows skip path
[1/6] Balance check
Operator 0xDC5b...17B5: 1.0000 PEAQ (sufficient)
[2/6] 2FA enrollment - skipped (all wallets funded)
[3/6] Fund from Gas Station - skipped (all wallets funded)
[4/6] Register machine
Already registered (machine_id=42). Skipping.
[5/6] Mint NFT
Already minted (token_id=11). Skipping.
[6/6] Write DID attributes
Machine DID attributes already on chain. Skipping.
The stdout summary stays the same on rerun; only the stderr skip
messages and the peaqos.log entries flip from confirmed to skipped.
Example — peaqos.log (JSONL, one line per step):
{"step":"register","status":"confirmed","mode":"self","address":"0xDC5b...","machine_id":42,"ts":"2026-04-23T15:00:18Z"}
{"step":"mint_nft","status":"confirmed","machine_id":42,"recipient":"0xDC5b...","token_id":11,"tx_hash":"0xminttx...","ts":"..."}
{"step":"machine_did","status":"confirmed","mode":"self","machine_id":42,"token_id":11,"operator_did":"","machine_did_tx_count":6,"tx_hash":"0xdidtx...","ts":"..."}
On a rerun, the same three rows appear with "status":"skipped" and, for
the DID row, "recovered_from":"AttributeAlreadyOnChain".
peaqos stream publish
Chunk, encrypt, and sign data for the peaqOS stream pipeline. Takes raw data
(local file or URL), splits it into fixed-size chunks using the SDK's
build_chunk_chain, encrypts each chunk with a unique XChaCha20-Poly1305 key
wrapped for owner/operator/machine recipients, signs the chain with an
Ed25519 key, and writes output files to a local directory.
Optionally upload encrypted blobs and chunk envelopes to S3-compatible storage
with --s3. Local output is always written; S3 upload is additive.
peaqos stream publish \
--input ./sensor-data.bin \
--output-dir ./chunks/ \
--owner-public-key <x25519-hex> \
--operator-public-key <x25519-hex> \
--machine-public-key <x25519-hex> \
--signing-key-file ./ed25519.key \
--machine-did did:peaq:0x... \
--machine-key-id did:peaq:0x...#keys-1
# URL input (downloaded automatically)
peaqos stream publish \
--input https://example.com/data.bin \
--output-dir ./chunks/ \
...
# Custom chunk size and JSON output
peaqos stream publish \
--input ./data.bin \
--output-dir ./chunks/ \
--chunk-size 1024 \
--json \
...
# S3 upload (requires optional boto3 extra — see below)
peaqos stream publish \
--input ./data.bin \
--output-dir ./chunks/ \
--s3 s3://my-bucket/data-stream/ \
...
# MinIO or other S3-compatible endpoint
peaqos stream publish \
--input ./data.bin \
--output-dir ./chunks/ \
--s3 s3://peaq-stream/chunks/ \
--s3-endpoint http://localhost:9000 \
--s3-region us-east-1 \
...
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--input |
Yes | — | File path or URL to the source data. |
--output-dir |
Yes | — | Directory to write chunk files. Created if missing. |
--owner-public-key |
Yes | — | Owner X25519 public key (hex). |
--operator-public-key |
Yes | — | Operator X25519 public key (hex). |
--machine-public-key |
Yes | — | Machine X25519 public key (hex). |
--signing-key-file |
Yes | — | Path to Ed25519 private key file (hex). |
--machine-did |
Yes | — | Machine DID (e.g. did:peaq:<address>). |
--machine-key-id |
Yes | — | DID key reference (e.g. did:peaq:<address>#keys-1). |
--chunk-size |
No | 262144 | Bytes per chunk (256 KB default). |
--json |
No | — | Output manifest as JSON to stdout. |
--s3 |
No | — | S3 bucket path (e.g. s3://my-bucket/prefix/). Enables upload. |
--s3-region |
No | from env | Region for the S3-compatible service. |
--s3-endpoint |
No | from env | Custom S3-compatible endpoint URL (MinIO, R2, etc.). |
S3 upload (optional)
S3 support requires the optional boto3 dependency:
pip install peaq-os-cli[s3]
When --s3 is used, the command uploads each chunk-{n}.bin, rewrites each
chunk-{n}.json with an updated storageRef, uploads the envelopes and
manifest.json, and adds s3Bucket / s3Prefix to the manifest. Upload
progress is printed to stderr (suppressed by global --quiet). Partial upload
failures are not cleaned up — re-run the command to retry idempotently.
Credentials and endpoint configuration
| Variable | Description |
|---|---|
PEAQOS_S3_ACCESS_KEY_ID |
Access key ID for the S3-compatible service. |
PEAQOS_S3_SECRET_ACCESS_KEY |
Secret access key. |
PEAQOS_S3_REGION |
Default region (overridden by --s3-region). |
PEAQOS_S3_ENDPOINT |
Default custom endpoint URL (overridden by --s3-endpoint). |
When PEAQOS_S3_* credentials are not set, the CLI falls back to the standard
boto3 credential chain (shared credentials file, instance profiles, etc.).
Output
Creates chunk-{n}.json (envelope), chunk-{n}.bin (encrypted data), and
manifest.json in the output directory. Without --s3, each chunk's
storageRef is null.
Example (human output):
Chunking 1048576 bytes into 4 chunks...
Published 4 chunks to ./chunks/
Schema: peaq.stream.chunks.v1
Source Hash: 0xabc123...
Chunk Size: 262144 bytes
Machine DID: did:peaq:0xAbc...
Files:
chunk-0.json chunk-0.bin
chunk-1.json chunk-1.bin
chunk-2.json chunk-2.bin
chunk-3.json chunk-3.bin
manifest.json
Example (human output with --s3):
Chunking 1048576 bytes into 4 chunks...
Uploading chunk-0.bin to S3...
Uploading chunk-0.json to S3...
...
Published 4 chunks to ./chunks/
Uploaded 4 chunks to s3://my-bucket/data-stream/
Schema: peaq.stream.chunks.v1
Source Hash: 0xabc123...
Chunk Size: 262144 bytes
Machine DID: did:peaq:0xAbc...
S3 Bucket: my-bucket
S3 Prefix: data-stream/
Files (local + S3):
chunk-0.json chunk-0.bin → s3://my-bucket/data-stream/chunk-0.bin
chunk-1.json chunk-1.bin → s3://my-bucket/data-stream/chunk-1.bin
chunk-2.json chunk-2.bin → s3://my-bucket/data-stream/chunk-2.bin
chunk-3.json chunk-3.bin → s3://my-bucket/data-stream/chunk-3.bin
manifest.json → s3://my-bucket/data-stream/manifest.json
With --json and --s3, stdout includes s3Bucket, s3Prefix, and a
chunks array with per-chunk storageRef values.
peaqos show machine
Display the full on-chain profile for a single machine DID — identity, DID attributes, MCR snapshot, and recent event summary.
peaqos show machine did:peaq:0x<40-hex>
peaqos show machine did:peaq:0x<40-hex> --json # raw JSON to stdout
Example output:
Machine: did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
Machine ID: 45
Operator : did:peaq:0x9Eea...641C
DID Attributes:
documentation_url: https://example.com/docs
data_visibility : public
MCR Snapshot:
Rating : B
Score : 31 / 100
Bond Status: bonded
Recent Events:
Total : 10
Last Event : 2026-04-20T14:30:00Z
Last Origin Value: 123
Last Currency : HKD
Last Subunit : 100
Last Status : ok
Last USD Value : 0.13
When the most recent event is a revenue event, the block surfaces the
PRO-336 / PRO-334 FX fields. Last USD Value is rendered as USD
dollars (Decimal-quantised to 2 places — usd_value=13 → 0.13,
usd_value=150 → 1.50). When amount_status is
"unsupported_currency" or "fx_unavailable", the Last USD Value
row shows — (em-dash) so the CLI never displays a misleading USD
number for a row whose FX state the server flagged as unreliable:
Recent Events:
Total : 10
Last Event : 2026-04-20T14:30:00Z
Last Origin Value: 100
Last Currency : XYZ
Last Status : unsupported_currency
Last USD Value : —
Activity events (eventType=1) omit all five FX lines.
peaqos show operator machines
List every machine managed by a given operator DID in a tabular summary
(peaqID, Machine ID, MCR, Rating).
peaqos show operator machines did:peaq:0x<40-hex>
peaqos show operator machines did:peaq:0x<40-hex> --json # raw JSON to stdout
Example output:
Operator: did:peaq:0x9Eeab1aCcb1A701aEfAB00F3b8a275a39646641C
Machines: 3
peaqID Machine ID MCR Rating
────────────────────────────────────────────────────────────────────────────
did:peaq:0x9a5F...37C5 45 31 B
did:peaq:0xAb3D...12F0 46 75 A
did:peaq:0xC12E...99B1 47 55 BB
peaqos qualify event
Submit one machine event on-chain via the Event Registry (submitEvent).
Prerequisites
Configure .env in the CLI directory (or export the same variables): private key, RPC URL, and contract addresses. See peaq_os_cli.config.load_client.
Required flags
| Flag | Meaning |
|---|---|
--machine-id |
Positive integer machine identity. |
--type |
revenue or activity. |
--value |
Non-negative integer as ISO 4217 subunit per PRO-334. BREAKING: pre-PRO-334 callers passed whole-currency amounts; the wire is now subunit. Example: HK$1.23 → --value=123 --currency HKD; ¥100 → --value=100 --currency JPY (JPY has no minor unit). Partner is responsible for the conversion. |
--ts |
Event time: Unix seconds (digits only) or ISO 8601 with timezone (Z or +hh:mm). |
Use a timestamp on or before the chain's block time. If --ts is ahead of the network clock, the contract can revert with FutureTimestamp.
Common options
| Flag | Meaning |
|---|---|
--trust |
self (default), onchain, or hardware. |
--source-chain |
same, peaq, or base (maps to a chain id for the SDK). |
--source-tx |
32-byte tx hash (hex, 0x optional). Required when --trust is onchain. |
--raw-data |
File path; file bytes are hashed and stored as the event data hash. |
--metadata |
File path; bytes are sent as on-chain metadata. |
--currency |
Per PRO-336 §6 — currency code for revenue events (e.g. USD, HKD, 3-10 uppercase alphanumeric chars). Activity events take "". Omit to use the SDK's smart default ("USD" for revenue, "" for activity). |
Examples
# Revenue event (self-reported trust, default source chain)
peaqos qualify event --machine-id 42 --type revenue --value 100 --ts 1735000000
Event submitted.
Machine ID: 42
Type: revenue
Value: 100
Trust: self-reported
Tx: 0x3f4a8c1e2d9b7f05a6c3e8d1f4b2a7c9e0d5f3b1a8e2c6d9f7b4a1e3c5d8f2b4
Data Hash: 0xa1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890
# Activity with ISO timestamp
peaqos qualify event --machine-id 42 --type activity --value 0 --ts "2026-04-22T12:00:00Z"
# On-chain-verified event with a source tx hash
peaqos qualify event --machine-id 42 --type revenue --value 200 --ts 1735000000 \
--trust onchain \
--source-tx 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab
# Attach a payload file (raw data is hashed on submit)
peaqos qualify event --machine-id 42 --type activity --value 0 --ts 1735000000 \
--raw-data ./sensor.bin
peaqos qualify mcr
Look up a machine's Machine Credit Rating (MCR) from the MCR HTTP API.
Usage
peaqos qualify mcr <DID> [--json]
DID— Must matchdid:peaq:0xplus exactly 40 hex characters (checksum casing is allowed).--json— Print only JSON to stdout (pretty-printed, indent 2). No banner or prose. Useful for scripts.
In --json mode the object includes the SDK field mcr (rating label, e.g. Provisioned, BBB) and a duplicate key mcr_rating with the same string for tools that expect a *_rating field.
Examples
# Human-readable block (rating, score, bond, events, trend, last updated)
peaqos qualify mcr did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
MCR for did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5
Rating: A
Score: 82 / 100
Bond Status: bonded
Events:
Total: 150
Revenue: 120
Activity: 30
30-Day Revenue: +12.5%
Last Updated: 2026-04-20T14:30:00Z
FX Degraded: no
FX Degraded: yes (PRO-336 §S6 / PRO-331) means at least one event in the
scoring set used a degraded FX source (stale_latest /
default_usd_fx_outage). Use it to distinguish a conservative score caused
by FX outage from an empty-data machine when gating UI / alerts on data
quality.
# Machine-readable JSON for jq / scripts
peaqos qualify mcr did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5 --json
{
"did": "did:peaq:0x9a5F1E244c15e491Ae571c5bF77fDD836ddc37C5",
"mcr": "A",
"mcr_rating": "A",
"mcr_score": 82,
"bond_status": "bonded",
"event_count": 150,
"revenue_event_count": 120,
"activity_event_count": 30,
"revenue_trend": "+12.5%",
"last_updated": 1745152200
}
Typical failures
| Situation | Exit | What you see |
|---|---|---|
| Bad or empty DID | 1 |
Validation message |
| No MCR row for that DID (HTTP 404) | 2 |
Machine not found |
| API unavailable (HTTP 503) | 2 |
MCR API unavailable |
| Other HTTP / RPC issues | 2 |
Wrapped SDK or network message |
peaqos scale agent pair
Pair an AI agent to an activated machine via the challenge-sign flow.
Requests a pairing challenge, collects the agent's EIP-191 signature, and
creates the pairing with the signed proof. The one-time pairing_token is
printed on success. Subsequent commands (such as peaqos scale search)
use that token via --pairing-token-file.
Requires an activated machine and a platform API key
(PEAQOS_ORCH_API_KEY). The token is rendered to stdout exactly once
and is never written to peaqos.log or --verbose output.
# Interactive: prompts for the EIP-191 signature
peaqos scale agent pair \
--machine-id mach_1 \
--agent-address 0xAgent...0101 \
--agent-provider teneo \
--agent-role machine-market-buyer
# Non-interactive: reads signature from file, skips confirmation
peaqos scale agent pair \
--machine-id mach_1 \
--agent-address 0xAgent...0101 \
--agent-provider teneo \
--agent-role machine-market-buyer \
--agent-signature-file sig.txt \
--per-tx-limit 5 --daily-limit 20 --currency USD \
--allowed-skills pyth-price-feed,walrus-store \
--yes
# JSON output (requires --agent-signature-file)
peaqos scale agent pair \
--machine-id mach_1 \
--agent-address 0xAgent...0101 \
--agent-provider teneo \
--agent-role machine-market-buyer \
--agent-signature-file sig.txt \
--json
peaqos scale machine onboard
Onboard a machine into the Machine Market. Four-step wizard: request an identity challenge, sign it (via key file, OWS wallet, or manual paste), register the machine with identity proof, and activate it.
The CLI verifies that the signer address matches one of the DID controller addresses returned by the challenge endpoint before proceeding to registration.
Signing modes (checked in order):
--identity-signature-file— read a pre-signed EIP-191 signature from file.--identity-key-file— read a private key from file and sign the challenge.- OWS wallet (
PEAQOS_OWS_WALLETset) — sign via the active wallet. The key is exported from the vault for the duration of signing only. - None of the above — display the challenge and prompt for a pasted signature.
A raw PEAQOS_PRIVATE_KEY client does not auto-sign; it always falls
through to mode 4 (manual prompt). Only --identity-signature-file,
--identity-key-file, or an active OWS wallet avoid the prompt.
# Sign with a DID controller key file (non-interactive)
peaqos scale machine onboard \
--identity-ref peaqos:machine:my-bot \
--display-name "My Edge Node" \
--owner-id operator-42 \
--machine-type edge-node \
--runtime-profile linux-docker \
--identity-key-file ./controller.key \
--capabilities price-feed,qvac \
--skill-keys pyth-price-feed \
--labels env=production,region=eu \
--yes
# Auto-sign via OWS wallet (PEAQOS_OWS_WALLET must be set)
peaqos scale machine onboard \
--identity-ref did:peaq:0xAbCd...1234 \
--display-name "My Edge Node" \
--owner-id operator-42 \
--machine-type edge-node \
--runtime-profile linux-docker \
--yes
# Pre-signed signature from file
peaqos scale machine onboard \
--identity-ref peaqos:machine:my-bot \
--display-name "My Edge Node" \
--owner-id operator-42 \
--machine-type edge-node \
--runtime-profile linux-docker \
--identity-signature-file sig.txt \
--yes
# Interactive: prompts for a pasted EIP-191 signature
peaqos scale machine onboard \
--identity-ref did:peaq:0xAbCd...1234 \
--display-name "My Edge Node" \
--owner-id operator-42 \
--machine-type edge-node \
--runtime-profile linux-docker
# JSON output (requires a non-interactive signing method)
peaqos scale machine onboard \
--identity-ref peaqos:machine:my-bot \
--display-name "My Edge Node" \
--owner-id operator-42 \
--machine-type edge-node \
--runtime-profile linux-docker \
--identity-key-file ./controller.key \
--json
Flags
| Flag | Required | Description |
|---|---|---|
--identity-ref |
Yes | Machine identity reference (did:peaq:0x... or peaqos:machine:<id>). |
--display-name |
Yes | Human-readable machine name. |
--owner-id |
Yes | Operator/owner identifier. |
--machine-type |
Yes | Machine type (e.g. edge-node, robot). |
--runtime-profile |
Yes | Runtime profile (e.g. linux-docker). |
--capabilities |
No | Machine capabilities (comma-separated). |
--skill-keys |
No | Skill keys the machine supports (comma-separated). |
--labels |
No | Machine labels (key=value, comma-separated). |
--identity-signature-file |
No | Path to file containing a pre-signed EIP-191 signature. |
--identity-key-file |
No | Path to file containing the DID controller private key for signing. Mutually exclusive with --identity-signature-file. |
--skip-activate |
No | Register in draft status without activating. |
-y, --yes |
No | Skip confirmation prompt. |
--json |
No | Output raw JSON. Requires a non-interactive signing method (--identity-signature-file, --identity-key-file, or OWS wallet). |
Example output
[1/4] Requesting identity challenge...
[2/4] Signing identity challenge...
Signed with key from ./controller.key
Signer: 0x1111...1111
[3/4] Registering machine...
[4/4] Activating machine...
Machine onboarded successfully (active).
Machine ID: mach_abc123
Identity: did:peaq:0xAbCd...1234
Status: active
Name: My Edge Node
Next: peaqos scale agent pair --machine-id mach_abc123
peaqos scale machine status
Display details of a single machine.
peaqos scale machine status mach_abc123
peaqos scale machine status mach_abc123 --json
Example output
Machine mach_abc123
Display name: My Edge Node
Status: active
Identity: peaqos:machine:my-bot
Owner: operator-42
Type: edge-node
Runtime: linux-docker
Capabilities: price-feed, qvac
Skills: pyth-price-feed
Created: 2026-05-16T12:00:00Z
peaqos scale machine list
List all machines registered on the orchestration service.
peaqos scale machine list
peaqos scale machine list --json
Example output
Machines
ID Name Status Identity Type
─────────────────────────────────────────────────────────────────────────────────────────
mach_abc123 My Edge Node active peaqos:machine:my-bot edge-node
mach_def456 Test Machine draft did:peaq:0xAbCd...1e8f robot
2 machines found.
peaqos scale search
Search for services matching a task in the Machine Market. The agent describes what it needs (service type, capabilities, budget) and gets back a ranked list of matching quotes.
Requires an active machine and a valid agent pairing token
(--pairing-token-file).
peaqos scale search \
--machine-id mach_1 \
--service-type oracle.price-feed \
--pairing-token-file ./token.txt
peaqos scale search \
--machine-id mach_1 \
--service-type oracle.price-feed \
--pairing-token-file ./token.txt \
--json # raw JSON to stdout
Flags
| Flag | Required | Description |
| --machine-id | Yes | Machine performing the search. |
| --service-type | Yes | Service type (e.g. oracle.price-feed). |
| --pairing-token-file | Yes | Path to file containing the agent pairing token. |
| --agent-pairing-id | No | Agent pairing ID. |
| --operation | No | Desired operation (e.g. get-latest-price). |
| --capabilities | No | Required capabilities (comma-separated). |
| --region | No | Preferred region. |
| --max-results | No | Max quotes to return. |
| --budget-amount | No | Budget amount. |
| --budget-max | No | Maximum budget amount. |
| --budget-currency | No | Budget currency (e.g. USD). |
| --native-only | No | Require native execution (no external handoff). |
| --allow-handoff | No | Allow external handoff. |
| --provider-credentials | No | Path to JSON file with provider credentials. |
| --json | No | Output raw JSON to stdout. |
Example output
Searching for "oracle.price-feed" services...
Found 2 matching services.
# Skill Key Provider Score Execution Integration
────────────────────────────────────────────────────────────────
1 pyth-price-feed pyth 0.95 native native
2 dia-price-feed dia 0.72 ext-handoff partner-required
Search ID: msearch_449650d9b2be
Use: peaqos scale order <service-id> to place an order (when available).
When no quotes are returned:
Searching for "compute.marketplace" services...
No matching services found.
Search ID: msearch_abc123
Try broadening your search: remove --native-only, increase --budget-amount, or try a different --service-type.
Environment
Orchestration-specific variables (in .env or environment):
| Variable | Purpose |
|---|---|
PEAQOS_ORCHESTRATION_URL |
Base URL of the Machine Markets API. |
PEAQOS_ORCH_API_KEY |
Platform API key (deployment-level auth). |
PEAQOS_ORDER_STEP_DELAY_SEC |
Optional seconds to pause between order placement steps. |
The orchestration URL and API key can also be passed as CLI flags
(--orchestration-url, --orch-api-key).
peaqos scale order <service-uuid>
Place a market order end-to-end: create the order, handle payment when
required, then execute. The service UUID is the first argument (from a
prior peaqos scale search quote). Registered subcommands
(status, list, received, dispute) take precedence over service IDs.
Requires an active machine, agent pairing ID, and pairing token
(--pairing-token-file). Progress steps are written to stderr; the
final summary or --json payload goes to stdout.
Payment flows (chosen from the service quote):
| Pattern | Steps | When |
|---|---|---|
| No payment | [1/2] create → execute |
paymentStatus is not-required (e.g. native Pyth) |
| Wallet payment | [1/5] create → payment intent → send payment → proof → execute |
EVM USDC, Solana USDT, etc. |
| Escrow | Same as wallet, but step 4 calls escrow lock instead of payment proof | External handoff with on-chain escrow |
| x402 | [1/6] create → payment intent → sign → proof → execute → confirm |
Agentic Market providers (paid HTTP, e.g. Wolfram Alpha over USDC) |
For the x402 rail the CLI signs the provider's payment challenge locally with
the active wallet (client.account — the OWS wallet when PEAQOS_OWS_WALLET is
set, otherwise the local key) and hands the signed PAYMENT-SIGNATURE header to
peaqOS, which pays the provider during execute. There is no separate on-chain
transfer and no "paste the transaction hash" prompt. After order creation, you
confirm once before payment intent, signing, proof submission, and execution;
delivery is then confirmed automatically (step 6). If execution fails after proof is
recorded, the error reports the current payment status so you can verify whether
the authorization is held.
Payment transfer modes (step 3 when wallet payment is required; the x402 rail signs instead of transferring):
| Mode | How |
|---|---|
| OWS | PEAQOS_OWS_WALLET set — CLI signs and sends the ERC-20 transfer via the OWS vault; tx hash captured automatically. Passphrase from OWS_PASSPHRASE or an interactive prompt. |
| Manual | No OWS wallet — CLI prints amount, chain, token, and payee; operator completes the transfer and pastes the tx hash at the > prompt. |
| Pre-supplied | --payment-tx-hash (+ --payment-chain, --payment-token) — skips step 3; proof submitted with the given hash/signature. |
Use --skip-payment only when payment was already completed externally;
combine with --payment-tx-hash to record proof without re-sending funds.
Flags
| Flag / argument | Required | Description |
|---|---|---|
<service-uuid> |
Yes | Service ID from search results. |
--machine-id |
Yes | Machine placing the order. |
--agent-pairing-id |
Yes | Agent pairing ID (from peaqos scale agent pair). |
--pairing-token-file |
Yes | Path to agent pairing token file. |
--search-id |
No | Search ID from a prior peaqos scale search. |
--quote-id |
No | Quote ID from search results. |
--operation |
No | Requested operation (e.g. get-latest-price). |
--budget-amount |
No | Budget amount. |
--budget-currency |
No | Budget currency (e.g. USD). |
--input |
No | JSON file with operation input. |
--provider-credentials |
No | JSON file with provider credentials (never logged). |
--payment-tx-hash |
No | Pre-completed payment tx hash (EVM) or signature (Solana). |
--payment-chain |
No | Chain for proof (e.g. base, solana, peaq). Required with --payment-tx-hash. |
--payment-token |
No | Token for proof (e.g. USDC, USDT). Required with --payment-tx-hash. |
--skip-payment |
No | Skip the on-chain payment step (use with --payment-tx-hash when proof is supplied separately). |
-y, --yes |
No | Skip confirmation prompts. |
--json |
No | Output JSON to stdout (implies --yes). Contains order, execution, and payment when a payment record exists. |
Set PEAQOS_ORDER_STEP_DELAY_SEC to a non-negative number of seconds to pause
between placement steps for demos or eventually consistent order state. When the
variable is unset, no delay is applied.
Examples
No-payment service (native execution, two steps):
peaqos scale order svc_pyth_btc_usd \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--search-id msearch_449650d9b2be \
--quote-id quote_abc123 \
--operation get-latest-price \
--yes
[1/2] Creating order...
[2/2] Executing order...
Order executed.
Order ID: ord_e89c70259bdb
Service: BTC/USD (pyth-price-feed)
Status: delivered
Payment: not_required
Confirm delivery: peaqos scale order received ord_e89c70259bdb
Manual wallet payment (operator sends USDC, pastes hash):
peaqos scale order svc_dia_eth_usd \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--yes
# Step 3 prompts: paste 0x... tx hash after transferring off-wallet
OWS auto-payment (PEAQOS_OWS_WALLET in .env):
export PEAQOS_OWS_WALLET=agent
export OWS_PASSPHRASE='...' # optional; otherwise prompted once
peaqos scale order svc_dia_eth_usd \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--yes
[3/5] Sending payment...
Signing transfer via OWS (wallet=agent, chain=base)
0x3333...3333 → 0x4444...4444 1.00 USDC
Tx: 0x602d...5584
Pre-supplied payment (skip transfer step):
peaqos scale order svc_dia_eth_usd \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--payment-tx-hash 0x602d5584... \
--payment-chain base \
--payment-token USDC \
--yes
x402 paid provider (local signing, no on-chain transfer):
peaqos scale order "agentic-market:...:query:92c9d0a2" \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--input query.json
[1/6] Creating order...
Order summary:
Order ID: ord_3ba63e8494a8
Service: wolfram-alpha
Status: created
Payment: payment_pending
Proceed with payment and order execution? [y/N]: y
[2/6] Creating payment intent...
Payment required (x402).
Amount: $0.02
Chain: eip155:8453
Token: USDC (0x8335...2913)
Pay from: 0x9fbd...4913
Pay to: 0x6302...Ad57
The agent wallet will sign the x402 authorization next.
[3/6] Signing x402 payment...
[4/6] Recording payment proof...
[5/6] Executing order...
[6/6] Confirming delivery...
Order executed.
Order ID: ord_3ba63e8494a8
Service: Wolfram Alpha
Status: delivered
Payment: paid (x402)
Result: x^3/3 + C
External handoff (escrow + handoff URL):
Order placed (external handoff).
Order ID: ord_63ab7e934300
Service: Aethir GPU Cloud
Status: handoff
Handoff: Open Aethir Cloud → https://app.aethir.com/
After using the external service:
peaqos scale order received ord_63ab7e934300
JSON output (scripting):
peaqos scale order svc_pyth_btc_usd \
--machine-id mach_1 \
--agent-pairing-id pair_67c50f8fdd3c \
--pairing-token-file ./token.txt \
--yes --json
{
"order": { "id": "ord_e89c70259bdb", "status": "delivered", "...": "..." },
"execution": {
"status_code": 200,
"run": { "...": "..." },
"outcome": { "...": "..." }
}
}
When the order requires payment, the response also includes "payment": { "status": "held", ... }.
On partial failure after create, the error includes the order ID, current
payment status, and a hint to run peaqos scale order status <id>.
peaqos scale order status <order-id>
Check order and payment state.
peaqos scale order status ord_e89c70259bdb
peaqos scale order status ord_e89c70259bdb --json
Example output
Order ord_e89c70259bdb
Service: BTC/USD (pyth-price-feed)
Status: delivered
Execution: native
Created: 2026-05-16T12:00:00Z
Payment:
Status: not_required
Rail: —
Amount: —
Next: peaqos scale order received ord_e89c70259bdb
--json returns { "order": { ... }, "payment": { ... } }.
peaqos scale order list
List market orders for a machine (GET /market/orders). Supports
page-by-page listing with --limit and --cursor, or fetching every
order in one shot when using --json without --limit.
Flags:
| Flag | Description |
|---|---|
--machine-id |
Required. Machine whose orders to list. |
--limit |
Page size (1–500). Omitted → server default (100). |
--cursor |
Opaque cursor from a previous response (next page). |
--json |
Machine-readable output (see below). |
Human output (default) returns one page. When the API includes a
next_cursor, a copy-paste hint is printed after the table. Cursors are
shown verbatim in the hint and are never written to logs (even with
--verbose).
peaqos scale order list --machine-id mach_prod_smoke_mcr_1
peaqos scale order list --machine-id mach_prod_smoke_mcr_1 --limit 10
peaqos scale order list --machine-id mach_prod_smoke_mcr_1 \
--limit 10 --cursor eyJ2IjoxLCJvZmZzZXQiOjJ9
Example output (human)
Orders for mach_prod_smoke_mcr_1
ID Service Status Execution Created
─────────────────────────────────────────────────────────────────────────────────
ord_e89c70259bdb BTC/USD (pyth-price-feed) confirmed native 2026-05-16T12:25:00Z
ord_63ab7e934300 Aethir GPU Cloud disputed ext-handoff 2026-05-16T13:00:00Z
2 orders shown.
Next page: peaqos scale order list --machine-id mach_prod_smoke_mcr_1 --cursor eyJ2IjoxLCJvZmZzZXQiOjJ9
When there is no next page, only the count line is shown (no Next page: line).
JSON output:
| Invocation | Shape |
|---|---|
--json (no --limit) |
Root array of all orders across pages (auto-paginated). |
--json --limit N |
Single page: { "items": [...], "next_cursor": "..." | null }. |
# All orders (pipe-friendly for jq)
peaqos scale order list --machine-id mach_1 --json | jq '.[] | .id'
# Manual paging
peaqos scale order list --machine-id mach_1 --json --limit 5
[
{ "id": "ord_e89c70259bdb", "status": "delivered", "...": "..." },
{ "id": "ord_63ab7e934300", "status": "handoff", "...": "..." }
]
{
"items": [{ "id": "ord_e89c70259bdb", "...": "..." }],
"next_cursor": "eyJ2IjoxLCJvZmZzZXQiOjJ9"
}
Invalid --limit (0, negative, or above 500) exits with code 1 and:
Limit must be between 1 and 500.
peaqos scale order received <order-id>
Confirm delivery and release escrowed funds. The order must be in
delivered status (native execution or after external handoff).
peaqos scale order received ord_e89c70259bdb \
--pairing-token-file ./token.txt
peaqos scale order received ord_e89c70259bdb \
--pairing-token-file ./token.txt \
--json
Example output
Delivery confirmed.
Order ID: ord_e89c70259bdb
Status: confirmed
Payment: release_pending
peaqos scale order dispute <order-id>
Raise a dispute and freeze escrowed payment. Requires --reason and the
pairing token. Prompts for confirmation unless --yes or --json.
peaqos scale order dispute ord_63ab7e934300 \
--reason "Service unavailable after payment" \
--pairing-token-file ./token.txt \
--yes
# Optional evidence JSON file
peaqos scale order dispute ord_63ab7e934300 \
--reason "Incorrect deliverable" \
--evidence ./evidence.json \
--pairing-token-file ./token.txt \
--json
Example output
Dispute raised.
Order ID: ord_63ab7e934300
Status: disputed
Payment: frozen
Reason: Service unavailable after payment
Integration tests
Order lifecycle integration tests live at
tests/integration/commands/scale/test_order_integration.py. Enable with
PEAQOS_CLI_ORCH_INTEGRATION=1 and the PEAQOS_INTEGRATION_* variables
documented in that file.
peaqos stream grant
Grant a buyer decryption access to a published chunk chain. Reads chunk
envelope files from a publish output directory, unwraps the owner's per-chunk
keys, re-wraps them for the buyer, and writes peaq.stream.buyer-access.v1
files. Chunk envelope files are never modified — only new buyer access files
are produced.
Prerequisites:
- A publish output directory containing
chunk-*.jsonenvelope files (frompeaqos stream publish). The encryptedchunk-*.binblobs andmanifest.jsonare not read by this command. - Owner X25519 private key file (the key used when the chain was published).
- Buyer X25519 public key (hex) and buyer recipient ID (e.g.
did:peaq:<buyer-address>).
Progress and the human summary are written to stderr; --json writes only
the summary object to stdout.
Key file format: --owner-private-key-file expects an X25519 private key
as a single line of hex — exactly 64 hex characters, with an optional 0x
prefix. This is not the secp256k1 0x-prefixed 64-hex format used by
read_key_file in Utilities below.
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--chunk-dir |
Yes | — | Directory containing published chunk envelope files (chunk-*.json). |
--buyer-public-key |
Yes | — | Buyer's X25519 public key (hex). |
--buyer-id |
Yes | — | Buyer recipient ID (e.g. did:peaq:<buyer-address>). |
--owner-private-key-file |
Yes | — | Path to file containing the owner's X25519 private key (hex). |
--output-dir |
Yes | — | Directory to write buyer access files (created if missing). |
--max-file-size |
No | 512000 |
Maximum buyer access file size in bytes (500 KB). |
--json |
No | — | Output summary JSON to stdout (no other stdout output). |
Output files
Buyer access files use schema peaq.stream.buyer-access.v1. Files are named
<buyerPublicKeyHex>-<n>.json with a 1-based index (e.g.
a1b2c3d4...-1.json, a1b2c3d4...-2.json). Entries are batched up to
--max-file-size (default 500 KB). A single oversized entry gets its own
file; entries are never split across files.
Examples
peaqos stream grant \
--chunk-dir ./publish-output \
--buyer-public-key a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456 \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--owner-private-key-file ./owner-x25519.key \
--output-dir ./access
Progress and summary on stderr:
Granting access to 4 chunks for buyer did:peaq:0xBuyer00000000000000000000000000000001...
Wrote 1 buyer access file to ./access
Schema: peaq.stream.buyer-access.v1
Buyer ID: did:peaq:0xBuyer00000000000000000000000000000001
Chunks: 4
Files: 1
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456-1.json (12.3 KB)
# Smaller batch size → more access files
peaqos stream grant \
--chunk-dir ./publish-output \
--buyer-public-key a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456 \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--owner-private-key-file ./owner-x25519.key \
--output-dir ./access \
--max-file-size 1024
# JSON summary to stdout (stderr empty)
peaqos stream grant \
--chunk-dir ./publish-output \
--buyer-public-key a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456 \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--owner-private-key-file ./owner-x25519.key \
--output-dir ./access \
--json
{
"schemaVersion": "peaq.stream.buyer-access.v1",
"buyerId": "did:peaq:0xBuyer00000000000000000000000000000001",
"chunkCount": 4,
"fileCount": 1,
"outputDir": "./access",
"files": [
{
"name": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456-1.json",
"sizeBytes": 12634
}
]
}
Common errors
| Condition | Exit code | Message |
|---|---|---|
Wrong owner private key (key_commitment mismatch) |
2 |
Key commitment verification failed — wrong owner key? |
No chunk-*.json files in --chunk-dir |
1 |
No chunk files found in {path} |
| Gap or duplicate chunk indices | 1 |
Missing chunk at index {n} / Duplicate chunk at index {n} |
| Invalid buyer public key hex | 1 |
Validation error before SDK call |
Empty --buyer-id |
1 |
--buyer-id must not be empty. |
| Output directory not writable | 1 |
Cannot write to: {path} |
peaqos stream consume
Decrypt a purchased chunk chain and reassemble the original data. Verifies the chain integrity, decrypts each chunk using the buyer's wrapped key, and writes the reassembled original data to an output file.
Supports two input modes:
- Local directories — provide
--chunk-dir,--access-dir, and--data-dirpointing to directories already on disk. - Remote download — provide
--download-urlpointing to an HTTP/HTTPS release package. The package is downloaded to a work directory first, then the existing verify → decrypt → reassemble pipeline runs on the downloaded files. The work directory is deleted after successful reassembly unless--keep-filesis set.
Prerequisites:
- Buyer X25519 private key file (the key whose public key was used in grant).
- For local mode: chunk directory (
chunk-*.jsonenvelopes, optionallymanifest.jsonfrompeaqos stream publish), encrypted data directory (chunk-*.binblobs), and buyer access directory (*.jsonfiles frompeaqos stream grant). - For remote mode: an HTTP/HTTPS URL to a self-contained release
package that bundles everything the pipeline needs — chunk envelopes
(
chunk-*.json), encrypted data blobs (chunk-*.bin), and buyer access files (*.json) — exposed either as amanifest.jsonlisting those files or as a ZIP archive containing them. This is a self-hosted bundle, distinct from the SDKS3DeliveryChannelpre-signed URL, which delivers only the buyer access files (the ciphertext stays referenced by each chunk'sstorage_ref). Manifest file names are restricted to flat*.json/*.binnames. A query token on the URL (for a self-hosted endpoint that authorises that way) is preserved when fetching each file — but note an S3 pre-signed single-object URL cannot address the manifest's sub-paths (SigV4 signs the object path, so a changed path returns 403). A pre-signed URL pointing at a single ZIP object still works: the manifest probe returns 403/404 and the command falls back to fetching the signed object as a ZIP.
Roundtrip note (acceptance-criterion deviation).
--download-urldoes not consume the URL produced bypeaqos stream distribute/S3DeliveryChanneldirectly. That pre-signed URL delivers only the first buyer-access file; the chunk envelopes are not delivered and the ciphertext stays referenced by each chunk'sstorage_ref, and the SDK ships no buyer-side S3 receiver. A complete distribute → consume roundtrip therefore requires SDK/orchestration support (an S3 delivery receiver plus a descriptor enumerating every access file, chunk-envelope location, and astorage_refresolver) that does not exist yet. Until then, point--download-urlat a self-contained bundle as described above.
Progress and the human summary are written to stderr; --json writes only
the summary object to stdout.
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--chunk-dir |
Yes (local mode) | — | Directory containing chunk envelope files (chunk-*.json). Not used with --download-url. |
--access-dir |
Yes (local mode) | — | Directory containing buyer access files (*.json). Not used with --download-url. |
--data-dir |
Yes (local mode) | — | Directory containing encrypted data blobs (chunk-*.bin). Not used with --download-url. |
--buyer-private-key-file |
Yes | — | Path to file containing buyer's X25519 private key (hex). |
--buyer-id |
Yes | — | Buyer recipient ID matching the access files. |
--output |
Yes | — | Output file path for the reassembled data. |
--skip-verify |
No | False |
Skip chain verification (not recommended, debugging only). |
--json |
No | False |
Output summary JSON to stdout (no other stdout output). |
--download-url |
No | — | HTTP/HTTPS URL to a release package. Mutually exclusive with --chunk-dir, --access-dir, --data-dir. |
--work-dir |
No | temp dir | Working directory for downloaded files. Cleaned up after success unless --keep-files. Ignored when --download-url is absent. |
--keep-files |
No | False |
Keep the work directory after successful reassembly. Ignored when --download-url is absent. |
Examples
# Local mode — directories already on disk
peaqos stream consume \
--chunk-dir ./chunks \
--access-dir ./access \
--data-dir ./chunks \
--buyer-private-key-file ./buyer-x25519.key \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--output ./recovered-data.bin
# Remote download — fetch a self-contained release bundle
peaqos stream consume \
--download-url "https://bundles.example.com/releases/ord-001/" \
--buyer-private-key-file ./buyer-x25519.key \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--output ./recovered-data.bin
# Remote download — keep the downloaded files for inspection
peaqos stream consume \
--download-url "https://bundles.example.com/releases/ord-001/" \
--work-dir ./downloaded \
--keep-files \
--buyer-private-key-file ./buyer-x25519.key \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--output ./recovered-data.bin
# Skip verification (debugging only)
peaqos stream consume \
--chunk-dir ./chunks \
--access-dir ./access \
--data-dir ./chunks \
--buyer-private-key-file ./buyer-x25519.key \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--output ./recovered-data.bin \
--skip-verify
# JSON summary to stdout
peaqos stream consume \
--chunk-dir ./chunks \
--access-dir ./access \
--data-dir ./chunks \
--buyer-private-key-file ./buyer-x25519.key \
--buyer-id did:peaq:0xBuyer00000000000000000000000000000001 \
--output ./recovered-data.bin \
--json
Human output on stderr:
Downloading release package from https://bundles.example.com/releases/ord-001/...
Downloading chunk-0.json...
Downloading chunk-0.bin...
Downloading chunk-1.json...
Downloading chunk-1.bin...
Downloading buyer-access-abc123.json...
Verifying chain... ✓ 4 chunks valid.
Decrypting chunk 0/4...
Decrypting chunk 1/4...
Decrypting chunk 2/4...
Decrypting chunk 3/4...
Reassembled 1048576 bytes to ./recovered-data.bin
Source Hash: 0xabc123...
Chunks: 4
Buyer ID: did:peaq:0xBuyer00000000000000000000000000000001
JSON output:
{
"output": "./recovered-data.bin",
"totalBytes": 1048576,
"chunkCount": 4,
"sourceHash": "0xabc123...",
"buyerId": "did:peaq:0xBuyer00000000000000000000000000000001",
"verified": true
}
Download behaviour
When --download-url is provided, the command:
- Creates the work directory (
--work-dirif given, otherwise a temp dir). - Downloads land in a command-owned, uniquely named
peaqos-package-*subdirectory of the work directory, so a pre-existing--work-dir's files (including any priorpeaqos-package-*kept via--keep-files) are never touched. - Fetches
manifest.jsonfrom the URL path (a query token is preserved). If the manifest contains a"files"list, each file is downloaded individually with per-file progress onstderr(suppressed under--quiet). The manifest itself is persisted so itssourceHashsurvives. - If
manifest.jsonreturns 404 (absent) or 403 (e.g. a pre-signed single object), or has no"files"key, the base URL is downloaded as a ZIP archive and extracted. - Downloaded files are sorted (recursively, so a ZIP wrapping the package in a
top-level directory works) into
chunks/,data/, andaccess/subdirectories;manifest.jsonis co-located with the chunks so itssourceHashis recovered before the pipeline runs. - On success, cleanup removes only what the command created: a work directory
it created is removed entirely; otherwise only the
peaqos-package-*staging subdirectory is removed, and an--outputinside it is preserved.--keep-filesskips cleanup; a cleanup failure is reported as a warning. - On any error, the work directory is preserved for debugging.
Common errors
| Condition | Exit code | Message |
|---|---|---|
| Chain verification failed | 2 |
Chain verification failed at chunk {n}: {reason} |
| Missing encrypted data for a chunk | 2 |
Missing encrypted data for chunk {n} |
| No buyer access for a chunk | 2 |
No buyer access for chunk {n} ({chunk_id}) |
| Wrong buyer private key | 2 |
Decryption failed for chunk {n} — access not granted for this buyer private key |
key_commitment mismatch |
2 |
Key commitment verification failed for chunk {n} |
plaintext_hash mismatch |
2 |
Data integrity check failed for chunk {n} — plaintext hash mismatch |
| Download HTTP error | 2 |
Download failed: HTTP {code} from {url} |
| Download timeout | 2 |
Download failed: connection timed out after 60s |
| Downloaded archive not a valid ZIP | 2 |
Downloaded archive is not a valid ZIP file: {detail} |
| No chunk files in dir | 1 |
No chunk files found in {path} |
| No encrypted data files | 1 |
No encrypted data files found in {path} |
| No buyer access files | 1 |
No buyer access files found in {path} |
--download-url with a dir flag |
1 |
--download-url is mutually exclusive with --chunk-dir, --access-dir, and --data-dir. |
Invalid --download-url scheme |
1 |
--download-url must start with http:// or https://. |
Missing --chunk-dir (local mode) |
1 |
--chunk-dir is required when --download-url is not provided. |
Empty --buyer-id |
1 |
--buyer-id must not be empty. |
| Output path not writable | 1 |
Cannot write to: {path} |
peaqos stream pay
Transfer tokens on-chain to a seller and optionally submit the transaction hash as payment proof. Supports native token and ERC-20/SPL contract transfers on peaq, Base, and Solana.
When --confirmation-url is provided, proof is submitted immediately after the transfer. If omitted, only the transfer executes and a peaqos stream payproof hint is printed so proof can be submitted separately.
Progress lines are written to stderr; the transfer summary and --json payload go to stdout. The transaction hash is always written to stdout before the proof step, so it is captured even if proof submission fails.
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--seller-address |
Yes | — | Recipient address (EVM 0x... or Solana base58). |
--amount |
Yes | — | Human-readable transfer amount (e.g. "10.5"). |
--chain |
Yes | — | Target chain: peaq, base, or solana. |
--order-id |
Yes | — | Order ID for the purchase. |
--confirmation-url |
No | — | URL to submit payment proof after transfer. Omit to transfer only. |
--token-address |
No | — | ERC-20 contract (EVM) or SPL mint address (Solana). Omit for native token. |
--token-decimals |
No | — | Token decimal count override (for tokens not in the well-known registry). |
--rpc-url |
No | — | RPC endpoint. Required for --chain base and --chain solana. |
--private-key-file |
No | from config | Path to buyer private key file (0x-prefixed hex). Falls back to PEAQOS_PRIVATE_KEY. |
--json |
No | False |
Output result as JSON to stdout. |
Examples
# Native PEAQ transfer (no proof)
peaqos stream pay \
--seller-address 0xSeller...1234 \
--amount 10.5 \
--chain peaq \
--order-id order-001
# Base EVM transfer with proof submission
peaqos stream pay \
--seller-address 0xSeller...1234 \
--amount 1.0 \
--chain base \
--order-id order-002 \
--rpc-url https://mainnet.base.org \
--token-address 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--confirmation-url https://api.example.com/payments/proof
# Solana SPL transfer
peaqos stream pay \
--seller-address So111...base58 \
--amount 5.0 \
--chain solana \
--order-id order-003 \
--rpc-url https://api.mainnet-beta.solana.com \
--token-address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
# JSON output with proof
peaqos stream pay \
--seller-address 0xSeller...1234 \
--amount 10.5 \
--chain peaq \
--order-id order-001 \
--confirmation-url https://api.example.com/payments/proof \
--json
Human output (with --confirmation-url):
Transferring 10.5 on peaq to 0xSeller...1234...
Tx Hash: 0xabc123...
Chain: peaq
Status: submitted
Proof: accepted
Order ID: order-001
Submitted: 2026-06-25T12:00:05Z
Human output (without --confirmation-url):
Transferring 10.5 on peaq to 0xSeller...1234...
Tx Hash: 0xabc123...
Chain: peaq
Status: submitted
Submit proof manually: peaqos stream payproof --tx-hash 0xabc123... --order-id order-001 --confirmation-url <url>
JSON output:
{
"txHash": "0xabc123...",
"chain": "peaq",
"status": "submitted",
"payerAddress": "0xPayer...5678",
"payeeAddress": "0xSeller...1234",
"amount": "10.5",
"token": "PEAQ",
"tokenAddress": null,
"proof": {
"accepted": true,
"orderId": "order-001",
"submittedAt": "2026-06-25T12:00:05Z"
}
}
"proof" is null when --confirmation-url is omitted.
Error codes
| Condition | Exit | Message |
|---|---|---|
Invalid or empty --amount |
1 |
Validation message |
Empty --seller-address or --order-id |
1 |
Validation message |
| Missing Solana dependency | 1 |
Install instructions (pip install peaq-os-sdk[solana]) |
| Signing failure | 1 |
Sanitized message (no key material) |
| Insufficient balance | 2 |
Insufficient balance for transfer |
| Transaction reverted | 2 |
Transaction reverted: {reason} |
| Proof HTTP failure | 2 |
Payment proof submission failed: {reason} |
| Missing env vars / config | 3 |
Actionable config message |
peaqos stream payproof
Submit a payment proof for a completed on-chain transfer. Use this when the transfer was done outside of peaqos stream pay, or when the proof step from that command failed and needs to be retried.
Progress is written to stderr; the proof result and --json payload go to stdout.
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--tx-hash |
Yes | — | EVM transaction hash (0x...) or Solana transaction signature. |
--order-id |
Yes | — | Order ID associated with the payment. |
--confirmation-url |
Yes | — | URL to submit the payment proof to. |
--chain |
Yes | — | Chain the transfer was on: peaq, base, or solana. |
--payer-address |
Yes | — | Buyer wallet address that signed the transfer. |
--payee-address |
Yes | — | Seller wallet address that received the transfer. |
--amount |
Yes | — | Human-readable amount transferred (must match the original transfer). |
--token |
No | — | Token symbol metadata (e.g. USDC). |
--token-address |
No | — | Token contract or SPL mint address. Omit for native transfers. |
--json |
No | False |
Output result as JSON to stdout. |
Examples
# Submit proof for a previously completed transfer
peaqos stream payproof \
--tx-hash 0xabc123... \
--order-id order-001 \
--confirmation-url https://api.example.com/payments/proof \
--chain peaq \
--payer-address 0xPayer...5678 \
--payee-address 0xSeller...1234 \
--amount 10.5
# ERC-20 transfer proof (Base USDC)
peaqos stream payproof \
--tx-hash 0xdef456... \
--order-id order-002 \
--confirmation-url https://api.example.com/payments/proof \
--chain base \
--payer-address 0xPayer...5678 \
--payee-address 0xSeller...1234 \
--amount 1.0 \
--token USDC \
--token-address 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
# JSON output
peaqos stream payproof \
--tx-hash 0xabc123... \
--order-id order-001 \
--confirmation-url https://api.example.com/payments/proof \
--chain peaq \
--payer-address 0xPayer...5678 \
--payee-address 0xSeller...1234 \
--amount 10.5 \
--json
Human output:
Submitting payment proof...
Proof: accepted
Order ID: order-001
Submitted: 2026-06-25T12:00:05Z
JSON output:
{
"accepted": true,
"orderId": "order-001",
"submittedAt": "2026-06-25T12:00:05Z"
}
Error codes
| Condition | Exit | Message |
|---|---|---|
Empty --tx-hash or --order-id |
1 |
Validation message |
| Proof HTTP failure | 2 |
Payment proof submission failed: {reason} |
| Missing env vars / config | 3 |
Actionable config message |
peaqos stream distribute
Listen for buyer payment confirmation and deliver buyer access files. After publishing a chunk chain, the seller runs this command to wait for a buyer's payment to be confirmed, then automatically generates buyer access files and delivers them to S3.
The command polls --confirmation-url every --poll-interval seconds until
the endpoint reports a confirmed payment or --timeout seconds elapse. On
confirmation the SDK builds buyer access files (the same as peaqos stream grant), uploads them to the S3 path under {prefix}{buyer_id}/, and returns
a pre-signed download URL.
Prerequisites:
- A published chunk directory containing
chunk-*.jsonenvelope files (frompeaqos stream publish). - Owner X25519 private key file (the same key used at publish time).
- A reachable HTTP endpoint at
--confirmation-urlthat returns a JSON body containing at minimumstatus,buyer_id, andbuyer_public_key_hex. - AWS S3 credentials in
PEAQOS_S3_ACCESS_KEY_ID/PEAQOS_S3_SECRET_ACCESS_KEY(or the standardboto3credential chain) when--delivery s3. boto3installed (pip install peaq-os-cli[s3]).
Progress lines are written to stderr; the human summary is written to
stdout. --json writes only the result object to stdout.
Key file format: --owner-private-key-file expects an X25519 private key
as a single line of hex — exactly 64 hex characters, with an optional 0x
prefix. This is the same format accepted by peaqos stream grant.
Flags
| Flag | Required | Default | Description |
|---|---|---|---|
--chunk-dir |
Yes | — | Directory containing published chunk envelope files (chunk-*.json). |
--owner-private-key-file |
Yes | — | Path to file containing the owner's X25519 private key (hex). |
--confirmation-url |
Yes | — | HTTP endpoint to poll for payment confirmation. |
--order-id |
Yes | — | Purchase order identifier (purchaseId in the orchestration API). |
--poll-interval |
No | 30 |
Seconds between confirmation polls. |
--timeout |
No | 3600 |
Max seconds to wait for confirmation before giving up. |
--delivery |
Yes | — | Delivery channel. Currently only s3. |
--s3 |
Conditional | — | S3 bucket path (e.g. s3://my-bucket/prefix/). Required when --delivery s3. |
--s3-region |
No | from env | S3 region (overrides PEAQOS_S3_REGION). |
--s3-endpoint |
No | from env | Custom S3-compatible endpoint URL (MinIO, R2, etc.). |
--presign-expiry |
No | 3600 |
Pre-signed download URL expiry in seconds. |
--max-file-size |
No | 512000 |
Maximum buyer access file size in bytes (500 KB). |
--json |
No | — | Output result as JSON to stdout (no other stdout output). |
Examples
# Basic — poll every 30 seconds, 1-hour timeout
peaqos stream distribute \
--chunk-dir ./publish-output \
--owner-private-key-file ./owner-x25519.key \
--confirmation-url https://api.example.com/orders/ord-001/status \
--order-id ord-001 \
--delivery s3 \
--s3 s3://my-bucket/distributes/
# Faster polling with a shorter timeout
peaqos stream distribute \
--chunk-dir ./publish-output \
--owner-private-key-file ./owner-x25519.key \
--confirmation-url https://api.example.com/orders/ord-001/status \
--order-id ord-001 \
--delivery s3 \
--s3 s3://my-bucket/distributes/ \
--poll-interval 10 \
--timeout 300
# Longer-lived download links (24 hours)
peaqos stream distribute \
--chunk-dir ./publish-output \
--owner-private-key-file ./owner-x25519.key \
--confirmation-url https://api.example.com/orders/ord-001/status \
--order-id ord-001 \
--delivery s3 \
--s3 s3://my-bucket/distributes/ \
--presign-expiry 86400
# JSON output to stdout
peaqos stream distribute \
--chunk-dir ./publish-output \
--owner-private-key-file ./owner-x25519.key \
--confirmation-url https://api.example.com/orders/ord-001/status \
--order-id ord-001 \
--delivery s3 \
--s3 s3://my-bucket/distributes/ \
--json
Progress on stderr, summary on stdout:
Waiting for payment confirmation (polling every 30s)...
Payment confirmed for buyer did:peaq:0xBuyer00000000000000000000000000000001 (tx: 0xabc...)
Distributing 4 chunks to s3://my-bucket/distributes/
Buyer ID: did:peaq:0xBuyer00000000000000000000000000000001
Access Files: 1
Download URL: https://my-bucket.s3.amazonaws.com/distributes/did:peaq:0xBuyer.../access-1.json?X-Amz-Signature=...
Expires: 3600s
JSON output:
{
"order_id": "ord-001",
"buyer_id": "did:peaq:0xBuyer00000000000000000000000000000001",
"tx_hash": "0xabc...",
"chunks_distributed": 4,
"access_files_count": 1,
"delivery": {
"channel": "s3",
"download_url": "https://my-bucket.s3.amazonaws.com/distributes/...?X-Amz-Signature=...",
"delivered_at": "2026-06-25T12:00:00Z",
"presign_expiry": 3600
}
}
Common errors
| Condition | Exit code | Message |
|---|---|---|
| Payment confirmation timed out | 2 |
Payment confirmation timed out after {N}s for order {order_id} |
| S3 upload failed | 2 |
S3 upload failed: {reason} |
--delivery s3 without --s3 |
1 |
--s3 is required when --delivery is s3 |
--poll-interval not positive |
1 |
--poll-interval must be a positive integer. |
--timeout not positive |
1 |
--timeout must be a positive integer. |
| Non-confirmed payment status from SDK | 1 |
payment.status — ... (constraint: confirmed) |
No chunk-*.json files in --chunk-dir |
1 |
No chunk files found in {path} |
| Missing or unreadable owner key file | 1 |
Could not read key file: {path} (...) |
boto3 not installed |
3 |
boto3 is required for S3 delivery but is not installed — install with: pip install boto3 |
Errors
The CLI maps SDK and network exceptions to stable exit codes:
| Exit code | Meaning |
|---|---|
0 |
Success |
1 |
User / validation error (bad input, cap, rate limit) |
2 |
Network, RPC, or on-chain error (connection, HTTP, revert) |
3 |
Configuration error (missing env vars, invalid private key) |
Subcommands funnel exceptions through peaq_os_cli.errors.handle_sdk_error,
which raises click.ClickException with the mapped exit code and a
user-friendly message. Known on-chain revert reasons and Faucet API error
codes are translated by map_revert_reason and map_faucet_error.
Output formatting
Subcommands render results through peaq_os_cli.formatting to keep human
output consistent across the CLI:
truncate_address— shortens a hex address to0x{first4}...{last4}.format_timestamp— renders a Unix timestamp as ISO 8601 UTC, or—forNone.format_key_value— alignskey: valuepairs so the colons line up.format_table— left-aligned columnar table with a header separator.print_json— writesjson.dumps(data, indent=2)to stdout for pipe-friendly output.print_step— writes[{step}/{total}] {label}progress lines to stderr, suppressed when the active Click context is quiet.
Utilities
Input parsing and validation helpers in peaq_os_cli.utils:
parse_timestamp— accepts pure-digit Unix seconds or ISO 8601 strings with an explicit UTC offset (...Zor...+HH:MM). Raisesclick.BadParameteron unrecognised input.validate_did_format— requiresdid:peaq:0xfollowed by 40 hex characters.validate_address_format— requires a0x-prefixed 40-hex-character address.read_key_file— reads, strips, and validates a0x-prefixed 64-hex private key file. Raisesclick.ClickExceptionwith exit code1on missing files or invalid content.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file peaq_os_cli-0.0.6.tar.gz.
File metadata
- Download URL: peaq_os_cli-0.0.6.tar.gz
- Upload date:
- Size: 188.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
182ae2a1689f08a04889ac5cecb276740ae48ed863ba1e65753cf10bf5837bcb
|
|
| MD5 |
cbb2e5969266ef7b0d06daf34f6d5a6d
|
|
| BLAKE2b-256 |
7fecd90353e926779bf2fe9c27ad1a01e71f87011690d828e35a60d83f8873be
|
Provenance
The following attestation bundles were made for peaq_os_cli-0.0.6.tar.gz:
Publisher:
peaq-os-cli-py.yml on peaqnetwork/peaq-os-cli-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
peaq_os_cli-0.0.6.tar.gz -
Subject digest:
182ae2a1689f08a04889ac5cecb276740ae48ed863ba1e65753cf10bf5837bcb - Sigstore transparency entry: 2089146283
- Sigstore integration time:
-
Permalink:
peaqnetwork/peaq-os-cli-py@785e59865d52eee35f6ad3bb4dfce2421c298d67 -
Branch / Tag:
refs/heads/dev - Owner: https://github.com/peaqnetwork
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
peaq-os-cli-py.yml@785e59865d52eee35f6ad3bb4dfce2421c298d67 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file peaq_os_cli-0.0.6-py3-none-any.whl.
File metadata
- Download URL: peaq_os_cli-0.0.6-py3-none-any.whl
- Upload date:
- Size: 174.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19425097a5e253eca45e7a53782fbd3f8216f42297154c27ad773d998012ce42
|
|
| MD5 |
fad89ab288dade7ffa78c23891d7ec09
|
|
| BLAKE2b-256 |
7648dc500019d081dbe673412e459ad94ea1348bd8e72c772e3258c0cddaa2ff
|
Provenance
The following attestation bundles were made for peaq_os_cli-0.0.6-py3-none-any.whl:
Publisher:
peaq-os-cli-py.yml on peaqnetwork/peaq-os-cli-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
peaq_os_cli-0.0.6-py3-none-any.whl -
Subject digest:
19425097a5e253eca45e7a53782fbd3f8216f42297154c27ad773d998012ce42 - Sigstore transparency entry: 2089147105
- Sigstore integration time:
-
Permalink:
peaqnetwork/peaq-os-cli-py@785e59865d52eee35f6ad3bb4dfce2421c298d67 -
Branch / Tag:
refs/heads/dev - Owner: https://github.com/peaqnetwork
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
peaq-os-cli-py.yml@785e59865d52eee35f6ad3bb4dfce2421c298d67 -
Trigger Event:
workflow_dispatch
-
Statement type: