How to Contribute to the iroh Project: A Complete Developer Guide

To contribute to the iroh project, engage in GitHub Discussions to validate your approach, file a detailed issue, fork the repository, implement changes in the appropriate crate (such as iroh or iroh-relay), and submit a draft pull request for iterative review.

The iroh project is a Rust-based peer-to-peer networking stack built on QUIC that provides hole-punching, relay services, and DNS-based discovery. Maintained by n0-computer, this open-source repository follows a structured workflow to ensure high-quality contributions. Understanding the workspace architecture and the standardized process defined in CONTRIBUTING.md is essential for successfully submitting code that gets merged.

Understanding the iroh Repository Structure

The iroh repository is organized as a Cargo workspace containing multiple specialized crates. Knowing which crate owns specific functionality helps you place new code correctly and avoid circular dependencies.

Core Crates and Their Responsibilities

  • iroh – The core library providing hole-punching, connection establishment, and the public API surface. Entry point is at iroh/src/lib.rs.
  • iroh-relay – Implements relay client and server logic for public relay nodes. Key implementation files include iroh-relay/src/server.rs.
  • iroh-base – Contains shared types such as EndpointId and RelayUrl used across the workspace. See iroh-base/src/lib.rs.
  • iroh-dns / iroh-dns-server – Handles DNS-based address lookup (Pkarr) for endpoint IDs. Logic resides in iroh-dns/src/lib.rs.

The top-level Cargo.toml defines workspace members, build profiles, and global settings, making it the map for understanding inter-crate dependencies.

The iroh Contribution Workflow

Contributing to iroh follows a linear, collaborative process designed to catch issues early and maintain code quality.

  1. Discuss – Start on the project's Discussions page to clarify requirements or validate your approach before writing code.

  2. File an Issue – Search existing issues to avoid duplicates. If none exist, create a new issue using the "New issue" button, including a clear description and labels like feature or bug.

  3. Fork & Clone – Fork the repository, then clone your fork locally:

    git clone https://github.com/<your-username>/iroh.git
    cd iroh
  4. Create a Branch – Use descriptive names that indicate the change scope:

    git checkout -b feat/socket-metrics
  5. Implement – Modify code in the appropriate crate (e.g., iroh/src/socket/metrics.rs). Follow Rust documentation conventions, add unit tests alongside implementations, and include integration tests under iroh/tests/ when applicable.

  6. Open a Draft Pull Request – Push your branch and open a PR marked as draft to signal work-in-progress. The PR template requires a description, breaking change notes, and a checklist covering self-review, documentation, and tests.

  7. Review Cycle – Respond to reviewer feedback, iterate on the code, and mark the PR as "Ready for review" when stable.

  8. Merge – Once approved by maintainers, the PR will be merged into the main branch.

Practical Example: Adding Socket Metrics

To demonstrate how to contribute to the iroh project, consider adding a simple statistic to track active QUIC streams per socket.

Implementing the Metrics Struct

Create or modify iroh/src/socket/metrics.rs to define the tracking structure:

/// Tracks basic socket statistics.
#[derive(Default, Debug, Clone)]
pub struct SocketMetrics {
    /// Current number of open QUIC streams.
    pub open_streams: usize,
}

impl SocketMetrics {
    /// Increment the open-stream counter.
    pub fn inc_streams(&mut self) {
        self.open_streams += 1;
    }

    /// Decrement the open-stream counter.
    pub fn dec_streams(&mut self) {
        self.open_streams = self.open_streams.saturating_sub(1);
    }
}

Exposing the Metrics

Add a public accessor in iroh/src/socket.rs to allow callers to retrieve metrics:

impl Socket {
    /// Return a copy of the current metrics.
    pub fn metrics(&self) -> SocketMetrics {
        self.metrics.clone()
    }
}

Writing the Test

Create iroh/tests/socket_metrics.rs to verify functionality:

#[tokio::test]
async fn test_socket_metrics() {
    let endpoint = iroh::Endpoint::bind().await.unwrap();
    let socket = endpoint.socket(); // hypothetical accessor
    let mut metrics = socket.metrics();

    // Simulate opening two streams.
    metrics.inc_streams();
    metrics.inc_streams();
    assert_eq!(metrics.open_streams, 2);

    // Simulate closing one stream.
    metrics.dec_streams();
    assert_eq!(metrics.open_streams, 1);
}

Run cargo test to execute the suite and verify your changes compile and pass.

Key Files Every Contributor Should Know

  • CONTRIBUTING.md – The authoritative source for contribution guidelines, PR style requirements, and the review checklist.
  • Cargo.toml (workspace root) – Defines all workspace members, build profiles, and dependency versions.
  • iroh/src/lib.rs – The public API surface for the core library; understanding this helps you maintain backward compatibility.
  • iroh-relay/src/server.rs – Core relay server implementation; common target for performance or security improvements.
  • iroh-base/src/lib.rs – Contains shared primitives like EndpointId and RelayUrl that propagate across crates.

Summary

  • Start with communication – Use GitHub Discussions and Issues to align your work with project goals before coding.
  • Respect the architecture – Place code in the correct crate (iroh, iroh-relay, iroh-base, etc.) to maintain modularity.
  • Write tests – Include unit tests with your implementation and integration tests under iroh/tests/.
  • Use draft PRs – Open early drafts to gather feedback during development rather than after completion.
  • Follow the checklist – Adhere to the requirements in CONTRIBUTING.md to expedite the review process.

Frequently Asked Questions

What programming language is the iroh project written in?

The iroh project is written in Rust and organized as a Cargo workspace. All contributions must follow Rust documentation conventions and idiomatic patterns as enforced by the project's CI and linting configuration.

Do I need to open an issue before submitting a pull request?

Yes, you should search existing issues first and create a new one if your change isn't already tracked. For minor fixes or clarifications, starting with a GitHub Discussion is also acceptable. This prevents duplicate work and ensures your approach aligns with maintainer expectations.

How do I know which crate to modify when contributing?

Consult the repository structure: use iroh for core P2P networking and hole-punching logic, iroh-relay for relay server/client functionality, iroh-base for shared types and primitives, and iroh-dns for DNS-related address resolution. The top-level Cargo.toml lists all workspace members and their relationships.

What is the best way to test changes locally before submitting?

Run cargo test from the workspace root to execute the full test suite. For faster feedback during development, run cargo test --package <crate-name> to target specific crates. Ensure your changes include unit tests in the source files (e.g., src/lib.rs) and integration tests under iroh/tests/ when testing cross-component behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →