# Shekyl CLI User Guide This guide covers the command-line tools shipped with shekyl-core. If you prefer a graphical interface, see the [Shekyl GUI Wallet User Guide](https://github.com/Shekyl-Foundation/shekyl-gui-wallet/blob/main/docs/USER_GUIDE.md) instead -- both guides share the same section structure so you can cross-reference equivalent features. --- ## Table of Contents 1. [Introduction and Prerequisites](#introduction-and-prerequisites) 2. [Running a Node (shekyld)](#running-a-node-shekyld) 3. [Wallet Basics (shekyl-cli)](#wallet-basics-shekyl-cli) 4. [Sending and Receiving](#sending-and-receiving) 5. [Staking](#staking) 6. [Mining](#mining) 7. [PQC Multisig](#pqc-multisig) 8. [Anonymity Networks (Tor and I2P)](#anonymity-networks-tor-and-i2p) 9. [Network Selection](#network-selection) 10. [Post-Quantum Security](#post-quantum-security) 11. [Wallet RPC Server](#wallet-rpc-server-shekyl-wallet-rpc) 12. [Blockchain Utilities](#blockchain-utilities) 13. [Security and Backup](#security-and-backup) 14. [Troubleshooting](#troubleshooting) 15. [Glossary](#glossary) 16. [Getting Help](#getting-help) --- ## Introduction and Prerequisites ### What are the CLI tools? Shekyl ships a set of command-line programs for running a node, managing wallets, and working with blockchain data. They are the same programs that the GUI wallet uses behind the scenes, and they give you full control over every feature. Use the CLI tools when you want to: - Run a dedicated node on a server (headless, no desktop environment) - Script wallet operations or build integrations - Access advanced features not yet exposed in the GUI - Operate over SSH or inside containers ### System requirements - **OS / architecture:** Linux (**x86_64, ARM64 only**), macOS (Intel, Apple Silicon), Windows (**64-bit only**, via MSYS2). **32-bit targets are not supported and must not be used:** Shekyl's post-quantum primitives (ML-KEM-768, ML-DSA-65) require 64-bit arithmetic for their constant-time security property, and running a 32-bit Shekyl wallet exposes the wallet private key to a published timing-side-channel attack class (see `docs/STRUCTURAL_TODO.md` §"32-bit targets cannot safely run Shekyl" for the technical analysis). If your hardware is 32-bit-only — older Raspberry Pi Zero / Pi 1, pre-2005 x86 desktops, some embedded boards — Shekyl is not appropriate for it. - **Disk:** ~50 GB for a full node; ~10 GB with `--prune-blockchain` - **RAM:** 4 GB minimum, 8 GB recommended during initial sync - **Network:** Reliable broadband; the initial sync downloads the full chain ### Shipped executables | Binary | Purpose | |--------|---------| | `shekyld` | Full node daemon -- connects to the network, syncs the chain, relays transactions | | `shekyl-cli` | Interactive command-line wallet | | `shekyl-wallet-rpc` | Wallet RPC server for programmatic access | | `shekyl-gen-ssl-cert` | Generate self-signed SSL certificates for RPC | | `shekyl-blockchain-import` | Import blockchain from a file | | `shekyl-blockchain-export` | Export blockchain to a file | | `shekyl-mdb-copy` | Compact a stopped daemon's database | | `shekyl-blockchain-stats` | Print blockchain statistics | | `shekyl-blockchain-ancestry` | Trace transaction ancestry chains | | `shekyl-blockchain-depth` | Compute minimum chain depth for outputs | | `shekyl-blockchain-usage` | Histogram of output reuse as ring members (legacy) | ### Getting the binaries Download pre-built releases from the [GitHub releases page](https://github.com/Shekyl-Foundation/shekyl-core/releases), or build from source following the [Installation Guide](INSTALLATION_GUIDE.md). --- ## Running a Node (`shekyld`) The daemon is the engine of the Shekyl network. It downloads and verifies every block, maintains the UTXO set, and relays transactions. Your wallet talks to the daemon -- it cannot function without one. ### First launch ```bash ./shekyld ``` On first run, `shekyld` creates a data directory and begins downloading the blockchain from peers. The default locations are: - **Linux:** `~/.shekyl/` - **macOS:** `~/.shekyl/` - **Windows:** `C:\ProgramData\shekyl\` Initial sync takes several hours depending on your hardware and network. You will see log lines showing block height, download rate, and verification progress. Let it run until you see "SYNCHRONIZED OK" in the output. ### Configuration file Instead of passing flags on the command line, you can write them in a config file. The syntax is `optionname=value`, one per line. Boolean flags use `optionname=1`. ``` # shekyld.conf data-dir=/var/lib/shekyl log-file=/var/log/shekyl/shekyld.log log-level=0 prune-blockchain=1 # RPC defaults to loopback. For your own wallet on another machine you # control, bind a view-only second listener (not a public remote node): # rpc-restricted-bind-port=11030 ``` Load a config file with `--config-file /path/to/shekyld.conf`. See [`utils/conf/shekyld.conf`](../utils/conf/shekyld.conf) for a minimal example. ### Key daemon flags **Data and logging** | Flag | Description | |------|-------------| | `--data-dir ` | Override the blockchain data directory | | `--log-file ` | Write logs to a specific file | | `--log-level <0-4>` | Verbosity: 0 = minimal, 4 = trace | | `--max-log-file-size ` | Rotate logs when they exceed this size (default 104857600) | | `--max-log-files ` | Number of rotated log files to keep | **Synchronization and storage** | Flag | Description | |------|-------------| | `--prune-blockchain` | Enable pruning (~95% storage reduction for old prunable data) | | `--db-sync-mode ` | LMDB sync mode: `safe`, `fast`, `fastest` | | `--block-sync-size ` | Number of blocks per sync batch | **RPC** | Flag | Description | |------|-------------| | `--rpc-bind-port ` | HTTP RPC listen port (default: 11029 mainnet); Axum is the sole transport | | `--rpc-bind-ip ` | Bind address for RPC (default: 127.0.0.1). IPv4 or IPv6 (`::1`). Loopback only: a wildcard (`0.0.0.0`, `::`) is refused, and so is a network address — the daemon RPC has no authentication. `--rpc-use-ipv6` also binds `--rpc-bind-ipv6-address` (default `::1`) on the same start. Another machine of yours reaches this node through its onion service | | `--restricted-rpc` | Disable admin endpoints on the main listener (view-only for *your* wallet; not a public remote node) | | `--rpc-restricted-bind-port ` | Second view-only listener for a wallet you operate | | `--rpc-access-control-origins ` | Comma-separated CORS allow-list (default: deny) | shekyld does **not** accept `--rpc-login` or `--rpc-ssl*` (inbound RPC is plaintext). Use loopback locally; for remote access prefer an onion service or a reverse proxy. Wallet-RPC retains login/SSL flags for its own listener. **Peer-to-peer** | Flag | Description | |------|-------------| | `--p2p-bind-port ` | P2P listen port (default: 11021 mainnet) | | `--out-peers ` | Maximum outbound peer connections | | `--in-peers ` | Maximum inbound peer connections | | `--add-peer ` | Manually add a peer | | `--add-priority-node ` | Peer that is always maintained | | `--ban-list ` | File of banned IP addresses | **Background operation** `shekyld` always runs in the foreground. Use your platform's service manager for background operation (systemd on Linux, launchd on macOS, Task Scheduler on Windows); the GUI wallet supervises its own bundled `shekyld` via the Tauri sidecar. An example systemd unit lives at `contrib/packaging/linux/shekyld.service`. The `--detach`, `--pidfile`, and `--*-service` flags were removed in V3.1. | Flag | Description | |------|-------------| | `--non-interactive` | Disable the interactive console (required under a service manager) | ### Interactive console When `shekyld` is running in the foreground, you get an interactive console. Type `help` to list all commands. The most useful ones, grouped by purpose: The same commands work from a second shell against a running daemon — `shekyld status`, `shekyld exit` — over its local RPC port (pass `--rpc-bind-port` / `--testnet` if the daemon is not on the defaults). The exit status is `0` when the daemon answered, `1` when the command is unknown or the request failed (daemon not running, connection refused, error reply), so scripts can check it without parsing the output. **Status and information** | Command | Description | |---------|-------------| | `status` | One-line summary: height, net hash, connections, sync state | | `print_height` | Current blockchain height | | `diff` | Current mining difficulty | | `sync_info` | Detailed sync and peer download state | | `hard_fork_info` | Current and upcoming hard fork versions | | `version` | Daemon version string | **Mining** | Command | Description | |---------|-------------| | `start_mining [threads]` | Start the built-in CPU miner | | `stop_mining` | Stop mining | | `mining_status` | Current mining state, hash rate, address | | `show_hr` / `hide_hr` | Toggle real-time hash rate display | **Network and peers** | Command | Description | |---------|-------------| | `print_pl` | Full peer list | | `print_pl_stats` | Peer list statistics | | `print_cn` | Active connections with data transfer stats | | `print_net_stats` | Aggregate network bandwidth | | `bans` | List all banned peers | | `ban [seconds]` | Ban a peer | | `unban ` | Remove a ban | | `limit_up ` / `limit_down ` | Set bandwidth limits | | `out_peers ` / `in_peers ` | Adjust peer count at runtime | **Chain inspection** | Command | Description | |---------|-------------| | `print_bc [end]` | Print block headers in a range | | `print_block ` | Print a single block's details | | `print_tx ` | Print transaction details | | `is_key_image_spent ` | Check if a key image is spent | | `print_pool` | Full transaction pool | | `print_pool_sh` | Transaction pool (short format) | | `print_pool_stats` | Pool statistics | | `alt_chain_info` | Show alternative chain branches | | `bc_dyn_stats ` | Dynamic block stats for recent blocks | | `print_coinbase_tx_sum ` | Sum of coinbase outputs in a range | **Maintenance** | Command | Description | |---------|-------------| | `save` | Force a blockchain save | | `flush_txpool [txid]` | Remove transaction(s) from the pool | | `flush_cache [bad-txs\|bad-blocks]` | Clear internal caches | | `pop_blocks ` | Roll back the last N blocks | | `prune_blockchain` | Enable pruning on a non-pruned database | **Exit** | Command | Description | |---------|-------------| | `stop_daemon` / `exit` | Gracefully shut down | --- ## Wallet Basics (`shekyl-cli`) `shekyl-cli` is an interactive shell: start it, then type commands at the prompt. The prompt always names the network — and the open wallet, when there is one: ``` mainnet> testnet:miner> ``` Type `help` for the full command list and `help ` for one command's usage. Wallet files live under `~/.shekyl/wallets//` by default, one directory per network, so a testnet wallet can never shadow a mainnet one. `--wallet-dir ` overrides the directory. ### Creating a new wallet At the prompt: ``` mainnet> create mywallet ``` You will be prompted for a password, and the wallet's 24-word BIP-39 seed phrase (English wordlist) is shown **once** — **write it down on paper immediately**. This seed is the only way to recover your funds if your wallet file is lost. To keep the seed out of logs and scrollback, `create` refuses to print it when output is piped or redirected. For scripts there is a non-interactive subcommand that writes the seed to a file instead of the terminal (created `0600`, refusing to overwrite): ```bash ./shekyl-cli create mywallet --seed-out /safe/path/seed.txt \ [--password-file | --password-stdin] ``` Your wallet is automatically a V3 wallet with full post-quantum key material (Ed25519 + ML-DSA-65). No extra steps are needed. ### Restoring from a seed phrase At the prompt: ``` mainnet> restore mywallet word1 word2 ... word24 ``` or non-interactively, reading the seed from a file: ```bash ./shekyl-cli restore mywallet --seed-file /safe/path/seed.txt \ [--password-file | --password-stdin] ``` If you opted in to a BIP-39 passphrase at creation, you will need it here too. After a restore, run `refresh` to scan the chain for your funds. The seed words are the only restore path: every wallet key (spend, view, message-signing, ML-KEM) derives from the master seed, so there is no separate restore-from-keys flow and no view-only wallet variant. ### Opening an existing wallet At the prompt: ``` mainnet> open mywallet ``` or open at startup: ```bash ./shekyl-cli --wallet mywallet ``` ### Connecting to a daemon By default the wallet connects to a daemon on this machine, at the RPC port for the selected network (`127.0.0.1:11029` on mainnet; `--testnet` and `--stagenet` pick the matching port automatically). If no daemon is answering there, the wallet says so when it starts and names the command that would fix it (`shekyld --testnet`, and the port it answers on). `shekyld` serves RPC on loopback only, so a node of yours on another machine is reached through a Tor onion service you run in front of its loopback RPC (see "Wallet through Tor" below), over a SOCKS proxy: ```bash ./shekyl-cli --wallet mywallet \ --proxy socks5h://127.0.0.1:9050 \ --daemon-address :11029 ``` Shekyl RPC is operator-to-operator: there is no recommended configuration in which the wallet talks to a daemon someone else controls, and `shekyld` does not advertise itself as a public node. A `--daemon-address` that is not loopback is said out loud when the wallet starts — whoever operates that daemon sees which blocks the wallet requests and what it broadcasts, and no proxy or encryption changes that. The warning reads the same for your own node: it states what a daemon is told, not who you are talking to. Without `--proxy`, a non-loopback address additionally warns that the connection itself is visible on the network path. ### Understanding Bech32m addresses Shekyl uses a segmented **Bech32m** address format with three parts: 1. **Classical segment** (`shekyl1...`) -- ~113 characters, contains Ed25519 spend and view public keys 2. **PQC-A segment** (`skpq...`) -- contains part of the ML-KEM-768 encapsulation key 3. **PQC-B segment** (`skpq2...`) -- contains the rest of the ML-KEM-768 key The full address is approximately 2,030 characters. When sharing addresses, use `address --out`, `make_uri`, or payment-request URIs — never retype it. To see your address inside the wallet: ``` mainnet> address ``` By default this prints a **short display form** (the first 24 characters, an ellipsis, and the last 12) plus the full length — enough to recognize the address at a glance, and explicitly not valid for pasting. `address --full` prints the whole string; `address --out ` writes it to a new private file so the full form never has to transit terminal scrollback or shell history. --- ## Sending and Receiving ### Receiving SKL Your wallet has **one reusable primary address**. On-chain privacy comes from per-output cryptography (stealth outputs, hybrid KEM) — **not** from generating a new address for every sender. Reuse your address freely; rotation does not improve chain privacy and is not recommended as default hygiene. Display your primary address: ``` mainnet> address ``` (the short display form; `address --full` / `address --out ` for the real string — see "Understanding Bech32m addresses" above). **Merchants and invoicing:** create a **payment request** (amount, label, optional expiry) and share a `shekyl:` URI with query parameters: ``` mainnet> request new