FearMiner 1.15.2 - GPU and CPU miner
================================================================================
https://fearminer.com

One binary, one launcher per algorithm, and the algorithms' engines in
engines/ (see ENGINES). fearminer --list-algorithms prints what it mines
and the fee of each; fearminer --help prints every option.


QUICK START
--------------------------------------------------------------------------------
The window: double-click fearminer.exe on Windows, FearMiner.app on a Mac
(FearMiner-<version>-macos-arm64.zip, a download of its own), or run
fearminer gui on any desktop. Pick the algorithm, put your pool, wallet and worker, tick
the cards, Start. It saves them in fearminer.toml beside the binary, the
file the launchers and the command line read, and shows the hashrate, the
shares, each card's temperature, power and fan, and the log. Any argument,
or a launcher, is the command line below, as ever.

1. Open the launcher of the algorithm you mine (start_quantus.bat,
   start_randomx.bat, start_pearl.bat or start_tensorcash.bat on Windows,
   start_quantus.sh, start_randomx.sh or start_pearl.sh on Linux and
   macOS) in a text editor and put YOUR wallet address and
   YOUR pool in it. The WALLET and the POOL shipped there are placeholders:
   the launcher refuses to start with either. The pool is yours to choose,
   its host and port from the pool's own page (stratum+ssl://HOST:PORT);
   the miner never picks one for you, and the lines commented beside POOL
   show the form. WORKER is any name for this machine.
   Or write the setup in a file instead: fearminer config example prints
   fearminer.toml with every option and its default; put it beside the
   binary with your wallet and your pool in it and the launcher runs on it
   (see CONFIGURATION FILE below). By hand:
   fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1 (see THE WALLET
   AND ITS POOL).

2. Run it. The miner watches itself: a supervisor process restarts the
   mining process after a crash or a hung card (see SUPERVISOR below), and
   the launcher restarts the whole thing if it ever stops.

3. Read the cockpit: hashrate, shares, per-GPU cards, the log. Keys: q quits,
   l shows the log alone. The same in a window: http://127.0.0.1:4300/gui
   in any browser on this machine (start_tensorcash_gui.bat opens it for
   you on Windows); it is served by the miner itself and calls nothing else. Stats are also served on http://127.0.0.1:4300/stats
   and on the API, http://127.0.0.1:4300/api/v1/summary (this machine only;
   --api-bind 0.0.0.0:4300 opens them to the LAN, see API below).
   Each GPU card shows what the card is doing when it is not mining:
   "Paused (temp 91 °C)" while the thermal cut-off holds it (see below),
   "Lost" when the driver reported it gone (the other cards carry on),
   "Excluded" for a card left out with -d. /stats carries the same as
   "state", one entry per card.
   See WHAT THE COCKPIT SHOWS below for the figures.


WHAT THE COCKPIT SHOWS
--------------------------------------------------------------------------------
Local vs effective hashrate. The big figure is the local hashrate, what the
cards compute. "eff" beside it is the effective hashrate, what the pool
credits: the difficulty of the shares it accepted in the last hour, over
that time, and its percentage of the local average over the same hour. The two differ by the stale shares, the latency and the luck of
the window.
Under ten accepted shares in the window the figure is not given yet: the
cockpit shows the estimate dimmed with its margin, "~118.2 T +-41 %" (one
standard error, about 1/sqrt(shares)), and the figure from the tenth share
on. An hour lets a slow card reach ten shares.

Shares per device. Each card's row shows acc/rej, the pool's verdicts on
that card's shares, the stale ones in parentheses (a stale is a share the
pool refused because its job was gone: latency, not the card). A card with
a hardware fault is the one whose rejects are not stale, or the one with
an "invalid N" note: a solution the card handed back that the CPU refused
before it was submitted (see SELF-TEST AND VERIFIED SHARES below).

Efficiency. kH/W, in the header for the rig and on each row: the session's
hashes over the joules the card drew, from the driver's energy counter
where the card keeps one (exact) or integrated from the board power the
driver reports (NVML on NVIDIA). Board power, not wall power: the power
supply's losses and the rest of the machine are not in it. "-" on an engine
that reports no power (Vulkan, CPU).

Sensors. Each GPU row shows the core temperature and, when the card has the
sensors, the memory and hotspot ones ("64°C · mem 78 · hot 81"), the fan,
the power against its limit, the clock and the card's own throttle reasons.
Memory temperature is on most cards from the 3090 class up; a laptop or a
small card has none. The hotspot sensor is not in NVML, so on NVIDIA it
stays absent. /stats and the API carry every reading, and also the energy
counter, the ECC counters, the PCIe replay counter and the PCIe link (a
card at gen 1 x1 under load is on a bad riser), null where the card or the
driver gives none.

On /stats the same figures are hashrate_effective_hs, hashrate_effective_pct,
efficiency_kh_per_w (null when they cannot be computed) and, per row under
devices, shares_accepted, shares_rejected, shares_stale, efficiency_kh_per_w,
temp_mem_c, temp_hotspot_c, energy_mj, throttle_reasons, ecc_corrected,
ecc_uncorrected, pcie_replays, pcie_gen, pcie_width, and tuning: the row's
autotune while it runs ({phase, done, total, percent, elapsed_s, eta_s,
best, best_rate}), null otherwise. The top-level tuning is true while any
device tunes; the rates are left as they are during a tune.
Also there: mode ("mining" or "monitoring") and time_to_first_share_s, the
seconds from the start of the process to the first share the pool accepted
(null before it; the log says it once: "first share accepted after 12.3 s").


THERMAL CUT-OFF
--------------------------------------------------------------------------------
Each sensor is judged against its own limit: the core against --temp-limit
(90), the memory against --temp-limit-mem (105), the hotspot against
--temp-limit-hotspot (100); 0 turns that sensor's cut-off off. A sensor
must stay at or over its limit for --temp-hold seconds (15) before the card
is paused: a spike at a job change is not a hot card, and a dip under the
limit starts the count again. The paused card finishes its search, then
idles with the sensor and its reading on the row, "Paused (mem 106 °C)",
until every sensor that held it has cooled past its resume point: the core
to --temp-resume (75), the memory and the hotspot to their limit minus
--temp-hysteresis (10). The log says so once on pause (E306) and once on
resume; a pause is the temp_high notification.

--temp-shutdown is the last resort, off by default: a paused card whose core
stays at or over it for --temp-hold seconds, counted from the pause that
should have cooled it, stops the miner with exit code 11, E319 on the log
and a temp_critical notification. A card never paused is never shut down. Under the supervisor the miner is restarted after the backoff
and gives up after --max-restarts if the card is still that hot. Must be
over --temp-limit. --no-nvml leaves NVML closed: no sensors at all (null on
the API), the gpu start line says so instead of the thresholds, the cut-off
has nothing to read, mining goes on.


OVERCLOCKING
--------------------------------------------------------------------------------
Off unless asked: without an OC option the miner touches no clock, power
limit or fan register, so a rig whose overclock is set outside (a HiveOS
flight sheet, Afterburner, nvidia-smi) keeps it. --no-oc makes it
explicit and the start log says so.

With an option given (--cclock, --lock-cclock, --mclock, --lock-mclock,
--pl, --fan; one value for every card, or one per card in -d order), the
card is set through NVML, the driver's own library, with no X server:
the same calls nvidia-smi -lgc, -lmc and -pl make. Setting a clock needs
root (--allow-root); without it every set is E703 with what to do, and
mining goes on at the clocks the card has. Every set is read back: the log, fearminer oc show
and /api/v1/oc show what the card reads as, never what was asked. A
memory lock must be one of the steps the card publishes (oc show lists
them; E701 lists them otherwise); a power limit or an offset must be
inside the card's range (E702 shows the minimum and the maximum); a card
without fan control refuses --fan (E704, a laptop); a refused setting
leaves the others alone. --oc-delay holds the core offset and lock back
until the card has started mining (its first accepted share, or 30 s)
plus that many seconds, for the rigs that crash when the offset lands on
a cold card.

Every change opens a step on the log, "OC step: GPU0 core +100, mem +800,
pl 220 W -> hashrate over the next 10 min and rejects/invalids", and ten
minutes later the summary with the rate averaged since and the accepted,
rejected and invalid shares counted since, so you see where the limit is.

Before the first set, what each card read as is recorded in
oc-restore.json in the state directory (the values present at launch, not
the factory ones) and put back at a clean stop, by the supervisor when
the mining process crashed or was killed, and by fearminer oc reset after
a run killed without cleanup (E708 on the log, with the cause). A lock has
no read-back in the driver, so a lock the miner set is reset to the
driver's default, which also removes one set outside before the start.
fearminer oc reset --defaults resets the cards to the driver's defaults
instead. In the file, [oc] takes the options and [oc.quantus],
[oc.randomx]... a set per algorithm, applied for the algorithm mined.
AMD and Intel cards are not controlled in this version.


