Skip to content

feat: add peeroxide-cli#12

Merged
eshork merged 13 commits intomainfrom
feat/peeroxide-cli
May 1, 2026
Merged

feat: add peeroxide-cli#12
eshork merged 13 commits intomainfrom
feat/peeroxide-cli

Conversation

@eshork
Copy link
Copy Markdown
Collaborator

@eshork eshork commented Apr 30, 2026

Summary

Adds `peeroxide-cli` — a command-line toolkit for interacting with the peeroxide P2P networking stack, wire-compatible with the Node.js Hyperswarm network.

New Crate: `peeroxide-cli`

The binary is named `peeroxide` and provides six subcommands:

  • `lookup` — query the DHT for peers announcing a topic; `--json` NDJSON output, `--with-data` for mutable record retrieval
  • `announce` — announce presence on a topic; `--seed` for deterministic identity, `--data` attachment, echo protocol responder for connectivity testing
  • `ping` — reachability diagnostics; bootstrap NAT check, direct UDP probe, pubkey/topic-based peer ping, `--connect` full handshake with echo probes
  • `cp send` / `cp recv` — streaming encrypted file transfer over P2P swarm connections; atomic writes, progress reporting, stdin/stdout support
  • `deaddrop leave` / `deaddrop pickup` — anonymous store-and-forward messaging via DHT mutable records; passphrase encryption, CRC32c integrity, chunked payloads, AIMD adaptive concurrency
  • `node` — long-lived DHT bootstrap node
  • `config init` — generate default TOML configuration

Additional features: TOML config system, `--generate-man` roff man page generation, SIGINT/SIGTERM graceful shutdown, 24 unit tests, 9 local integration tests, 4 live network tests.

Public API Changes — library crates bumped to v1.2.0

All changes are additive (semver-compatible). No existing signatures were removed or altered.

`libudx`

Symbol Change
`UdxSocket` Now implements `Clone` (cheap Arc-based handle; all clones share the same underlying socket)
`UdxSocket::close(self)` Signature unchanged. Behavior note: close is a no-op unless this is the last clone

`peeroxide-dht` — `DhtHandle`

Symbol Change
`DhtHandle::table_id()` Added — returns the node's current routing table ID
`DhtHandle::server_socket()` Added — returns the primary UDX socket for stream multiplexing
`DhtHandle::listen_socket()` Added — returns the socket bound to the advertised server port

`peeroxide-dht` — `HyperDhtHandle`

Symbol Change
`HyperDhtHandle::server_socket()` Added — delegates to `DhtHandle::server_socket()`
`HyperDhtHandle::listen_socket()` Added — delegates to `DhtHandle::listen_socket()`
`HyperDhtHandle::persistent_stats()` Added — returns `PersistentStats` from the request handler

`peeroxide-dht` — `PeerConnection`

Symbol Change
`PeerConnection::socket` Type unchanged (`UdxSocket`). `UdxSocket` now implements `Clone` so field is cheap to copy
`PeerConnection::new()` Signature unchanged
`PeerConnection::with_remote_addr()` Signature unchanged

`peeroxide-dht` — free functions

Symbol Change
`establish_stream(result, runtime)` Signature restored to original two-param form
`establish_stream_with_socket(result, runtime, socket)` Added — variant for callers that need socket reuse
`should_direct_connect(relayed, firewall, holepunchable, same_host)` Added — connection-path decision logic extracted as public fn

`peeroxide-dht` — `PingResponse`

Symbol Change
`PingResponse::to` Added — reflexive address as seen by remote
`PingResponse::closer_nodes` Added — closer nodes returned by remote

`peeroxide-dht` — `MutablePutResult`

Symbol Change
`MutablePutResult::commit_timeouts` Added — count of timed-out commit-phase requests

`peeroxide-dht` — `Io`

Symbol Change
`Io::server_socket()` Added — returns the server-side UDX socket
`Io::primary_socket()` Added — returns the primary socket (client if firewalled, server otherwise)

`peeroxide-dht` — new types

Symbol Change
`PersistentStats` Added — storage statistics struct (`records`, `record_topics`, `mutables`, `immutables`, `router_entries`)

`peeroxide` — `SwarmHandle`

Symbol Change
`SwarmHandle::dht()` Added — access the underlying `HyperDhtHandle`
`SwarmHandle::key_pair()` Added — access the swarm's Ed25519 identity key pair

`peeroxide` — re-exports

Symbol Change
`peeroxide::HyperDhtHandle` Added re-export
`peeroxide::MutablePutResult` Added re-export
`peeroxide::MutableGetResult` Added re-export
`peeroxide::ImmutablePutResult` Added re-export

Documentation

