Open-source project
n0-computer/sendme avatar
n0-computer/sendme

sendme, and sending a directory over the internet with no account

A tool to send files and directories, based on iroh

1,225 stars83 forksRustApache-2.0

At a glance

What is it?
Sendme is a small Rust CLI built on iroh and the iroh-blobs protocol, so a file or a directory moves between two machines over a hole punched NAT connection, with a relay as the fallback, a blake3 verified stream that can resume, and no server and no account in the middle.
Who is it for?
Adopt sendme if you need a one-off file transfer where the two ends have no shared infrastructure and you do not want to run a server or create an account, because a ticket is a self-contained capability and the transfer is verified. Do not adopt it as a replacement for a sync tool, a backup system or a file server, because the provider runs until you stop it and the receiver writes into the current directory.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A ticket, and the two libraries doing the work

Sendme is an example application using iroh with the iroh-blobs protocol to send files and directories over the internet, and the project says it is also useful as a standalone tool for quick copy jobs.

The example application framing matters. The interesting engineering is in iroh and iroh-blobs, and sendme is the small program that shows how to use them, which is a useful thing for a project to be explicit about, because it sets the expectation that the tool may change shape when the libraries do.

The responsibilities are split cleanly. Iroh takes care of hole punching and NAT traversal whenever possible, and falls back to a relay if hole punching does not succeed. Iroh-blobs takes care of blake3 verified streaming, including resuming interrupted downloads.

That division is the whole design in two sentences, and both halves answer a real problem. Hole punching means the transfer is direct when the network allows it, so the data does not pass through a third party, and the relay is the fallback for the networks where it does not. Verified streaming means the bytes are checked as they arrive rather than trusted, and the resume support means a large download that drops can continue rather than start again.

There is one more property worth stating. Sendme works with 256 bit node ids and is therefore location transparent, so a ticket remains valid if the IP address changes, and connections are encrypted using TLS.

The primary language is Rust, the licence is Apache-2.0 or MIT at your option, and the releases are v0.36.1 from 2026-10-06, v0.36.0 from 2026-06-15 and v0.35.0 from 2026-05-27.

Two commands and one string between them

The usage section is short, and the whole workflow fits on a screen.

Sending is one command with a file or a directory.

bash
sendme send <file or directory>

That creates a temporary iroh node that serves the content in the given file or directory, and it outputs a ticket that can be used to get the data. The provider runs until it is terminated with Control-C, and on termination it deletes the temporary directory. The documentation also notes that this currently creates a temporary directory in the current directory, and that in the future that will not be needed anymore.

Receiving is the mirror image.

bash
sendme receive <ticket>

That downloads the data and creates a file or directory named like the source in the current directory. The order of operations matters here: it creates a temporary directory in the current directory, downloads the data, and only then moves the files to the target directory, and on completion it deletes the temp directory. All temp directories start with .sendme-.

So the download is never partially visible under the final name. If the transfer fails, you are left with a temporary directory rather than a half written file that looks complete, which is the behaviour you want when a directory is being received and a partial copy would be worse than no copy.

The ticket is the only thing that crosses between the two machines, and because it encodes a node id rather than an address, the person receiving it does not need to be on the same network, and the sender can change address mid transfer without invalidating it.

Install, versions, and what the manifest fixes

Installation is a single cargo command.

bash
cargo install sendme

The package manifest gives the rest of the constraints. The package is sendme at version 0.36.1, edition 2021, with a rust-version of 1.91 and a comment reminding the maintainer that the same value has to be updated in the CI workflow file. The authors are Rüdiger Klaehn and the n0 team, and the keywords are scp, sftp, network, p2p and holepunching, with the description being a CLI tool to send directories over the network with NAT hole punching.

That keyword list is a good hint about the intent. The project is positioning itself against the scp and sftp workflows, and the comparison is fair because both of those need an address, a credential and usually a server, whereas a ticket needs none of those.

The dependency set is small and reads like a well-factored CLI. anyhow for errors, clap with the derive feature for the command line, console and indicatif for the terminal and the progress bar, derive_more for the display and from_str derives, futures-buffered for the async plumbing, serde for the configuration and the ticket format, tokio with the full feature set, tracing with tracing-subscriber and an env filter for logging, walkdir to traverse a directory, data-encoding and hex for encoding, num_cpus and rand for the trivial needs, and irpc for the RPC layer.

The two libraries that matter are pinned close to their current majors, iroh at 1.0.0 and iroh-blobs at 0.103.1, with n0-future as a small helper crate from the same organisation.

The release profile is tuned for a small binary: panic set to abort, opt-level s, codegen-units 1, link time optimisation on, debug info stripped and strip enabled.

The clipboard feature, and why it needs per platform code

One optional feature in the manifest is worth looking at, because it explains a chunk of the dependency list.

The clipboard feature enables crossterm with the event-stream and osc52 features, windows-sys with the Win32_System_Console feature, and libc on unix. The clipboard feature is in the default set.

The reason it needs three crates is that copying a ticket to the clipboard is a genuinely different problem on each platform. On unix, OSC 52 is a terminal escape sequence that the terminal emulator handles, and the escape sequence has to be written to the terminal, which is what crossterm provides and what libc is for when the code needs to put the terminal into raw mode. On Windows there is a console API for reading from the clipboard, which is what windows-sys covers.

The alternative would be to shell out to an external clipboard tool, which is what many small CLIs do, and the project has chosen to keep the dependency inside the binary instead. That is a defensible trade for a tool whose entire point is that you copy a ticket and paste it into a chat window.

The default features list is clipboard, so a user who installs with cargo install sendme gets the copy-to-clipboard behaviour without asking for it, and the platform specific dependencies are marked optional so a build for a platform that does not need them does not pull them in.

The crossterm dependency is optional in the manifest but is what makes the feature possible, and the same feature would have to be reimplemented differently for each platform it supports, which is a maintenance cost the project has taken on deliberately for a convenience that is central to the workflow.

Dual licensing, and the contribution clause that keeps it that way

The licence arrangement here is explicit and unusually well stated, and it is worth copying.

The project is licensed under either of the Apache License, Version 2.0, referenced as LICENSE-APACHE, or the MIT licence, referenced as LICENSE-MIT, at your option. The copyright is 2026 N0, INC, and both licence files are in the repository root, and the project metadata records the licence expression as Apache-2.0 OR MIT.

Dual licensing like this is common in libraries where one option suits commercial users with a patent grant and the other suits everyone else who wants the shortest possible notice. The choice is left to the user, which means an organisation with a procurement policy can pick the one it already approves without asking.

The contribution clause is the part that keeps the arrangement working, and it is a specific commitment rather than a general one. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the project by you, as defined in the Apache-2.0 licence, shall be dual licensed as above, without any additional terms or conditions.

That sentence matters more than it looks. Without it, the first corporate contribution under a different licence could complicate the project's ability to offer the MIT option, and the licence file itself would have to be negotiated again. With it, the dual licence is stable by construction, and the only thing a contributor can do is opt out explicitly and be treated differently.

For an author, the practical effect is that the MIT option stays available, which is the whole reason the project offers it.

A small repository with a security-conscious workflow

The repository is small, and the top level listing says what it is. There is a src directory, a tests directory, a Cargo.lock, a Cargo.toml, the two licence files, a README, a.github directory, a.pinact.yaml, a zizmor.yml and a.gitignore.

Two of those files are about supply chain security rather than about the tool. The.pinact.yaml and zizmor.yml files configure those two tools.

That is a sensible two-file security posture for a project whose CI builds and publishes binaries, and it is more attention than most small Rust tools pay to the workflow files.

The test suite is a tests directory rather than inline unit tests, and the dev dependencies describe the approach. duct is a library for running subprocesses, which is how a tool that shells out to itself is tested, nix provides signal and process features for the same reason, tempfile handles the temporary directories the tool creates in the current directory, and serde_json is for the configuration and ticket formats.

The point of testing a program like this is the round trip, and the round trip is what those dependencies are for: start a send, take the ticket, receive it, and check that the file arrives intact.

Editorial conclusion

Adopt sendme if you need a one-off file transfer where the two ends have no shared infrastructure and you do not want to run a server or create an account, because a ticket is a self-contained capability and the transfer is verified. Do not adopt it as a replacement for a sync tool, a backup system or a file server, because the provider runs until you stop it and the receiver writes into the current directory. Before you rely on it, check that the receiving side can accept a directory of arbitrary size, since the receiver downloads into a temporary directory in the current directory first and only then moves the files, and read the ticket rather than the address, because the 256 bit node id stays valid if the IP address changes.

Frequently asked questions

How do I install and use sendme?

Install it with `cargo install sendme`, then run `sendme send <file or directory>` to serve the content and get a ticket, and `sendme receive <ticket>` on the other machine to download it into the current directory.

How does sendme get the data across the network?

It uses iroh, which takes care of hole punching and NAT traversal whenever possible and falls back to a relay if hole punching fails, and iroh-blobs for blake3 verified streaming including resuming interrupted downloads. Connections are encrypted using TLS.

What happens if the download is interrupted?

The transfer uses blake3 verified streaming with support for resuming interrupted downloads. The receiver also downloads into a temporary directory starting with .sendme- and only moves the files to the target directory once the download has finished.

What licence does sendme use?

It is dual licensed at your option, under the Apache License 2.0 or the MIT licence, with LICENSE-APACHE and LICENSE-MIT in the repository. Contributions are dual licensed the same way unless you explicitly state otherwise.

What do I need to build sendme from source?

The manifest specifies edition 2021 with a rust-version of 1.91, and the current package version is 0.36.1. The recent releases are v0.36.1 from 2026-10-06, v0.36.0 from 2026-06-15 and v0.35.0 from 2026-05-27.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. n0-computer/sendme on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/n0-computer-sendme.svg)](https://hysenlabs.com/projects/n0-computer-sendme)

Was this useful?