WHAT IS IN THIS FOLDER
--------------------------------------------------------------------------------
  fearminer(.exe)        the miner, one executable; it reads
                         a fearminer.toml beside it when there is one (see
                         CONFIGURATION FILE), never writes it, and outside
                         its folder it writes only two caches: the GPU tuning
                         result (~/.config/fearminer/tuning.json on Linux,
                         %USERPROFILE%\.config\fearminer\tuning.json on
                         Windows, ~/Library/Caches/fearminer on macOS) and the
                         state directory ~/.cache/fearminer
                         (%USERPROFILE%\.cache\fearminer on Windows): the
                         engines it fetched (engines/, see ENGINES), the
                         single-instance lock (fearminer.lock), the crash
                         counters per card
                         (crashes.json), the wallet fingerprints per pool
                         (wallets.json, a hash, never the wallet), the
                         self-test verdicts (selftest.json), the last
                         benchmark per algorithm (bench-<algo>.json), the
                         supervisor's log (watchdog.log, 256 KB at most),
                         the API token (api_token, see API below) and the
                         telemetry's install id (telemetry-id, see
                         TELEMETRY below; none with --no-telemetry), plus a
                         log file when you ask for one (--log-file, see LOG
                         FILE below)
  fearminer-helper       Linux only: the privileged helper RandomX uses for the
                         MSR tweaks and the huge pages, through sudo (see
                         RANDOMX below); the miner itself never runs as root
  engines/               the signed index of the algorithms' engines and the
                         engines of this platform, as the release found them:
                         a first start with no network mines from here (see
                         ENGINES); keep it beside the binary
  start_<algo>.bat/.sh   one launcher per algorithm, to edit and run
  readme.txt             this file
  THIRD-PARTY-NOTICES.txt  the licences of the open-source components inside
  openapi.json           the description of the API (see API below)
  telemetry-schema.json  what the telemetry may send, field by field, and what
                         it never sends (see TELEMETRY below)
  SHA256SUMS.txt         checksums of the files in this folder