Full mdBook documentation site under `docs/` (26 pages across 5 tool chapters + concepts + appendices), GitHub Actions workflow for automated GitHub Pages deployment.

eshork added 8 commits April 29, 2026 23:39
- mdBook scaffold with 26 pages across 5 tool chapters (lookup, announce,
  ping, cp, deaddrop) plus concepts and appendices
- Echo protocol defined once in announce/echo-protocol.md; ping cross-refs
- GitHub Actions workflow for automated GitHub Pages deployment
- DOCS_PLAN.md progress tracker (all phases complete)
- ISSUES.md with source-level findings from documentation review
- AGENTS.md files at docs/, peeroxide-cli/, and workspace root
- .gitignore updated to exclude docs/book/ build output
- Introduce UdxSocketInner to hold all socket state; UdxSocket becomes a
  thin Arc<UdxSocketInner> handle that is Clone + cheap to copy.
- Drop impl moves to UdxSocketInner so the recv loop is only aborted when
  the last clone is dropped, not on every clone drop.
- Restore UdxSocket::close(self) consuming signature.
- Revert PeerConnection.socket back to UdxSocket (was Arc<UdxSocket>).
- Revert server_socket()/listen_socket() return types to UdxSocket.
- Update establish_stream() shared_socket param to Option<UdxSocket>.
- Remove all Arc::new(socket) / Arc::clone(&socket) call sites in io.rs.
- All 53 unit tests + integration tests pass (cargo test --workspace).
@eshork

This comment was marked as resolved.

…task files

- Remove docs-task-specific directives (DEADDROP_V2, echo protocol, DOCS_PLAN,
  RALPH_PROMPT, PR-TODOS, ISSUES.md, API_CHANGES.md) from AGENTS.md
- Add Task Artifacts section: standing policy that task-specific files must not
  be committed without explicit direction; pre-PR scan requirement added
- Delete ISSUES.md (contents moved to PR #12 comment) and API_CHANGES.md
  (breaking changes it documented are fully resolved by UdxSocket refactor)
- Add .gitignore patterns for common task-artifact filenames (*_PLAN.md,
  *_PROMPT.md, *_TODOS.md, RALPH_PROMPT.md, REFACTOR_PLAN.md, etc.)
@eshork
Copy link
Copy Markdown
Collaborator Author

eshork commented Apr 30, 2026

Source-level issues found during docs review

These were logged in ISSUES.md during the documentation pass. Moving here before deleting the file so they're not lost.

Bug: announce.rs — seq reuse when two refreshes occur within the same second

The announce command uses Unix epoch seconds for the seq field in metadata puts. If two refreshes (or the initial put and a refresh) occur within the same second, they will produce identical seq values. The DHT may reject a put with a seq that is less than or equal to the existing sequence number.

File: peeroxide-cli/src/cmd/announce.rs — around the refresh loop.

Inconsistency: announce/unannounce output

The ANNOUNCE output always displays the hashed topic (e.g. ANNOUNCE blake2b("topic")), even if the user provided a raw 64-character hex key. However, UNANNOUNCE correctly displays the raw hex if it was provided as input. This makes it harder to correlate start and end log lines when using raw keys.

File: peeroxide-cli/src/cmd/announce.rs

Neither of these are actually concerning.

eshork added 3 commits April 30, 2026 17:51
- Move test module to end of ping.rs (fixes clippy::items_after_test_module)
- Extract type alias MatrixRow in cmd/mod.rs (fixes clippy::type_complexity)
- Restore two-param establish_stream(); add establish_stream_with_socket() for
  callers that need socket reuse — removes the last remaining API breaking change
- Remove task artifact files: DOCS_PLAN.md, RALPH_PROMPT.md, REFACTOR_PLAN.md,
  peeroxide-cli/PLANNING.md
- Add PR checklist to AGENTS.md (high-level: tests, artifacts, API policy, CI)
CONTRIBUTING.md rewritten: adds peeroxide-cli to crate table, fixes Node.js
version (18→20), removes reference to non-existent TESTING.md, replaces the
generic numbered PR process with a proper pre-open/pre-merge checklist, adds
release-plz release process note, adds API stability section.

AGENTS.md: inline checklist replaced with a short summary + pointer to
CONTRIBUTING.md, with a directive to check it before any PR-related action.
@eshork eshork force-pushed the feat/peeroxide-cli branch from 880e525 to 7c56e37 Compare May 1, 2026 01:15
@eshork eshork merged commit fc12a07 into main May 1, 2026
4 checks passed
@eshork eshork deleted the feat/peeroxide-cli branch May 1, 2026 02:09
@github-actions github-actions Bot mentioned this pull request May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant