// Chapter 14 · Operate
Node CLI
The network is CLI-first for one reason: operators run their nodes on headless machines, often through SSH, often as a service.
CLI-first because operators run on headless machines.
// 14.0 · v1.2.1 · runs on ssh + as a service · ollama-backed
// Daemon shape
Node key, probe, init, start, service, heartbeat, serve, claim-elsewhere. Eight responsibilities.
The Node CLI is CLI-first because operators run their nodes on headless machines, often through SSH, often as a managed service. It runs on macOS and Linux; on Windows, inside WSL2. Inference executes on Ollama, the open-source LLM runtime the one-line installer sets up for you.
Staking, claiming rewards, and unstaking are on-chain wallet actions done in the Operator Console (registerNode, claim, requestUnstake, withdrawStake), not CLI subcommands. The CLI is the off-chain half: it attaches a machine to a node the wallet already staked and keeps it online with liveness heartbeats. It uses a separate, low-value node keypair, never the staking wallet's key. The two halves share only the nodeId.
- 00:00registerednode #4231 · stake 50,000 $PRLX
- 00:04onlineCLI attached · heartbeating · state active
- 01:12request servedinference · served whole · PoE ✓
- 01:12reward accrued+12.84 $PRLX · uptime credit
Nodes serve whole ParalleliX AI inference requests. There is no task submission or sub-task fan-out on the live path.
The Console shows each node's online status and live earnings. The CLI is the off-chain half that keeps the machine online.
weight = stake x tier x uptime
share = daily_pool x weight / Σ weight
source: 25% Operator Rewards bucket · ~34,200 $PRLX/day via Sablier
Per-day reward breakdown sourced from the 25% Operator Rewards bucket, which unlocks linearly via Sablier, or a share of ParalleliX AI usage in steady state. Rewards accrue on-chain and are claimed in the Console.
What the CLI does
// 14.1 · eight responsibilities · the daemon's hot path is poll · run · commit · sign · return
// Daemon responsibility register · 8 entries
- // 14.1.1Node key management
Generate and protect a node secp256k1 key: a separate, low-value liveness key, never the staking wallet's key.
- // 14.1.2Attach by nodeId
Attach the machine to a node already registered on-chain in NodeRegistryLocker, then submit the signed capability manifest.
- // 14.1.3Liveness heartbeats
Send signed liveness heartbeats to the coordinator every 10s. An online node is what OperatorStakeRewardsV2 streams rewards to; offline nodes do not accrue.
- // 14.1.4Coordinator link
Poll the coordinator for dispatched requests and maintain liveness; heartbeat every 10s.
- // 14.1.5Inference execution
Run each dispatched inference request whole through Ollama on local hardware. A single inference is served by one node, not split.
- // 14.1.6Proof-of-execution
Compute the SHA-256 PoE and return personal-signed results.
- // 14.1.7Run as a service
Install as systemd (Linux) or launchd (macOS) to run 24/7, survive reboot, and auto-restart.
- // 14.1.8Local status + logs
status prints node state; logs tails ~/.parallelix/node.log.
Command surface
// 14.3 · 9 subcommands · all accept --json
// parallelix-node · subcommands9 commands
parallelix-node probeDetect local hardware + Ollama; print the tier it maps to
parallelix-node initGenerate the secp256k1 node key (a separate, low-value key) and config; print the nodeKeyHash
parallelix-node models [pull <name>]List local Ollama models, or pull one (defaults to llama3.2)
parallelix-node startRun the daemon: attach to the on-chain nodeId, heartbeat, serve inference, return PoE (--gpu|--cpu, --model)
parallelix-node serviceInstall as a background service (systemd/launchd): 24/7, survives reboot, auto-restarts
parallelix-node verifyRun diagnostics: Node version, key permissions, Ollama + model, coordinator reachability
parallelix-node statusPrint local node state (address, nodeKeyHash, tier, contracts)
parallelix-node logsTail the node log (~/.parallelix/node.log)
parallelix-node versionPrint the CLI version
State machine
// 14.4 · start binds to an on-chain nodeId · unstake is initiated in the Console · transitions emit state.transition
┌──────────┐
│ FRESH │ (installed, no node key)
└────┼─────┘
│ init (generate node key, print nodeKeyHash)
▼
┌──────────┐
│ INITED │ (node key present, config written)
└────┼─────┘
│ registerNode in Console → nodeId
│ start --node-id N
▼
┌──────────┐
│ ACTIVE │ (online, heartbeating, serving; accruing rewards)
└────┼─────┘
│
┌─────────┼─────────────┐
▼ ▼ │ requestUnstake() in Console → coordinator 403
(idle) (running ▼
machine inference) ┌──────────┐
off) │ │ COOLING │ (daemon self-stops; 7-day cooldown)
└────┼─────┘ └────┼─────┘
▼ │ withdrawStake() in Console after cooldown
loop ▼
┌──────────┐
│ RETIRED │ (principal returned; nodeId retired)
└──────────┘The hot path
// 14.6 · poll, run, commit, sign, return · run is the only slow step
// Per-request hot path · 6 stepsexecute = slow step
- // 01
Poll
GET coordinator /operator/inbox?nodeId=<id> for a dispatched request. One whole inference request.
- // 02
Run
Ollama /api/generate with the model and prompt, whole on the local GPU/CPU. The only slow step.
- // 03
Commit
poe = sha256(request_id ‖ result ‖ node_id).
- // 04
Sign
signature = personal-sign(node.key, "parallelix-node:result:<id>").
- // 05
Return
POST coordinator /operator/result { result, poe, signature }.
- // 06
Heartbeat (in parallel)
Every 10s, personal-sign and POST /operator/heartbeat. This keeps the node online and accruing.
Status and logs
// 14.9 · status prints node state · logs tails ~/.parallelix/node.log
$ parallelix-node status
// node status
· node address 0x…
· nodeKeyHash 0x…
· tier 3
· coordinator https://parallelix.io/api
· ollama http://127.0.0.1:11434
$ parallelix-node logs
2026-… start node=4217 mode=gpu model=llama3.2
2026-… served req_a3f1 model=llama3.2 ms=47 poe=0x…
2026-… served req_a3f5 model=llama3.2 ms=92 poe=0x…Security primitives
// 14.10 · key ownership · signature on every message · no outbound credentials
// Security invariants · 4 entries
- // 01
Separate node key. A secp256k1 key generated on first init, stored at ~/.parallelix/node.key with mode 0600. It signs liveness and results only, never the staking wallet's key. init --force overwrites it and orphans the old node.
- // 02
Signature on every message. Every heartbeat and result is Ethereum personal-signed by the node key. The coordinator verifies it; unsigned or mis-signed messages are ignored.
- // 03
Self-stop on unstake. The coordinator returns 403 not_staked or in_cooldown for a node no longer backed on-chain; the daemon prints the reason and exits cleanly rather than spinning.
- // 04
No outbound credentials. The CLI emits no wallet private keys, no contract-owner keys, no third-party tokens.
// Where to go next · reading path