qrcp: Sending Files to a Phone by Scanning a QR Code in the Terminal
:zap: Transfer files over wifi from your computer to your mobile device by scanning a QR code without leaving the terminal.
At a glance
- What is it?
- qrcp binds a temporary web server to your Wi-Fi interface, prints a QR code, and lets a phone browser pull or push files. It is a small MIT-licensed Go tool for people who work in a terminal and do not want to install a mobile app.
- Who is it for?
- Adopt qrcp if both devices share a Wi-Fi network and you want a one-command transfer with no app installed on the phone. Do not adopt it for transfers across separate networks, for untrusted shared networks without a TLS certificate, or when you need the server to survive the first completed transfer and keep serving.
- Can I use it commercially?
- Yes. MIT 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 134 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem qrcp removes: no cable, no account, no mobile app
Moving a file between a laptop and a phone normally means one of three things: a USB cable, a cloud account both devices are signed into, or a chat app that recompresses the file. qrcp takes a fourth route. Both devices are already on the same Wi-Fi network, so the computer can serve the file directly and the phone only needs a browser and a camera. The README frames the tool as transferring files over Wi-Fi "by scanning a QR code without leaving the terminal".
The audience is narrow and specific: developers, sysadmins and anyone who lives in a shell and treats the phone as a second screen. It also suits one-off transfers where installing a mobile client is disproportionate to the task, for example handing a build artifact or a screenshot to a colleague's phone. It is not a sync tool, and it is not a replacement for a shared drive. Each invocation is a short-lived transfer, not a persistent service.
How the temporary web server and QR code work together
The mechanism is deliberately small. According to the README, qrcp "binds a web server to the address of your Wi-Fi network interface on a random port and creates a handler for it". The default handler serves the content and exits the program when the transfer is complete. In receive mode the roles invert: qrcp serves an upload page and handles the incoming transfer.
The QR code encodes a URL in the form the README gives as `http://{address}:{port}/{random_path}`. The random path segment matters: it is the only thing standing between the file and anyone else on the same network who guesses the address and port, which is why the default is a random string rather than a fixed route. Most QR scanner apps detect a URL in the decoded text and open it in the default browser, so the phone starts downloading without any extra confirmation step.
The dependency list in go.mod matches that design. `github.com/skip2/go-qrcode` draws the code in the terminal, `github.com/spf13/cobra` and `github.com/spf13/viper` handle the command surface and configuration, and `github.com/adrg/xdg` resolves the config directory. There is no database, no daemon and no state directory in the repository layout, which is consistent with a process that starts, serves and exits.
Installing qrcp and running a first send and receive
The README lists several install paths. On macOS, Homebrew is the shortest. On Linux there are AUR, Debian and RPM packages, and on Windows there is WinGet, Scoop and Chocolatey. Building from source requires Go 1.18 or later, and go.mod pins the module to Go 1.21.0 with toolchain go1.24.1.
go install github.com/claudiodangelis/qrcp@latestAfter installation, the README suggests confirming the binary works before anything else.
qrcp --helpSending a single file is the default mode. The README's example uses a PDF, and the same command shape works for any file. The terminal prints the QR code, and scanning it with a phone camera opens the browser and starts the download.
qrcp MyDocument.pdfReceiving is a subcommand. With no arguments it writes into the current working directory, and `--output` redirects it.
qrcp receive --output=/tmp/dirThe README also documents a `--zip` flag for compressing a file before transfer, which is the practical option for a large video, and multiple paths can be passed in one invocation to send several files. If the machine has more than one network interface, `-i` selects which one the server binds to, for example `qrcp -i tun0 MyDocument.pdf` for a VPN interface, or `-i any` to bind to all of them.
Configuration file, environment variables and the QRCP_ prefix
qrcp runs without configuration, but the defaults are worth overriding in two situations: a laptop with several interfaces, and a network where you do not want a random port. The default config file lives at `$XDG_CONFIG_HOME/qrcp/config.yml`, and `--config` points at a different file, as in `qrcp --config /tmp/qrcp.yml MyDocument.pdf`.
The keys are the ones the README documents: `interface`, `bind`, `port`, `path`, `output`, `fqdn`, `keep-alive`, `secure`, `tls-cert` and `tls-key`. Two of them interact in a way worth knowing. `bind` sets the address directly and overrides `interface`, so setting both is redundant. `fqdn` replaces the IP address in the URL with a hostname, which is useful when the phone resolves a local name but the raw IP is unreachable. The README gives `interface: any` as the value that binds the web server to `0.0.0.0`.
Environment variables cover the same ground with a `QRCP_` prefix. The README names `$QRCP_INTERFACE`, `$QRCP_PORT` and `$QRCP_KEEPALIVE`, which is enough to pin the interface and port in a shell profile or a script without writing a YAML file. Note the spelling difference between the YAML key `keep-alive` and the variable `QRCP_KEEPALIVE`.
keep-alive, HTTPS and the limits of a one-shot server
The default behaviour is to exit once the transfer finishes. That is efficient for a single file and awkward for anything else. If you are sending a folder to two people, or you want to send a second file after the first, the server is already gone. The `keep-alive` option exists for that case, and the README describes it as keeping the server alive after transferring files, defaulting to `false`.
The security model deserves a plain statement. By default the transfer is plain HTTP over the local network, protected only by the random path segment and by the assumption that the Wi-Fi network is trusted. Anyone who can observe the traffic or guess the URL can fetch the file. The `secure` option switches to HTTPS and requires `tls-cert` and `tls-key`, but the README does not describe certificate generation, so you supply your own pair. The README's HTTPS example is `qrcp --tls-cert /path/to/cert.pem --tls-key /path/to/cert.key MyDocument.pdf`. On a coffee shop or hotel network, that is the difference between a private transfer and a public one.
The more common failure mode is simpler: the phone cannot reach the address. qrcp picks an interface and encodes its address, and if that interface is a VPN tunnel, a Docker bridge or a virtual adapter, the phone has no route to it. The fix is `-i` with the real Wi-Fi interface, or `-i any` on the command line. Neither the README nor the release notes describe a fallback that detects an unreachable address, so this is diagnosed by reading the URL in the QR code and checking it against the phone's network.
Where qrcp sits next to LocalSend and similar tools
The related searches around this project point at LocalSend, Cimbar and Txqr, and the README itself has a section titled Clones and Similar Projects. The distinction that matters is what runs on each end.
LocalSend is a cross-platform application that installs on both devices and discovers peers on the local network. It gives you a persistent device identity, a transfer history and a UI, at the cost of installing software on the phone. qrcp inverts that: nothing is installed on the phone, the browser is the client, and the pairing step is a camera scan. The trade is that qrcp has no identity, no history and no discovery beyond the QR code itself.
Cimbar and Txqr belong to a different family. They encode data into the image or the video stream itself rather than into a URL, so they can move a payload through a camera without a network path at all. That is the airgapped case, and it is the opposite of qrcp's design, which assumes a working Wi-Fi link and uses the QR code only to carry an address. If the two devices cannot reach each other over TCP, qrcp is the wrong tool and an optical transfer tool is the right one.
Licence, maintenance and what an upgrade actually costs
qrcp is MIT licensed, which permits commercial and closed-source use and modification provided the copyright notice and permission notice are retained. That is a permissive arrangement with no copyleft obligation, and it is compatible with shipping the binary inside a larger internal toolchain. This is a description of the licence text, not legal advice; if the binary is redistributed, the notice requirement is the part to check with whoever handles licensing.
The last push to the default branch was on 2026-05-18, and the most recent release in the repository's release list is v0.11.6 from 2025-03-16. The project is not archived. Releases are managed with goreleaser, which is what produces the platform archives and the package-manager artifacts listed in the README.
Upgrade cost is low by construction. The configuration surface is eleven keys, three of which have environment variable equivalents, and the command surface is a send mode plus a receive subcommand. There is no plugin API, no server-side state and no migration path to maintain. The realistic upgrade risk is the dependency chain in go.mod, which pulls in Cobra, Viper and a YAML parser, and the toolchain line that pins go1.24.1. Building from source on an older Go installation is where an upgrade is most likely to fail, and the README's stated floor of Go 1.18 or later is looser than what go.mod actually declares.
Editorial conclusion
Adopt qrcp if both devices share a Wi-Fi network and you want a one-command transfer with no app installed on the phone. Do not adopt it for transfers across separate networks, for untrusted shared networks without a TLS certificate, or when you need the server to survive the first completed transfer and keep serving. Before relying on it, verify that the QR code's URL resolves from the phone, confirm which interface qrcp picked with a config file or -i, and test one send and one receive on your actual network.
Frequently asked questions
What application protocol is used to transfer files with qrcp?
qrcp serves the file over HTTP by default from a web server bound to your Wi-Fi interface, and the QR code encodes a URL of the form http://{address}:{port}/{random_path}. The phone's browser performs an ordinary HTTP download, or an upload in receive mode. Setting secure to true switches the server to HTTPS with a certificate and key you provide.
How can I receive a file using a QR code with qrcp?
Run the receive subcommand, which serves an upload page and handles the incoming transfer. With no arguments it writes to the current working directory, and --output points it at another directory such as /tmp/dir. Scanning the printed QR code opens that upload page in the phone's browser.
Does qrcp need a mobile app installed on the phone?
No. The README states that most QR apps detect URLs in decoded text and open them in the default browser, so the phone only needs a camera and a browser. That is the main difference from tools such as LocalSend, which require software on both devices.
Why does the phone fail to open the qrcp URL?
qrcp binds to the address of one network interface, and if it picked a VPN tunnel, a Docker bridge or another virtual adapter, the phone has no route to that address. Use -i with the real Wi-Fi interface, or -i any to bind to all interfaces.
Where does qrcp store its configuration file?
The default location is $XDG_CONFIG_HOME/qrcp/config.yml, and the --config flag points at a different file. Keys include interface, bind, port, path, output, fqdn, keep-alive, secure, tls-cert and tls-key, and the same settings are available through QRCP_-prefixed environment variables.
Official sources
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.
[](https://hysenlabs.com/projects/claudiodangelis-qrcp)