# lanspread-peer-cli Scriptable peer harness for automated LAN-spread tests. The binary starts the core peer runtime without the Tauri GUI, reads one JSON command per stdin line, and writes JSONL events, results, and errors to stdout. ## Running ```bash just peer-cli-build just peer-cli-image just peer-cli-tests just peer-cli-run alpha ``` Useful flags: - `--games-dir PATH` stores local archives and installs. - `--state-dir PATH` stores the generated peer identity. - `--identity-file PATH` loads one existing peer identity strictly. Missing or invalid files fail startup without repair, quarantine, or fallback. - `--catalog-db PATH` and `--manifests-dir PATH` select one coherent catalog authority profile. - `--fixture GAME_ID` seeds a tiny archive that the fixture unpacker can install. The selected profile must already authorize that exact fixture. ## Fixture Game Directories `fixtures/fixture-alpha`, `fixtures/fixture-bravo`, and `fixtures/fixture-charlie` are ready-to-use game directories for local CLI smoke tests. Point `--games-dir` at one of them to start a peer with several catalog-backed fake games. Each game includes `version.ini` and a real RAR archive renamed to `.eti`; `fixture-alpha` and `fixture-bravo` share `ggoo`, while `fixture-bravo` and `fixture-charlie` share `cnc4`. The checked-in `catalogs/default` profile authorizes the normal alpha, bravo, charlie, and persona packages. `catalogs/solid` and `catalogs/multi` are separate authorities because their `cnctw` packages intentionally contain different bytes and extracted layouts. `catalogs/unknown` is a source-only `cod2` profile used to prove that another peer's honest catalog cannot extend the client's local catalog. Regenerate and verify the profiles with: ```bash just fixture-catalogs just fixture-catalogs-check ``` Both commands use the Rust catalog publisher. Dynamic sparse and many-file acceptance packages use the same test-only generator through `just fixture-download-only-catalog` or `just fixture-catalog`; the Python scenario runner never derives hashes or catalog rows itself. Production artifacts are a separate corpus and are checked by `just catalog-check-production`. ## Commands Every command is a JSON object with `cmd` or `command`; `id` is optional and is echoed back on the result or error line. ```json {"id":"s1","cmd":"status"} {"id":"p1","cmd":"wait-peers","count":1,"timeout_ms":5000} {"id":"c1","cmd":"connect","peer_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","addr":"127.0.0.1:34567"} {"id":"g1","cmd":"list-games"} {"id":"d1","cmd":"download","game_id":"fixture-one","install":true} {"id":"i1","cmd":"install","game_id":"fixture-one"} {"id":"u1","cmd":"uninstall","game_id":"fixture-one"} {"id":"q1","cmd":"shutdown"} ``` `connect` requires the target's `peer_id` and `addr` from the same `local-peer-ready` event. Address-only connects are rejected because the peer ID is the TLS identity pin, not descriptive metadata. The `status` result includes receiver-side `active_operations` and sender-side `active_outbound_transfers` counts by game ID, which the scenario runner uses to verify transfer lifecycle cleanup.