MANUAL RUN
--------------------------------------------------------------------------------
  fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1           (your pool, your wallet;
                                                                   the chain read off it)
  fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1 --coin qtc
  fearminer --config fearminer.toml                                (everything from the file)
  fearminer config example > fearminer.toml                        (a file to start from)
  fearminer --dry-run ...                                          (what would run, and
                                                                   where each value came from)
  fearminer --check-config ...                                     (0 if it would start, 2 why not)
  fearminer -a quantus -o stratum+ssl://pool.example.com:3335 -u WALLET.rig1
  fearminer -a quantus -o pool.example.com:3333 -u WALLET -w rig1   (plain TCP)
  fearminer -a quantus -o stratum+ssl://pool.example.com:3335 -o stratum+tcp://backup.example.com:3333 -u WALLET.rig1
                                                                   (a backup pool)
  fearminer -a randomx -o stratum+ssl://pool.example.com:3335 -u WALLET.rig1
                                                                   (Monero, CPU)
  fearminer -a pearl -o stratum+ssl://pool.example.com:3335 -u WALLET.rig1
                                                                   (Pearl, NVIDIA)
  fearminer -a tensorcash -o wss://tensorcash.boblabs.eu:443/v1/ws -u WALLET.rig1
                                                         (TensorCash, NVIDIA, 20 GB)
  fearminer --list-algorithms                                      (algorithms, fees)
  fearminer --list-algorithms --json                               (the same, as JSON)
  fearminer --list-devices                                         (your GPUs: index, PCI id, UUID)
  fearminer --list-devices --json                                  (the same for a script)
  fearminer --benchmark --duration 30                              (no pool needed)
  fearminer --benchmark --bench-seed 1                             (same checksum every run)
  fearminer -a all --benchmark                                     (every algorithm, then a summary)
  fearminer --self-test                                            (the engines' known answers)
  fearminer --help                                                 (everything)

Options people ask about
  -o A -o B  (or -o A,B)      a backup pool: A is the primary; B is used when A
                              fails, and the miner returns to A when it answers
                              again (probed every five minutes). -u, -p,
                              --tls-fingerprint and --tls-spki take one value
                              for every pool, or one per pool in the same order.
  --pool-retries 3            attempts on a pool before the next one is tried;
                              a pool that refuses the login is skipped at once
  --job-timeout SECS          seconds without a new job before the connection
                              is treated as dead and made again; the chain's
                              own figure without it (quantus 120, randomx 300,
                              pearl 180), 0 turns it off
  --submit-timeout 10         seconds a submitted share waits for the pool's
                              reply before it is counted as unanswered (E125)
  --max-latency MS            leave a pool whose replies take longer than this
                              (the median of the last twenty) for two minutes,
                              for a faster pool of the list (E129); 0 = off
  -d 0,2                      mine on GPUs 0 and 2 only (indices from --list-devices,
                              in the order nvidia-smi prints the cards)
  -d pci:0000:41:00.0         the same card by its PCI id (--list-devices prints it;
                              41:00.0, pci:41 in hex or bus:65 in decimal also work)
  -d GPU-3f2a...              the same card by its UUID, whole, as --list-devices
                              prints it: the one name that follows the card to
                              another slot or another rig. A prefix is not a card.
  -d nvidia                   every NVIDIA card (amd, intel: none in this build, the
                              Vulkan engine takes the first N cards it finds whatever
                              their vendor; cpu is not a card, the CPU is -t)
  -d "!1"                     every card but GPU 1 (also !pci:41:00.0, !GPU-3f2a...,
                              !nvidia); a list of cards to use and a list to leave
                              out do not mix. On NVIDIA the exact cards are picked;
                              the Vulkan and Metal engines take the first N cards,
                              so only -d 0,1
  --device-missing first      when -d names a card this rig does not have: match
                              (the default) refuses the start (E206); first and last
                              keep the configuration and mine on the cards present,
                              the per-card lists laid over them from the first
                              position on, or from the last back; the log says which
                              cards were expected and not found
  --temp-limit 90             pause a GPU whose core stays at or over this for
  --temp-resume 75            --temp-hold seconds, until it has cooled to this one;
                              on by default at 90/75, --temp-limit 0 turns the core
                              cut-off off. Said in the log once on pause, once on
                              resume (see THERMAL CUT-OFF below). One value for every
                              card, or one per card in -d order (85,80,_: _ keeps the
                              default, a shorter list leaves the rest at it, a longer
                              one is refused with the count)
  --temp-limit-mem 105        the same on the memory sensor, resuming at the limit
  --temp-limit-hotspot 100    minus --temp-hysteresis (10); 0 turns that sensor off;
                              a card without the sensor is not judged on it
  --temp-hold 15              seconds a sensor must stay at or over its limit before
                              the pause; a shorter spike changes nothing
  --temp-shutdown 100         stop the miner (exit code 11) when a core stays at or
                              over this for --temp-hold seconds; off by default, the
                              last resort against a card that heats while paused
  --no-nvml                   do not open NVML: no GPU sensors, nothing for the
                              cut-off to read, mining goes on
  --lock-cclock 1500          overclocking (NVIDIA, through the driver, no X server
  --cclock +100               needed): a core clock lock or offset, a memory clock
  --lock-mclock 10251         lock (on a step the card publishes) or offset, the
  --mclock +800               power limit in watts or as a percentage of the card's
  --pl 220 / --pl 80%         default, the fan in percent or auto; one value for
  --fan 70%                   every card, or one per card in -d order (100,_,-50).
                              Without any of them the miner touches no register.
                              Every set is read back, every refusal explained with
                              its code (E703: needs root, --allow-root). What each
                              card read as before is put back at exit, by the
                              supervisor after a crash, and by fearminer oc reset
                              (see OVERCLOCKING below)
  --oc-delay 20               apply the core offset and lock 20 s after the card has
                              started mining (its first accepted share, or 30 s at
                              most), for the rigs that crash when the offset lands
                              cold; 0 by default
  --no-oc                     ignore every OC option and any [oc] section: no
                              register touched, said at start (the OC is set outside)
  --oc-reset-on-start         the driver's defaults first, then the options
  --oc-script <path>          run this program once per card before mining, with
                              FEARMINER_DEVICE, _PCI_BUS, _UUID and _ALGO set
  fearminer oc show           what each card reads as and publishes; oc reset puts
                              back what a run killed without cleanup left
  --list-devices --json       the listing as JSON: every card with its index, name,
                              PCI id, UUID, memory, compute capability, driver, vendor
                              and engine, plus the CPU (model, cores, threads, L3,
                              AES, NUMA nodes; with -a randomx its performance
                              prerequisites under cpu.performance) and the RAM
  --skip-preflight            do not act on the checks run before the first
                              connection (see BEFORE IT CONNECTS below)
  --self-test                 run the engines' known-answer test now: alone,
                              offline for the algorithm of -a (--self-test=all
                              for every one), exit 0 or 3; on a mining run,
                              at start even when the last one passed (see
                              SELF-TEST AND VERIFIED SHARES below)
  --verify-shares off         do not re-check GPU solutions on the CPU before
                              they are submitted (on by default; CPU solutions
                              are not re-checked either way)
  --bench-seed N              the deterministic benchmark: the same nonces and
                              the same checksum on every run (see BENCHMARK)
  fearminer explain E302      what an error code on the log means and what to do
  fearminer token show        the API token (see API below); token rotate replaces it
  fearminer cockpit           the cockpit of the miner already running here (the
                              service, another terminal); q closes the view, the
                              miner keeps running; also: fearminer watch
  fearminer verify SHA256SUMS check a download offline (see VERIFY A DOWNLOAD)
  -t 4                        add 4 CPU threads (off by default on a rig with a GPU;
                              for RandomX, one per physical core by
                              default); also -t 50% or -t -2 of that automatic
                              choice, or per algorithm: -t randomx:16,quantus:32;
                              more than the machine can spare (every thread but
                              two, one per card) is capped, and the cpu line says so
  --cpu-affinity 0-7          pin the CPU workers to these CPUs (a list, or a hex
                              mask 0xff) instead of the automatic placement
  --cpu-priority 0..5         the CPU workers' priority, XMRig's scale (2 is
                              normal; above needs a privilege on Linux)
  --msr auto|off|PRESET       RandomX: the MSR tweaks through fearminer-helper
                              (auto by default: applied when the helper is there,
                              else a coded line says what is lost; see RANDOMX)
  --1gb-pages                 RandomX: 1 GiB pages for the dataset (see RANDOMX)
  --helper PATH               where fearminer-helper is (default: the installed
                              /usr/local/bin/fearminer-helper, else the copy beside
                              the miner); an explicit path is the only one tried,
                              the installed one is not tried behind it; nothing
                              usable there is E601 on a RandomX run, never a refusal
  --tls-fingerprint <sha256>  pin a pool's self-signed certificate (see TLS below)
  --tls-spki sha256/BASE64    pin its public key instead (survives a renewal)
  --tls-tofu                  trust a certificate on first use, refuse another one
  --tls-insecure              accept any certificate: a TLS port forward or proxy
  --proxy socks5://host:port  every pool connection through a SOCKS5 proxy (Tor:
                              socks5://127.0.0.1:9050), the engines' included;
                              the proxy resolves the names
  --dns doh                   resolve the pool names over DNS over HTTPS (--doh-url);
                              doh-strict never asks the system resolver
  --ipv4-only / --ipv6-only   one address family (both by default, IPv6 first)
  --api-bind 0.0.0.0:4300     stats endpoint and API on the LAN (GET /stats, /hive-stats,
                              /mmpos, /api/v1/...; see API below); --no-api
                              disables it
  --no-telemetry              no telemetry at all: no install id, nothing sent
                              to telemetry.fearminer.com (see TELEMETRY below)
  --telemetry-interval 15     minutes between two telemetry beats (5 to 1440)
  --no-tui                    plain scrolling log instead of the cockpit (a pipe, a
                              file and TERM=dumb get the log too)
  --no-color                  no colour in the log, the cockpit in the terminal's own
                              colours (NO_COLOR in the environment does the same)
  -v                          debug log
  --log-file <path>           also write the log to a file (see LOG FILE below)
  --no-supervisor             one process, no supervisor (see SUPERVISOR below)
  --max-restarts 5            restarts allowed in --restart-window (30 min)
                              before the supervisor gives up (exit code 12)
  --on-failure script:<path>  run that script when it gives up (default: exit)
  --no-watchdog               no hang, hashrate, share or reject check, no
                              quarantine (see SUPERVISOR below)
  --hang-timeout 60           seconds without a sign of life from a GPU search
                              before the card is declared hung
  --hashrate-min 50%          the least a GPU's ten-minute average may be, as
                              a share of its best (or the rig's total: 300M);
                              under it the card is Degraded, then restarted
                              after --hashrate-grace (300 s); 0 turns it off
  --share-famine 5            expected share intervals a GPU may go without
                              finding a share before its search is restarted
  --max-rejects 15            shares refused in a row before the session is
                              reconnected, then moved to the next pool;
                              --max-rejects-device 5 marks the one card
  --no-share-timeout 1800     seconds without any accepted share before the
                              next pool is tried
  --device-quarantine 3       restarts blamed on one GPU in --restart-window
                              before it sits the next run out
  --reset-crashes             clear the crash counters kept per GPU (by UUID, so a
                              card keeps its count in another slot)
  --allow-multiple            run even when another fearminer is running
  --allow-root                mine as root (refused otherwise, exit code 3; the
                              HiveOS package passes it, the mmpOS one as root)
  --pass-file <path>          the pool password from a file, one line per pool,
                              instead of -p (see WHERE THE HASH GOES below)
  --ignore-wallet-check       send the wallet as typed, without checking it
  --notify-telegram TOKEN:CHAT  alerts to a Telegram chat (see NOTIFICATIONS)
  --notify-discord <url>      alerts to a Discord channel's webhook
  --notify-url <url>          alerts to your own endpoint, as JSON
  --notify-test               send one test message to each and exit
  --heartbeat-url <url>       ping a URL every minute (healthchecks.io,
                              Uptime Kuma), so a frozen rig is noticed
  --history off               keep no history at all (on by default, see
                              HISTORY below)
  --history-retention 90      days of history kept
  --history-max-size 32       hard bound on the history file, in MB; it wins
                              over the retention, which is cut back to fit

Every option can also be set from the environment as FEARMINER_<OPTION>
(FEARMINER_URL, FEARMINER_USER, FEARMINER_DEVICES, ...) and from the
configuration file (next section).


CONFIGURATION FILE
--------------------------------------------------------------------------------
fearminer config example > fearminer.toml prints a complete file: every
option under its own name, with its default and its help as a comment,
a commented [oc.<algo>] set under [oc], and no wallet or pool in it. Put
your wallet and your pool in and the miner runs on it:

  [pool]
  url = ["stratum+ssl://pool.example.com:3335"]
  user = "qzjd5MS1GSCpXLYp8DjZASifnkgtUpx5WwhmEzW3ppHdDe3uq"
  worker = "rig1"

  [devices]
  temp_limit = 85

A key is the option's name with underscores (--temp-limit is temp_limit),
at the top level or under the section named after its heading in --help
([pool], [network], [devices], [output], [benchmark], [supervisor],
[watchdog]). A switch takes true or false; the pool list takes a string or
a list of strings, or one [[pools]] table per pool with url, user, pass,
tls_fingerprint and tls_spki. ${VAR} in a string is replaced by that
environment variable.

The file is read from --config PATH (FEARMINER_CONFIG), else fearminer.toml
beside the binary, else the one in ~/.config/fearminer (Linux),
%APPDATA%\fearminer (Windows) or ~/Library/Application Support/fearminer
(macOS); --config "" reads none. The miner never writes it. A file named
with --config that is missing is an error (E211, exit code 2), and so is a
key that is not an option (E212, with the nearest one suggested), a value
of the wrong type or a ${VAR} that is not set (E213): a typo never leaves
an option silently at its default.

Precedence, lowest first: the defaults, the file, the FEARMINER_*
environment variables, the command line. A list (the pools) is replaced
as a whole by the source that sets it, never merged. --dry-run prints the
result, every key with its value and where it came from (default, file,
env, cli), the password masked, and what it makes (the mode, the
algorithm, the pools); --check-config validates it without mining and
exits 0 or 2 with the reason.


THE WALLET AND ITS POOL
--------------------------------------------------------------------------------
A wallet always comes with its pool:
  fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1
The pool is yours to choose; the miner never picks one. A wallet without a
pool is refused before anything is touched, at a start as under
--check-config and --dry-run, exit code 2:
  E224 wallet without a pool: a pool is needed: fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1 (or choose it in your cockpit's mining sheet)
Without -a, the chain is read off the address (a Quantus address, prefix
189, is quantus, printed as "algo quantus"; a Monero one randomx; a
prl1... one pearl); an address that fits several chains is refused by
name (E215) unless quantus, the default, is one of them; --coin qtc / -a
names the chain when it must.


WHEN THE POOL MISBEHAVES
--------------------------------------------------------------------------------
A pool that goes away is retried with a backoff: the wait doubles from
1 s to 60 s with every failure and is drawn at random under that, each
one logged with its reason and the clock time of the next attempt
(retrying <pool> in 6 s (backing off after 3 failed attempts; next
attempt at 14:03:22 UTC)); asking sooner would not make a pool that is
down come back. --pool-retries (3) attempts, then the next pool of the
list; with every pool down the list starts over, for ever.

A pool that answers can still misbehave; each case has a rule, a coded
line and a counter on the pool's record (GET /api/v1/pools):
  . a share with no reply within --submit-timeout (10 s) is unanswered
    (E125, shares.unanswered); --max-no-submit-responses (10) of those in
    a row reconnect the session (E113), and the next pool is tried when
    the next session goes the same way;
  . every refused share is one line with the pool's words and their
    class: low difficulty, stale, duplicate, unknown job, unauthorized or
    other (rejected_by_reason); result: false with no error is a refusal
    like any other;
  . no new job for --job-timeout seconds ends the session (E105); the
    figure is the chain's own unless set: 120 s on quantus, 300 s on
    randomx, 180 s on pearl;
  . a job sent again is ignored: the same line twice silently
    (jobs_duplicate), the work of an older job under any id as a replay
    (E128, jobs_replayed); the workers stay on the current job;
  . a job the rig has searched as far as its nonce space goes (2^32 on
    RandomX) is stopped (E127, nonce_space_exhausted) and the workers wait
    for the next job rather than hash the same nonces again;
  . a client.show_message is shown once, as text (escape sequences and
    control characters removed, 200 characters at most), never
    interpreted;
  . a client.reconnect is followed only towards a host of the pool list,
    on any port, after its wait (60 s at most), with the login of the
    listed pool it names; any other host is refused with one E126 line
    naming it;
  . with --max-latency MS, a pool whose replies take longer than that
    (the median of the last twenty) for two minutes is left for a faster
    pool of the list, when one answers faster (E129); the primary is
    taken back when it answers within the limit.


MONITORING MODE
--------------------------------------------------------------------------------
Started with no wallet and no pool at all (no arguments, or a file without
them), the miner does not print the help and does not exit: it watches the
machine instead of mining it. The checks run, the stats endpoint is up
(/stats says "mode": "monitoring"), the cockpit shows the cards with their
temperature, fan, power and clocks, and the banner says
  no wallet: monitoring only. To mine: fearminer -o stratum+ssl://POOL:PORT -u WALLET -w rig1
until Ctrl+C. Nothing is mined, for anyone: a service waiting for its
cockpit's mining sheet. A wallet without a pool is not monitoring: it is
refused (E224, exit code 2).


WHERE THE HASH GOES
--------------------------------------------------------------------------------
The wallet is checked before the miner connects anywhere: for Quantus it
must be a Quantus address (SS58, prefix 189, checksum verified), for
RandomX a Monero mainnet address (95 characters starting with 4 or 8, or
a 106-character integrated address; checksum verified; a testnet or
stagenet address is refused by name), the part of -u
before the .worker;
a +diff suffix or a solo: prefix is left out of the check and sent to the
pool as typed. A wallet that does not decode, or
one of another network, stops the miner with exit code 2, the cause and
what to do; nothing is guessed. --ignore-wallet-check sends it anyway and
the banner then says UNCHECKED.

Right after the version line, the log says where the hash goes, and the
cockpit header shows the same beside the pool (the wallet shortened, with
a check mark, "name" for an identity the pool resolves, or UNCHECKED for
one sent as typed):

  wallet   qzjd5MS1GSCpXLYp8DjZASifnkgtUpx5WwhmEzW3ppHdDe3uq (checksum ok)
  worker   rig1
  pool     stratum+ssl://pool.example.com:3335
  custody  pool (the pool pays the wallet)
  algo     quantus
  build    1.15.2 (a1b2c3d4e, 2026-09-21)  sha256 3a3524b62caa8307
  egress   ...

"build" carries the version and the first sixteen hex digits of the
SHA-256 of the running binary, so a log can be matched to a release
(SHA256SUMS.txt in this folder has the full one).

The miner also remembers, per pool, which wallet earned the last share
(wallets.json in the state directory, as a hash, never the wallet). When
the wallet differs at the next start it prints
  WARN wallet changed since the last session on <host> (was <date>)
shows "wallet changed" in the header, sets wallet_changed on /stats, and
keeps mining; the warning comes back at every start until the new wallet
earns a share. A miner whose configuration was changed behind your back
says so at once instead of mining for someone else for days.

Root and passwords. On Linux and macOS the miner refuses to start as root
(exit code 3): it needs no privileges; what RandomX wants from root goes
through fearminer-helper (see RANDOMX). --allow-root runs it anyway; HiveOS,
which runs every miner as root, gets it from the package. A real password
in -p (anything but the usual x) is visible in the process list, and the
miner says so once; --pass-file <path> reads it from a file instead, one
line per pool in the order of the pools, and warns when other users can
read the file. In the log file the password is always ***.


HISTORY
--------------------------------------------------------------------------------
The rig keeps its own history, in its own state directory: no server, no
database, nothing to set up. The last 24 hours are kept in memory, one
sample every 10 s, and written to <state dir>/history.bin once a minute
so a restart or a kill -9 does not lose them; on disk the same samples
are also rolled up as each window closes, one a minute for seven days,
one every five minutes for thirty, one an hour out to
--history-retention days (90).

A sample holds the local and the effective hashrate, the shares accepted,
rejected and invalid, the rig's power, the clock drift, the active pool
and the rig state, and per card the hashrate, the temperature, the fan,
the power and the clock. Rates and temperatures are averaged when samples
are folded together, share counts added, the pool and the state taken
from the newest; every answer says which per metric.

The file is one fixed-size ring per step, appended to a slot at a time
and never rewritten, with a CRC per record: it never grows, the oldest
sample is dropped by being written over, and a record torn by a power cut
is dropped at load instead of costing the file. --history-max-size is a
hard bound the file is laid out to from the first byte and it wins over
the retention. Ninety days of an eight-card rig is about 7 MB.

Read it with no miner running and nothing asked of the network:

  fearminer history --from -24h --step 5m
  fearminer history --from -7d --step 1h --metric temp_c --device 0
  fearminer history --from -30d --step 1h --format json

--from and --to take now, a relative -24h, -7d, -90m or -3600s, a unix
timestamp, or 2026-09-20T10:00:00Z; they default to a day ago and now.
--step takes 10s, 1m, 5m, 1h, 1d or bare seconds and picks which layer
answers. --format csv (the default) or json. The same data is served by
GET /api/v1/history?from=&to=&step=&metric=&device= on the API port.


LOG FILE
--------------------------------------------------------------------------------
--log-file <path> writes every line the miner logs to that file, with the
cockpit as with --no-tui: one line per record, a UTC timestamp with
milliseconds, no colour codes, the pool password replaced by ***. The file
is appended to, never emptied, so a restart by the launcher continues it.
It is rotated by size: at --log-max-size MB (10 by default) it becomes
<path>.1, the older ones move up, and --log-keep of them are kept (5 by
default). The file has its own level, --log-level-file (trace, debug, info,
warn, error; debug with -v, info otherwise), so it can hold a debug log while
the screen stays quiet. In plain mode a line a minute reports three
hashrates, the instant one, the ten-minute average and the session average,
then the effective one with its percentage of the local figure ("eff -"
under ten accepted shares).


SUPERVISOR
--------------------------------------------------------------------------------
Started to mine, fearminer is two processes: a small supervisor and the
mining process it starts with the same options. The supervisor holds no GPU
and survives whatever the driver does to the mining process. What you see
(the cockpit, the log) comes from the mining process, unchanged; the
supervisor prints only its own events, prefixed "supervisor:", and keeps
them in watchdog.log in the state directory.

  - Ctrl+C (or a SIGTERM) stops both: the mining process gets up to 8 s
    (--stop-timeout) to stop cleanly, then it is killed. A stop completes
    in under ten seconds even with a frozen card. Press Ctrl+C again to end
    the mining process at once.
  - A crash (a hung card, a driver fault, a lost device) restarts the mining
    process after 1 s, then 2 s, 4 s ... up to 60 s; ten minutes of healthy
    running reset the delay. A mistake in the options (exit code 2), a
    missing prerequisite (3) or another fearminer already running (4) is not
    restarted. After --max-restarts restarts in --restart-window (5 in
    30 min) the supervisor gives up (exit code 12), running the --on-failure
    script first if one is given. Every restart is logged with its cause.
  - The card that took the miner down is counted: the cockpit row shows
    "crashes N" and /stats carries "crashes" per card and "restarts".
    --reset-crashes clears the counters. A card blamed for
    --device-quarantine restarts (3) within --restart-window (30 min) sits
    the next run out: its row says Quarantined, the others carry on, a
    restart of the miner gives it another chance.
  - The watchdog inside the mining process (--no-watchdog turns it all off,
    and each rule is off on its own at 0); every verdict is logged with its
    code and its cause, and kept in watchdog.log:
      . a GPU search with no sign of life for --hang-timeout (60 s) is a
        hang: the miner exits for a restart (a hung kernel cannot be
        stopped from inside);
      . a card with no hashes for --zero-hashrate-timeout (5 min) while the
        other cards mine, or hashing at its usual rate with no accepted
        share for ten times the expected time between shares (10 to 60
        min) while the pool accepts shares from the other devices, is
        given up the same way;
      . a card whose ten-minute average falls under --hashrate-min (50 % of
        the best ten-minute average of the session, or the rig's total as
        300M) is Degraded on its row, and restarted if it stays under for
        --hashrate-grace (5 min); over --hashrate-max (off by default) the
        figure is wrong and is only reported;
      . a card that finds no share for --share-famine (5) times the
        expected interval, never under 10 min, while it hashes normally, is
        Degraded and its search restarted; a second famine restarts the
        miner;
      . a card whose shares the pool refuses --max-rejects-device (5) times
        in a row is Degraded until one is accepted (likely the overclock);
        the same count of solutions the CPU re-check refuses within ten
        minutes Degrades it too, until ten minutes pass without one;
        --max-rejects (15) refusals in a row from any device reconnect the
        session, and the next pool is tried when it happens again;
        --max-no-submit-responses (10) submits unanswered in a row (each
        for --submit-timeout, 10 s) reconnect it too, and the next pool is
        tried when it happens again;
      . no accepted share at all for --no-share-timeout (30 min) after the
        session connected: the next pool; a second such period restarts
        the miner;
      . a card the driver reports gone stops alone: its worker exits, its
        crash is counted, the others carry on; the miner exits for a
        restart only when nothing is left to mine on.
  - One instance at a time: a second fearminer exits with code 4;
    --allow-multiple runs several.
  - --no-supervisor runs one process, no supervisor, for a systemd unit,
    HiveOS or another watchdog that restarts the miner itself.

Exit codes: 0 stop requested; 1 error; 2 invalid options (a wallet that
does not decode is one); 3 missing prerequisite (no device, engine, port,
every device failing its self-test, or started as root without
--allow-root); 4 another instance running;
10 device crash or hang; 11 a watchdog verdict (zero, ghost or low
hashrate, a share famine, no accepted share) or a card past
--temp-shutdown; 12 the supervisor gave up; 13 died by a signal. 10, 11
and 13 are restarted by the
supervisor; the launcher stops on 2, 3, 4 and 12 and restarts on the rest.


BEFORE IT CONNECTS
--------------------------------------------------------------------------------
Before the stats port is bound or the pool is contacted, the miner checks
what the machine can mine with, one line each:
the NVIDIA driver (installed, version: 550 or newer, 570 for RTX 50), each
card's compute capability (7.0 or newer for the CUDA kernels) and free
memory against what the algorithm needs, the system memory, and whether it
runs in a virtual machine or under a locked-down or Secure Boot kernel,
with the effect on the algorithm (none for Quantus on a GPU).

A card that fails a check is left out with its code (E502, E310) and shows
as Excluded in the cockpit; the others mine. Nothing left to mine on is
E301 and exit code 3, before any connection. --skip-preflight prints the
same report and applies nothing.

Then the network: a "network" line (the proxy or the DNS mode, the address
families, trust on first use) and one "dns" line per pool saying what its
name resolves to and who answered (the system resolver, the DoH resolver,
or the proxy, which resolves the names itself). A name that resolves to
nothing is warned with its code (E107, E116, E117) and retried at every
connection attempt; it is not a stop.


TLS, PROXY AND DNS
--------------------------------------------------------------------------------
A stratum+ssl:// pool is spoken to over TLS 1.2 or 1.3 with the host name
as SNI, and its certificate is checked against the public roots built into
the binary. The protocol and the cipher are printed once per connection.
A refused certificate never falls back to plain TCP. A pool on a
self-signed certificate (a node, a P2Pool, a private pool) is pinned
instead:
  --tls-fingerprint SHA256    the SHA-256 of the certificate (openssl x509
                              -fingerprint -sha256); a renewal breaks the pin
  --tls-spki sha256/BASE64    the SHA-256 of its public key, HPKP notation; a
                              renewal that keeps the key does not break it
  --tls-tofu                  trust on first use: the certificate seen at the
                              first handshake is printed and remembered in
                              tls-pins.json in the state directory, keyed by
                              host:port; another certificate later is E118,
                              with both fingerprints. Accept the new one with
                              --tls-tofu-reset host:port, or delete the entry.
                              A file that cannot be read is E119: fixed or
                              moved away before the miner starts.
  --tls-insecure              check nothing: whatever certificate the pool
                              presents is accepted. For a TLS port forward
                              or a proxy, where the name dialled is not the
                              pool's and the public roots refuse a path that
                              works. Encrypted, not authenticated: anyone on
                              the path can impersonate the pool (E120 at
                              every start). A pool with a pin keeps its pin;
                              refused with
                              --tls-tofu or with no stratum+ssl:// pool left
                              to apply it to. The TLS line prints the SHA-256
                              of the certificate presented: pin it instead
                              when you can.
Each pin is one value for every pool, or one per pool (- for none); a
mismatch (E103) prints what was pinned and what the pool presented.

--proxy socks5://[user:pass@]host:port (FEARMINER_PROXY) sends every pool
connection through a SOCKS5 proxy: the session and the probes. The pool
names are handed to the proxy, which resolves them (no
DNS query for a pool leaves the machine; a .onion pool through Tor works).
A proxy that is down, refuses the credentials or cannot reach the pool is
E115 with the proxy's reply in words; the pool is never tried directly
while a proxy is configured. The password is masked on the log but visible
in the process list: prefer the configuration file or the environment.

The engines' own connections (the pool session an engine holds, the model
weights it downloads) go the same way. With --proxy, --dns doh or
doh-strict, or --ip 4|6, the miner runs an HTTP CONNECT proxy on
127.0.0.1 (a new port and password at each start) that dials through the
same proxy and resolver, and hands each engine its address (ALL_PROXY,
HTTPS_PROXY, HTTP_PROXY; NO_PROXY keeps loopback alone direct). An engine
that holds its pool session and cannot open it there (one published
before the engines could) is refused under --proxy and --dns doh-strict
(E325): a newer engine is needed, or run without the option. The terms,
the notifications and the heartbeat go through it too: a notification or
heartbeat URL off this machine and the local network must then be
https://.

--dns doh (FEARMINER_DNS) resolves the pool names over DNS over HTTPS at
--doh-url (https://cloudflare-dns.com/dns-query by default; an IP such as
https://1.1.1.1/dns-query works when the local DNS is what fails), falling
back to the system resolver when the endpoint does not answer (E116),
not for a name it says does not exist (E117); --dns doh-strict never asks
the system resolver at all (E116, E117). DoH hides
the names from the local resolver, not the pool from the network: the TLS
SNI and the pool's address stay visible; a proxy is what hides those.

--ip 4|6|any (FEARMINER_IP; --ipv4-only, --ipv6-only) picks the address
family. With both, a pool that resolves to IPv6 and IPv4 is connected IPv6
first and IPv4 250 ms later, the first to connect wins (Happy Eyeballs).
Every pool socket carries TCP keepalive (60 s idle, a probe every 10 s,
three probes), so a peer gone without a word is noticed in about a minute.


SELF-TEST AND VERIFIED SHARES
--------------------------------------------------------------------------------
Before the first share, every engine the run mines with answers its known
answers: the CPU engine its fixed vectors against the algorithm's reference
(for Quantus the chain's own qpow-math, for RandomX the library's test
vectors), and
each card 256 searches whose every answer is re-hashed on the CPU, then
eight searches at a real target whose solutions the CPU must confirm
(--self-test-nonces changes the 256). A card that answers wrong is E506,
left out of the run (its row shows no rate), and the others mine on; with
nothing left the miner exits with code 3. The verdict is kept in
selftest.json with the binary's SHA-256, the engine's, the driver version
and the cards, and a start on the same binary, engine, driver and cards
skips the test and says so; a new binary, an updated engine, a driver
update, a card added or moved, or a failure on record runs it again. --self-test on a mining run forces it; --self-test
alone (no pool, no wallet) runs it offline, one line per device, exit 0 or
3; --self-test=all runs every algorithm of the engine index.

Then, while mining, every solution a card hands back is re-computed on
the CPU before it is submitted (about 6 microseconds each; one share in
ten past 1 % of a core, which no pool reaches). A solution the CPU refuses
is never sent: it is dropped, logged as E507 with the card and the
overclock hint, counted as "invalid" on the card's row, on /stats
(shares_invalid) and on /api/v1/devices (shares.invalid), and told to the
notifiers as gpu_invalid_share. The count is the miner's own, not the
pool's. --verify-shares off turns the check off: a wrong solution is then
submitted and rejected by the pool. CPU solutions are not re-checked: the
engine that found them is the reference.


BENCHMARK
--------------------------------------------------------------------------------
--benchmark measures for --duration seconds after a warm-up, keeps the
figure in bench-<algo>.json in the state directory and prints the previous
one beside the new ("last time 588.2 MH/s on 2026-09-20"). It measures the
power too: the cards through NVML, the CPU package through its RAPL
counter when CPU threads hash (readable by root only on most Linux
systems); a part that cannot be read leaves the power "not measured",
never guessed. The report ends with the watts and the rate per watt.

-a all --benchmark measures every algorithm of the engine index, and
-a quantus,randomx --benchmark the ones named, one after the other, 60 s
each unless --duration says otherwise; one this machine cannot run is
skipped with the reason. A summary ends it: the rate, the power, the rate
per watt and the change since the last run, per algorithm. The cockpit
runs the same on a rig (the benchmark command): the rig stops mining,
measures, then mines again as it was.

--benchmark --bench-seed N is the deterministic benchmark: the work and
every worker's nonce sequence derive from N, the run ends when every
worker has found --bench-solutions solutions (4 by default) at a
difficulty fixed per algorithm, every solution is re-checked on the CPU,
and a checksum of the solutions is printed (FearMiner's own: the SHA-256
of the sorted solutions, first sixteen hex digits). Two runs on the same
hardware with the same seed, solutions, threads and cards print the same
checksum, and the next run says whether it matched the last; a mismatch
is a card that miscomputes, or another binary or driver (on a card, a
launch holding two solutions reports the first its threads reached, so a
lone mismatch on a healthy card is possible, a repeated one is not). The
run is capped at six times --duration.


ERROR CODES
--------------------------------------------------------------------------------
Every fault on the log carries a stable code, for example
  E302 device lost: GPU1 ...: reported gone by the driver; after 45 min of
  stable mining: likely the overclock, not the miner; lower the clock and
  try again (fearminer explain E302)
Only the code and the message are on the line. fearminer explain E302
prints the cause, the impact and what to do, offline; fearminer explain
alone lists every code. E1xx is the network (pool unreachable, TLS, login
refused, no job, every pool down, the proxy,
DNS over HTTPS, a certificate that changed since first use, a share
unanswered, a redirect refused, a job replayed, a pool too slow), E2xx the
configuration (bad URL, wallet required, a wallet without a pool, a
wrong option value, the
configuration file: missing, an unknown key, a bad value; a chain this
miner cannot run), E3xx the hardware (no device, device
lost, hang, zero or ghost hashrate, thermal pause and shutdown, driver missing or too
old, not enough GPU memory), E4xx the wallet, E5xx the kernels (compute
capability unsupported, degraded kernel, a device that fails its
self-test, an invalid share caught before submit), E6xx the privileges and
performance prerequisites (the helper missing, the MSR tweaks skipped and
why, huge pages short, the MSR values restored and the pages given back
or not), E7xx the
overclocking (a value the card refuses, privileges missing, what was
restored). A device fault says when it struck: at the very first search it
is the miner or the driver, after a long stable run it is likely the
overclock.


NOTIFICATIONS
--------------------------------------------------------------------------------
The miner can tell you what happens to it:

  --notify-telegram BOT_TOKEN:CHAT_ID   a Telegram bot (its token from
                                        @BotFather) in a chat (its id)
  --notify-discord <webhook url>        a Discord channel's webhook
  --notify-url <url>                    your own endpoint: one JSON POST per
                                        alert (the format is in the README
                                        on GitHub); --notify-secret signs it

Run once with --notify-test to check the setup: one test message goes to
each, and the outcome is printed.

What is told, with its severity: rig_up (info), rig_down (critical: a stop,
or the supervisor giving up), gpu_down (error: a card lost), gpu_unstable
(warning: a card whose rejects pile up, or that failed its self-test),
gpu_invalid_share (error: a card's solution refused by the CPU before it
was submitted), gpu_degraded (warning: a card the
watchdog holds Degraded), gpu_quarantined (error: a card left out for
restarting too often), hashrate_low / hashrate_recovered (warning / info:
the rate under 70 % of its best, or a card under --hashrate-min, and back),
hashrate_suspect (warning: a figure over --hashrate-max), temp_high
(warning: a card paused by the cut-off), temp_critical (critical: paused
over 10 min, 10 °C over the limit, or past --temp-shutdown: the miner
stops), shares_rejected_high (warning: over
5 % of 50+ shares), pool_disconnected / pool_failover / pool_recovered
(warning / warning / info), watchdog_restart (error: the supervisor
restarted the mining process),
update_available (info). --notify-min-severity (warning by default) is the
bar under which nothing is sent.

You will not get 200 messages when a pool blips: a condition is only told
once it has held for a while (a pool down for 60 s, a card lost for 30 s,
a thermal pause for 10 s, a low rate for 2 min), told again every four hours
at most while it lasts, and told once more when it is over. What happens
within thirty seconds goes out as one message; a critical event does not
wait. The log shows "alert firing: ..." and "alert resolved: ..." for what
was sent.

--heartbeat-url <url> pings the URL every minute (GET, or a POST with a
small JSON body with --heartbeat-post), <url>/start at startup and
<url>/fail on a critical event, the healthchecks.io convention; an Uptime
Kuma push URL works as is. When the pings stop, the rig is frozen or off:
that is what the receiving service is for.

The bot token, the webhook tokens and the secret never appear in the log.


ENGINES
--------------------------------------------------------------------------------
Each algorithm is an engine of its own, fearminer-engine-<algo>, which the
miner starts, speaks to and restarts when it fails (E320). The engines are
published with a signed index at https://download.fearminer.com/algos/;
the miner holds the key, refuses an index whose signature does not hold
(E321) and an engine whose checksum is not the index's (E323), and keeps
what it fetched in its state directory (engines/, the two latest versions
of each). At start: the index fetched (else the cached one, E322, else the
one in engines/ beside the binary), and the engine of the algorithm from
the cache, a download or engines/ beside the binary. No engine to be had
is E324 (E325 for one this miner cannot run): nothing is mined, the
devices are watched. Every hour a newer engine is fetched, checked and
swapped in between two jobs (E326), and rolled back when it fails its
self-test or mines 5 % slower over ten minutes (E327). --engine
quantus=1.0.6 holds an algorithm to a version (the engine key of
fearminer.toml, FEARMINER_ENGINE). The index lists the algorithms, their
names and coins.


SUPPORTED HARDWARE
--------------------------------------------------------------------------------
NVIDIA, native CUDA kernels tuned per architecture:
  + Blackwell (RTX 50)
  + Hopper
  + Ada Lovelace (RTX 40)
  + Ampere (RTX 30, A100)
  + Turing (RTX 20, GTX 16)
  + Volta
  Driver of the 550 series or newer, 570 or newer for RTX 50. A driver
  older than the 575 series runs the engines' CUDA 12.4 build.
Apple silicon (M1 and later), native Metal kernel, in the macOS archive.
Other GPUs run on Vulkan at a fraction of the rate. CPU-only algorithms need
no GPU at all. Pearl is the exception: NVIDIA sm_86 only for now (see PEARL).


RANDOMX (MONERO)
--------------------------------------------------------------------------------
-a randomx mines Monero on the CPU only; -d is refused. It needs 2 GiB of
RAM for the dataset plus 256 MiB, and 2 MiB per thread; a machine that
cannot hold the dataset mines on the cache alone, many times slower, and
the log says so at start. The dataset is rebuilt on every new seed hash
(about every three days), a few seconds on every core.

Two things make it 20 to 40 % faster, and both need root, which the miner
never has: huge pages (20 to 30 %, up to 50 % on some machines) and the MSR
tweaks XMRig applies (up to 30 % on an Intel, up to 6 % on a Zen). On Linux
both go through fearminer-helper, the small privileged binary beside the
miner, reached through sudo before the first connection and never after:
  sudo install -m 0755 fearminer-helper /usr/local/bin/fearminer-helper
  fearminer-helper install        (prints the sudoers line; writes nothing)
  echo 'USER ALL=(root) NOPASSWD: /usr/local/bin/fearminer-helper' \
    | sudo tee /etc/sudoers.d/fearminer-helper
  sudo chmod 0440 /etc/sudoers.d/fearminer-helper
  sudo modprobe msr && echo msr | sudo tee /etc/modules-load.d/msr.conf
  sudo -n /usr/local/bin/fearminer-helper status     (the check)
The helper exits 0 when done, 1 on a failure it names, 2 on an argument
it refuses (judged before the root check), 3 when not root where root is
needed; msr restore with nothing saved is nothing to do, exit 0 for anyone.
At start the miner then reserves the huge pages it needs (per NUMA node;
the pool grows until that many pages are free, by what is missing and no
more, so a second miner on the machine gets its own; the pages this run
added are given back at every exit and crash, its own and no other run's),
applies the CPU's MSR preset (the original values are kept and written
back at every exit and crash, E614 on the log), and prints one block: JIT,
AES, huge pages x/y, MSR, threads and their placement, and the share of the
ideal configuration the machine reaches. Every miss is a coded line with
the loss and the fix (E601 helper missing, E603 virtual machine, E604
kernel lockdown, E605 msr module, E606 writes off, E607 no preset, E609
huge pages short), never a refusal to start. --msr off writes nothing;
--msr zen4 (zen1..zen5, intel) or --msr addr:value:mask,... forces the
values, on the registers the presets tune only (0x1a4, 0xc0011020,
0xc0011021, 0xc0011022, 0xc001102b). Without the helper, huge pages by hand:
  Linux:    sudo sysctl -w vm.nr_hugepages=1184   (the number the E609 line
            gives; and the same line in /etc/sysctl.d/ to keep it; reserve
            them right after boot)
  Windows:  give your account "Lock pages in memory" (secpol.msc, Local
            Policies, User Rights Assignment), log out and in; E612 says
            when it is missing. No MSR tweaks on Windows (E611, once):
            they need a kernel driver, and this miner installs none
  macOS:    not available; the fallback is the only mode
--1gb-pages reserves 1 GiB pages for the dataset (1 to 3 % more), used
only where the kernel boots with default_hugepagesz=1G.
Threads: one per physical core by default, capped by the L3 cache
(2 MiB per thread), pinned one per core and spread over the NUMA nodes;
-t N overrides (also -t 50% or -t -2 of the default, -t randomx:16 per
algorithm); --cpu-affinity 0-7 or 0xff pins them where you say;
--cpu-priority 0..5 sets their priority. A miner started as root
(--allow-root, HiveOS) does the helper's work itself and calls no helper.


PEARL (PRL)
--------------------------------------------------------------------------------
-a pearl (also pearlhash, prl) mines Pearl on NVIDIA cards only: the
kernel is built for sm_86 (RTX 3090, RTX 3080 Ti) and a card of another
architecture is left out with the reason. Each card holds 4.5 GB of the
job (a card with less free memory is left out, E310); the NVIDIA driver is
all it needs, no CUDA toolkit. There is no CPU engine: -t on pearl is
refused (E202). Linux and Windows only: a Mac has no NVIDIA driver.
The work is a noised int8 matrix product; the rate counts its
multiply-accumulates and is shown in T (10^12 MAC a second, the unit the
pools credit), in the cockpit, the log and the benchmark; the API serves
the rates in MAC/s (hashrate.unit says so) and HiveOS gets TH/s. A share
at pool difficulty D is worth D x 2^32 MAC, which is how the effective
rate is counted, as the pool credits it. Every proof is checked by the
chain's own verifier before it is sent, and again by the miner on its
own copy (see SELF-TEST AND VERIFIED SHARES).
The wallet is a prl1... address (tprl1... and rprl1... are the test
networks' and are refused); with it and a pool, -a is not needed. The
pool is yours to choose, as for every algorithm. Pearl pools do not all
speak the same stratum: the miner speaks the "v2" dialect (one
mining.authorize, jobs with a 256-bit target, the proof gzipped in the
submit); a pool that speaks another one refuses the shares. For example:
  fearminer -o stratum+ssl://pool.example.com:3335 -u prl1... -w rig1
See FEE for the dev fee.


TENSORCASH (TSC)
--------------------------------------------------------------------------------
-a tensorcash (also tsc, poi) mines TensorCash, a proof of inference:
windows of the registered model (Qwen3-8B) run on the card, and a share is
a whole proof of 166-200 KB. NVIDIA only, 20 GB of card memory free
(RTX 3090, 4090, 5090 and the like), driver 575 or newer; no CPU engine,
no --benchmark. The pool is a WebSocket broker, -o wss://HOST/v1/ws, the
login -u WALLET.rig1 (a tc1q... address). At the first start the engine
downloads the backend built for the card and the model's weights (about
9 GB) into the state directory (tensorcash/ under it), checks them, and
takes them from there afterwards; the log says the progress. The rate is
in PoI/s (proofs a second) and the share counts are small and slow (a
pool may credit one every quarter of an hour): the cockpit and the page
show them as they come. Bob Labs (wss://tensorcash.boblabs.eu:443/v1/ws)
is built in: no password, no token to set; another broker takes its
token file in -p token-file=PATH and its session flags in a file named by
TSC_POOL_CONFIG. --tsc-precision bf16 takes the 16 GB bf16 weights
instead of the 9 GB Q8_0 ones. On Windows: start_tensorcash.bat, or
start_tensorcash_gui.bat to also open the miner's page in a window.

FEE
--------------------------------------------------------------------------------
FearMiner charges a dev fee. fearminer --list-algorithms and
https://fearminer.com show it.


API
--------------------------------------------------------------------------------
Beside /stats, on the same port (4300 by default), an API for a dashboard
or a script: reads, and three writes -- a set on a card (POST
/api/v1/oc), a command on the running miner (POST /api/v1/commands) and a
reload of the configuration (PUT /api/v1/config):

  GET /api/v1/summary   the whole picture: api_version, version, build,
                        uptime_s, algo, mode, session_connected, pool {url,
                        index, is_primary, switches}, hashrate {local_hs,
                        local_10m_hs, session_hs, effective_hs,
                        effective_pct, effective_estimate_hs,
                        effective_estimate_margin_pct}, shares {accepted,
                        rejected, stale, invalid, best_difficulty,
                        difficulty, luck_pct}, fee,
                        efficiency_kh_per_w,
                        restarts, alerts_firing, wallet_changed,
                        time_to_first_share_s, tuning (true while a device
                        autotunes) and tuning_devices (label, kind, index,
                        tuning: every device tuning, a first start's tune
                        before the devices have rows included)
  GET /api/v1/devices   one entry per row of the table: index, kind, label,
                        name, pci_bus_id, state, hashrate_hs, temp_c, fan_pct,
                        power_w, power_limit_w, clock_mhz, throttle,
                        shares {accepted, rejected, stale, invalid},
                        efficiency_kh_per_w, crashes, and the sensors a
                        card may have (null when not): temp_mem_c,
                        temp_hotspot_c, energy_mj, throttle_reasons (labels:
                        power_cap, hw_thermal, ...), ecc_corrected,
                        ecc_uncorrected, pcie_replays, pcie_gen, pcie_width,
                        pcie_max_gen, pcie_max_width, mem_used_mb and
                        mem_total_mb (the card's memory in MiB, through
                        NVML; null on a CPU row and on AMD or Intel cards),
                        tuning (the device's autotune while it runs:
                        phase, done, total, percent, elapsed_s, eta_s, best,
                        best_rate; null when it does not tune)
  GET /api/v1/pools     the pool list, with the rank, the active one and,
                        per pool, its own record since the start: shares
                        {accepted, rejected, stale, unanswered,
                        best_difficulty}, rejected_by_reason
                        {low_difficulty, stale, duplicate, unknown_job,
                        unauthorized, other}, uptime_s, reconnects,
                        avg_reply_ms, latency_ms, jobs_duplicate,
                        jobs_replayed, nonce_space_exhausted
  GET /api/v1/history   what this rig did, from its own history:
                        ?from=&to=&step=&metric=&device=. Answers
                        from_ms, to_ms, step_s, layer (ten_second, minute,
                        five_minute or hour: the step picks it), device,
                        clock {drift_ms, gaps, samples}, t_ms[] and
                        series[{metric, unit, aggregate, values[]}], with
                        null for a bucket nothing was sampled in. 400 for
                        a bound, a step, a metric or a device that is not
                        one (E202); 409 with --history off (E223). See
                        HISTORY above
  GET /api/v1/config    the configuration in force, the password as ***,
                        with reloadable[] and restart_required[], the two
                        published lists of what changes without a restart
                        and what does not (every object under /api/v1
                        carries api_version)
  PUT /api/v1/config    the hot reload: an empty body reads the
                        configuration again from the file, the environment
                        and the command line; {"set": {"temp_limit": "85"}}
                        reloads with those keys over every source, and they
                        keep winning at every later reload until written
                        again or written as null, which hands the key back
                        to the file (a flag written false is really off,
                        whatever the file says; taking a key back needs no
                        level). Every reload names the keys it holds, on
                        the log and in held[]. Validated
                        whole first: a configuration that does not validate
                        is refused whole (422, E220) and the one in force is
                        kept. Answers {source, changed[],
                        restart_required[], held[]}
  POST /api/v1/commands one command: {"command": "pause", "devices": [0]};
                        devices optional, omitted for the whole rig. pause,
                        resume, toggle and retune are taken by default;
                        restart and stop need --unrestricted-api operate and
                        are refused (403, E217) otherwise. Answers {command,
                        outcome, paused, paused_devices}
  GET /api/v1/oc        the overclocking per card: enabled, wanted, readback
                        (what the card reads as), applied, pending, refused
                        (with the code), restore (what is put back at exit)
  POST /api/v1/oc       {"device": 0, "core_offset_mhz": 100, "mem_offset_mhz":
                        800, "power_limit": "80%", "fan": "70%"}, every value
                        but device optional: applied now, read back, answered
                        with the card as it reads; needs the token from
                        anywhere, this machine included (401 without it);
                        409 on a run without an OC option or with --no-oc
  GET /healthz          "ok" while the miner answers; no token, no data
  GET /readyz           200 once a session is connected and a device mines,
                        503 with the reason before; no token
  GET /mmpos            the rig in the shape mmpOS's agent reads, no
                        token:
                        busid (cpu first, whatever its sockets, then each
                        card by its PCI bus), hash per row in units "hs"
                        (H/s, MAC/s on Pearl), air (accepted, invalid,
                        rejected), shares {accepted, rejected, invalid}
                        per row, miner_name, miner_version
  GET /openapi.json     the description of all of it, /stats, /hive-stats
                        and /mmpos included (openapi.json in this folder
                        is the same document)

The units are in the names (_hs hashes per second, _c degrees Celsius,
_w watts, _s seconds, _pct percent); a figure that cannot be computed yet
is null. The API answers from the moment the miner starts, before it has
connected anywhere, and keeps answering through reconnections.

From this machine no token is needed to read. From another machine (the
miner started with --api-bind 0.0.0.0:4300) every /api/v1 request, and
every write from anywhere, must carry the header
"Authorization: Bearer <token>": the token is made at the first
start, kept in api_token in the state directory (readable by you alone),
never written to the log (the start line only says where it is), and
printed by
  fearminer token show
A new one:
  fearminer token rotate
(the running miner keeps the old one until it restarts). Never put the
token in a URL. A wrong token is refused (401), more than 20 requests a
second from one machine too (429), a method a path does not take too
(405, with Allow). /healthz, /readyz, /stats, /hive-stats and /mmpos
never ask for it.

  curl -s http://127.0.0.1:4300/api/v1/summary
  curl -s -H "Authorization: Bearer <token>" http://<rig>:4300/api/v1/devices


COMMANDS AND HOT RELOAD
--------------------------------------------------------------------------------
A running miner takes a small set of commands and reads its configuration
again without restarting. Nothing here talks to anything outside the
machine.

pause, resume, toggle and retune are the only writes a miner takes by
default:
each is reversible, and none can move money, so a script that owns the
rig's schedule (a solar window, a cheap-power window) needs no more.
restart and stop end the mining, so they need --unrestricted-api operate;
the wallet, the pools and the overclocking need --unrestricted-api
sensitive. A command over the level is refused with E217, token or not,
and the refusal says how to enable it.

The level guards the API and it alone. The cockpit keys need the terminal
the miner draws on, a signal needs the right to signal the process, and a
sentinel file needs write access to the miner's own state directory:
whoever has any of those can already kill the process, so <state dir>/stop
stops a miner started with no unrestricted mode at all.

  pause     hold the rig, or the cards named: each worker finishes the
            search it is in, then idles. Nothing is dropped, nothing is
            interrupted mid-batch; the rows read Paused (operator)
  resume    mine again (a rig-wide resume also releases the cards held
            one by one)
  toggle    pause if mining, resume if paused
  retune    restart the search of the rig, or of the cards named, on the
            newest job. The measured launch geometry is cached inside the
            engine for the life of the process: a full re-measure is a
            restart with --retune
  restart   end the mining process; the supervisor starts it again
  stop      stop the miner for good

Four ways to send one, all the same underneath:

  - POST /api/v1/commands with the token;
  - the cockpit: p holds the whole rig and lets it go again, 1 to 9 one
    card each (1 is GPU0);
  - kill -USR1 <pid>: each one toggles the rig's pause. Send it to the
    pid you know, the one the service manager reports; it is passed on to
    the mining process;
  - sentinel files, for a script with no token: create <state dir>/pause,
    <state dir>/resume or <state dir>/stop and the miner acts on it
    within a second and deletes it. Writing the file again is the command
    again.

Every command is logged with where it came from and what it came to.

The hot reload: kill -HUP <pid>, the file watched under --watch-config
(off by default), and PUT /api/v1/config all read the configuration again
from the file, the environment and the command line, validate the whole
of it, then apply it and print what changed, the wallet first. A
configuration that does not validate is refused whole (E220) and the one
in force is kept, entirely: the mining is never interrupted by a reload
that was going to fail. A key that changed and needs a restart is named
with E219 and the rest is applied -- on the paths that read the machine's
own configuration (SIGHUP, --watch-config, PUT /api/v1/config with no
body). The set of PUT /api/v1/config is stricter, because it names the
keys it writes: a set naming such a key is refused with E219 and a 422,
and nothing of that request is applied.

What reloads: the pool list and every per-pool value (url, user, worker,
pass, pass_file, tls, tls_fingerprint, tls_spki, ignore_wallet_check),
the failover timings (pool_retries, job_timeout, submit_timeout,
max_latency), every --temp-* threshold, every watchdog threshold, the
notification targets and the severity floor, the heartbeat, the log level
(verbose, log_level_file: the console and the file keep two levels, as at
a start), and the overclocking sets (cclock, lock_cclock, mclock,
lock_mclock, pl, fan, oc_delay, no_oc): each card's new set is applied at
once, with no delay. A card the new sets say nothing about is left as it
is, registers and all; --no-oc and a restart are still the way to undo an
overclock.

What needs a restart: the algorithm, the device selection, the thread
count, the API bind, the engine and CPU knobs, the network options, the
log file, --oc-script, --oc-reset-on-start, the supervisor's settings and
the command options themselves. fearminer --help prints both lists, and GET /api/v1/config
serves them.

The pool and login keys and the overclocking sets are the sensitive
level: the "set" of PUT /api/v1/config refuses them (E217) unless the
miner was started with --unrestricted-api sensitive, token or not.
kill -HUP, --watch-config and a PUT with no body reload them without it:
those read your own configuration file rather than take a value from
outside.

A reload that changes the pool list does not disturb the session on the
air: it ends cleanly at its next half-second round and the next one opens
on the new primary, in the same process.

  fearminer -o ... -u WALLET --watch-config --log-file fearminer.log
  kill -HUP $(pgrep -o fearminer)
  curl -s -X PUT -H "Authorization: Bearer <token>" \
       -H 'Content-Type: application/json' \
       -d '{"set": {"temp_limit": "85"}}' \
       http://127.0.0.1:4300/api/v1/config


HOOKS
--------------------------------------------------------------------------------
--hook <EVENT>:<PATH>, repeatable, runs a program of yours when something
happens to the rig. It is run directly, never through a shell, so nothing
in the event can be read as a command; it is given 30 s and killed past
that; its exit code goes on the log (E139 when it is not 0). A hook is
told what happened, it is not asked for permission: whatever it answers,
the mining carries on.

--check-config checks the shape of the value and nothing else: the path
is checked when the event fires, not at the check, so --hook
temp-high:/nonexistent passes and is E139 the first time the rig gets
hot. E221 (bad hook) is the value itself: <EVENT>:<PATH>, with an event
that is one.

The events: start, exit, crash, pause, resume, pool-switch,
share-rejected-high, low-hashrate, temp-high, device-lost.

The context is in the program's environment, never on its command line:
FEARMINER_EVENT always, then the fields the event has -- FEARMINER_DEVICE,
FEARMINER_PCI_BUS, FEARMINER_ALGO, FEARMINER_POOL, FEARMINER_SUMMARY. A
field the event does not carry is absent, not empty. The device and
algorithm variables are spelt as --oc-script already spells them, so one
script serves both; that script is also given FEARMINER_UUID, which an
event does not carry.

  fearminer -o ... -u WALLET --hook temp-high:/opt/rig/hot.sh


BACKGROUND AND PRIORITY
--------------------------------------------------------------------------------
--background runs the miner without a console: it starts itself again in
a session of its own with its streams on /dev/null, prints the new pid
and returns. The shell that asked is free, and closing the terminal takes
neither process. Give --log-file with it, or the log goes nowhere and the
API is the only way to read the rig. A Unix option; on Windows run the
miner as a service.

--priority 0..5 sets the whole process's priority, on the same scale as
--cpu-priority, which moves the worker threads alone. Above 2 needs a
privilege on Linux; refused by the OS it is E613 and the miner keeps the
normal priority.

  fearminer -o ... -u WALLET --background --log-file fearminer.log
  fearminer -o ... -u WALLET --priority 1


VERIFY A DOWNLOAD
--------------------------------------------------------------------------------
The release page carries SHA256SUMS over every file and SHA256SUMS.minisig,
its signature by FearMiner's release key. With both beside the archive:

  fearminer verify SHA256SUMS

checks the signature offline with the key built into the binary, then the
SHA-256 of every file the sums name that is in the same folder, and prints
one line per file: ok, MISSING or MISMATCH. It exits 0 only when the
signature is good and every present file matches; anything else says
"verification FAILED; do not run this download". Given the archive
instead, it looks for SHA256SUMS beside it. sha256sum -c SHA256SUMS
--ignore-missing and minisign -Vm SHA256SUMS -P <key> do the same by hand
(the key is in the README on the release page). The release also carries
sbom.cdx.json, the list of every component inside the binary (CycloneDX),
covered by the same sums.


WHAT THE MINER TALKS TO
--------------------------------------------------------------------------------
The 'egress' line at start lists it, and this is all of it:
  - your pool, over stratum+tcp or stratum+ssl (every pool of the list,
    when there are backups);
  - telemetry.fearminer.com, the anonymous telemetry, every 15 minutes (see
    TELEMETRY below). --no-telemetry (or FEARMINER_NO_TELEMETRY=1) turns it
    off, and the line then says 'no telemetry (--no-telemetry)' instead of
    the host;
  - download.fearminer.com, the signed engines index, every hour, and an
    engine when a new one is published (see ENGINES);
  - and only if you ask for them, the notification and heartbeat endpoints
    of the NOTIFICATIONS section (api.telegram.org, discord.com, your own).


TELEMETRY
--------------------------------------------------------------------------------
FearMiner sends an anonymous report to telemetry.fearminer.com: how many rigs
run, on what and with what, never who. The page
https://fearminer.com/telemetry/ says field by field what is sent, why, and
what is done with it. A start once the run is under way (at the first
accepted share, a minute at most), a beat every 15 minutes
(--telemetry-interval, 5 to 1440 minutes) and a stop at a clean stop, which
holds the exit two seconds at most; one HTTPS POST each, over the pools' own
proxy and resolver, never retried, never queued, and a failure is a debug
line only: mining never waits for it.

What goes out, by group (schema 1, the fields in brackets):
  event     what the report is (kind: start, beat or stop; first: the first
            start of this install; previous_version: the last run's version
            on a start, when it was another)
  install   the install id (install): 32 random hex digits, drawn at the
            first start, kept in telemetry-id in the state directory,
            derived from nothing
  format    the payload's shape (schema) and the minutes between two
            beats (interval)
  version   the release (version) and the short commit (build)
  system    linux, windows or macos (os), its short name and major version
            (os_release: debian-13, windows-11), hiveos or mmpos (mining_os)
  mining    the algorithm (algo), the engine's version and build (engine,
            engine_build), the NVIDIA driver's and CUDA's major versions
            (driver)
  hardware  the GPU models and how many of each (gpus), the CPU's vendor,
            marketing name and physical cores (cpu)
  hashrate  a bucket of the 1-2-5 series and the unit (rate: 1G-2G H/s),
            never the figure
  features  the features in use as named flags (features), never a value
  uptime    under an hour, a day, a week, or more (uptime)
  errors    the error codes seen since the last report, counted (errors)
  pool      the first pool's host name alone (pool_host), none for an
            address or a local name

Never sent, in any version and under any option:
  - wallet
  - worker name
  - pool login or password
  - machine name
  - MAC address
  - card or disk serial number
  - GPU UUIDs or PCI bus ids
  - file paths
  - configuration contents or values
  - IP address (the ingestion reads the country from Cloudflare and never
    the address)
  - anything of the cockpit or relay (rig fingerprint, keys, codes)

fearminer telemetry show prints the JSON the next beat of a run with the
options given after it sends, the real install id included, and sends
nothing. fearminer telemetry rotate-id draws a new install id.

The hashrate, the GPU models and the country together can point at one large
farm; that is why the hashrate goes as a bucket and the install id carries
nothing else. A farm that wants nothing sent runs with --no-telemetry
(FEARMINER_NO_TELEMETRY=1, or no_telemetry = true under [output] in the
file): no install id is kept, nothing is sent, and the miner loses nothing.


WINDOWS
--------------------------------------------------------------------------------
The binary is unsigned: SmartScreen may say "unknown publisher", choose
"More info" then "Run anyway". Some antivirus engines flag every GPU miner;
whitelist fearminer.exe if needed.


MACOS
--------------------------------------------------------------------------------
Apple silicon only. The binary is not notarized: if it was downloaded with a
browser, Gatekeeper says it "cannot verify the developer" until the
quarantine flag is cleared; the launcher does it (xattr -d
com.apple.quarantine fearminer). Run it from Terminal: ./start_quantus.sh
or ./start_randomx.sh (Pearl and TensorCash need an NVIDIA card: not on a
Mac)


HIVEOS
--------------------------------------------------------------------------------
Custom miner package: fearminer_custom-1.15.2.tar.gz on the release page.
Flight sheet: miner "custom", installation URL
https://github.com/fearminer/fearminer/releases/download/v1.15.2/fearminer_custom-1.15.2.tar.gz
the algorithm's HiveOS name (qpow for Quantus, randomx for Monero,
pearlhash for Pearl), wallet template %WAL%.%WORKER_NAME%.


MMPOS
--------------------------------------------------------------------------------
Beta: built to mmpOS's published custom-miner guide and checked against it,
not yet run on a real mmpOS rig; say what does not work on the Telegram
channel or in an issue.

Custom miner package: fearminer_mmpos-1.15.2.tar.gz on the release page.
In the mmpOS dashboard:

1. Wallets: the address of the coin you mine.
2. Pools: your pool for that coin, SSL ticked for an SSL port, the username
   mmpOS proposes (%wallet_address%.%rig_name%%miner_id%) and the password
   x.
3. Miner profiles, Add profile, Basics: the coin (PRL for Pearl, QTC for
   Quantus, XMR for Monero), the platform "Linux / mmpOS",
   the miner "Custom miner", as Custom miner download url
   https://github.com/fearminer/fearminer/releases/download/v1.15.2/fearminer_mmpos-1.15.2.tar.gz
   and the pool of step 2.
4. Advanced: the Api port 4444 (or any free port), and as Arguments the
   line mmpOS fills in for a custom miner, with %pool_protocol% in it for
   an SSL pool (or --tls after it), then any fearminer option: --enroll
   fm1_... to join your cockpit, -d 0,2 for some cards, -t 0 for no CPU
   thread on Quantus:
   ./mmp-launch.sh --coin %coin% %pool_protocol% --pool %pool_server%:%pool_port% --user %user% --password %password% --api-port %api_port%
5. Save the profile and select it on the rig.

mmpOS fetches a URL once and keeps what it got: to update, put the next
release's URL in the profile. The miner logs into mmpOS's own log (the
miner command, the dashboard); its stats reach mmpOS through GET /mmpos
(see API). A cockpit shows the rig as managed by mmpOS: the profile
decides what it mines.


SUPPORT
--------------------------------------------------------------------------------
Releases:  https://github.com/fearminer/fearminer/releases
Issues:    https://github.com/fearminer/fearminer/issues
Web:       https://fearminer.com
