Piknik: a network clipboard for hosts behind NAT
Copy/paste anything over the network.
At a glance
- What is it?
- Piknik moves text, files and live streams between machines that cannot reach each other directly, relaying encrypted bytes through a staging server. It solves a narrow problem well, and the setup cost is a key exchange you have to get right.
- Who is it for?
- Adopt Piknik if you routinely move snippets or files between machines that cannot see each other and you are willing to run one small relay. Do not adopt it if you need a shared, persistent clipboard across many users, or if nobody in your team can host a publicly reachable TCP port.
- Can I use it commercially?
- Yes. BSD-2-Clause 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 170 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 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Piknik fills: a clipboard with no shared filesystem
Copying between two machines usually assumes something in common. SSH needs a reachable host and credentials. Shared drives need a mount. Chat apps need an account and a browser. Piknik assumes none of that. The README describes the target case directly: hosts that sit behind NAT gateways, on different networks, with no SSH needed. The author's framing is a clipboard that works over the network, and the two headline commands mirror the local clipboard verbs, copy and paste.
That makes it useful for a specific kind of person. A developer moving a token from a laptop to a build box. Someone on a corporate network who cannot open an inbound port. An operator who wants to send a tarball to a machine that only makes outbound connections. The README also claims cross-platform sharing between macOS, Linux and Windows, which matters because the awkward part of most transfer tools is that one end is a platform you do not control.
The scope is deliberately small. There is no account system, no web interface, no history browser. Content is held on a staging server and retrieved by whoever holds the matching client configuration. If you were hoping for a team-wide clipboard with named channels, this is the wrong shape of tool.
How the staging server relays without reading
The architecture has two roles. A staging server runs `piknik -server` and must be publicly accessible; the README states it must at least be reachable by clients over TCP on the configured port. Clients run `piknik -copy` and `piknik -paste`. The clipboard content transits over TCP through that server, which is how NAT and firewall problems get worked around.
The server does not get plaintext. The README states that nothing transits without end-to-end encryption and that the server cannot learn much about what the clipboard contains. The key material is generated once with `piknik -genkeys` and split across two configuration files. The server side gets `Listen`, `Psk` and `SignPk`. The client side gets `Connect`, `Psk`, `SignPk`, `SignSk` and `EncryptSk`. The asymmetry is the point: the server holds a public signing key and a pre-shared key, while the secret signing and encryption keys stay on clients.
Streaming mode reuses the same trust structure. One or more receivers run `piknik -pull`, a sender runs `piknik -push`, and all connected receivers get the same stream. The README notes only one sender can be active at a time. The optional `-cid` flag binds a label into the stream key derivation; the label is never sent over the wire, so a mismatch produces a decryption error rather than a silent wrong result. That is a defensible design, though it means a typo in a deploy label looks like a cryptographic failure.
Installing Piknik and running a first copy and paste
There are three documented install paths. Precompiled binaries for macOS, Linux (i386, x86_64, ARM), Win32, Win64, DragonflyBSD, NetBSD and FreeBSD are linked from the releases page. On macOS, Homebrew works. Otherwise you compile from source, and the README states Go >= 1.24 is required.
go buildThat produces a `piknik` executable in the current path. The repository's `go.mod` pins `go 1.24.0` and pulls in `github.com/BurntSushi/toml`, `github.com/minio/blake2b-simd`, `github.com/mitchellh/go-homedir`, `golang.org/x/crypto` and `golang.org/x/term`.
Next, generate keys. The README recommends random keys over password-derived ones.
piknik -genkeysThe output contains sections for servers, clients, and a hybrid section for a host acting as both. Only the server section goes on the staging server; only the client section goes on clients. Then write the configuration. The default location is `~/.piknik.toml`, except on Windows where it is `piknik.toml`. A client file follows the shape the README shows, with `Connect` edited to reflect the staging server IP and port.
Connect = "127.0.0.1:8075" # Edit appropriately
Psk = "bf82bab384697243fbf616d3428477a563e33268f0f2307dd14e7245dd8c995d"
SignPk = "0c41ca9b0a1b5fe4daae789534e72329a93a352a6ad73d6f1d368d8eff37271c"
SignSk = "cecf1d92052f7ba87da36ac3e4a745b64ade8f9e908e52b4f7cd41235dfe7481"
EncryptSk = "2f530eb85e59c1977fce726df9f87345206f2a3d40bf91f9e0e9eeec2c59a3e4"The README is explicit that these sample values should not be used and that you should get your own keys with `piknik -genkeys`. Run `piknik -server` on the relay, then copy from one host and paste on another. The README's own example pipes standard input into the copy side and reads standard output on the paste side.
pkc < kitten.gif
pkp > kittencopy.gifThose two commands are shell aliases, not binaries. The README points at a sample alias list and the repository ships `zsh.aliases` and a `fish-shell/` directory. `-paste` is described as a no-op and is the default action when `-copy` is not given. `-move` retrieves, prints and clears, and the README notes only one client will see the content.
Where Piknik stops being the right tool
The clipboard is a single slot, not a queue. If two people paste at the same time, the second write replaces the first. There is no versioning and no way to recover what was overwritten. For a personal scratchpad that is fine; for anything resembling shared state it is a data loss bug waiting to happen.
Memory is the other hard boundary. The README says to feed it anything as long as it fits in memory. That is an explicit ceiling, and it applies to the copy path. Streaming mode relaxes this for the sender side, but the README documents streaming limits that the server enforces: `MaxStreamBytes` defaults to 10737418240 (10 GiB), `MaxStreamDuration` defaults to 86400 seconds, and `MaxWaitingPullers` defaults to 100. Those defaults are generous, and they are also the failure surface. A long-running pipeline that exceeds the duration cap gets cut off.
The relay is a single point of failure by construction. If the staging server is down, nothing transits, and there is no documented fallback or peer-to-peer path. The README does not document rollback, retry behaviour, or what a client does when the server accepts a connection and then dies mid-stream.
Finally, streaming output is not trustworthy until the process exits. The README states that a zero exit status means all chunks were authenticated via AEAD and the complete stream signature was verified, and that a non-zero exit means the stream was incomplete or tampered with. Any pipeline that writes `piknik -pull` output straight into a deploy step without checking the exit status is using the tool incorrectly.
Piknik against a shared clipboard or an ad hoc transfer
The nearest alternative people reach for is a paste service or a shared clipboard daemon. The difference is where trust sits. A paste service terminates your data on someone else's host and gives you a URL; Piknik keeps the relay blind and requires the recipient to hold a client configuration with the secret keys. If your threat model includes the relay operator, that distinction decides the choice. If it does not, a paste service is less setup.
Against plain `scp` or `rsync`, the difference is direction. Those need the destination to accept an inbound connection, which is exactly the case Piknik was built for. Piknik inverts it: both sides dial out to a relay. The cost is that you now operate a relay.
Against a full file sync tool, Piknik has no resumption, no delta transfer and no directory semantics. It moves a blob or a stream. The README's own `tar cvf - *.txt | pkc` example is a hint that archiving is the user's job, not the tool's. If you need incremental sync of a tree, Piknik is not a smaller version of that tool; it is a different one.
Maintenance, licence and what upgrading costs
The repository is not archived, and the last push was on 2026-04-13. Release history is uneven: 0.10.2 landed on 2024-12-12, 0.10.1 on 2021-02-22, and 0.9.1 back in 2016. Long gaps between releases are normal here, so a quiet period should not be read as abandonment, and it should not be read as a guarantee either. Pin a version rather than tracking the branch.
The project is BSD-2-Clause. That is a permissive licence, and it means you can ship the binary inside a product without publishing your own source. It says nothing about the cryptographic guarantees of the protocol, which come from the implementation and the key handling, not the licence text. This is not legal advice; check the `LICENSE` file in the repository for the actual terms.
The upgrade cost is concentrated in the configuration format. Keys are generated once and copied into TOML files, and the README warns to copy only the server section to servers and only the client section to clients. A release that changes key derivation or the configuration schema would force every host to regenerate and redistribute, and the README does not document a migration path. The `-password` switch provides an escape hatch: the same password always generates the same set of keys on all platforms, which makes re-provisioning repeatable at the cost of deriving secrets from something weaker than random bytes. The README itself calls random keys highly recommended.
Editorial conclusion
Adopt Piknik if you routinely move snippets or files between machines that cannot see each other and you are willing to run one small relay. Do not adopt it if you need a shared, persistent clipboard across many users, or if nobody in your team can host a publicly reachable TCP port. Before rolling it out, verify three things: that `piknik -genkeys` output has been split correctly between server and client configuration files, that `chmod 600 ~/.piknik.toml` is applied on every client, and that your pipelines check the exit status of `piknik -pull`, because the README states stream output should be considered tentative until the process exits with code 0.
Frequently asked questions
What is Piknik?
It is a command line tool that copies and pastes data over the network, using a staging server so that hosts behind NAT can reach each other. The README describes it as a copy/paste clipboard that works over the network, with end-to-end encryption so the server cannot learn much about the content.
How do I install Piknik?
Download a precompiled binary for macOS, Linux, Win32, Win64, DragonflyBSD, NetBSD or FreeBSD from the releases page, use `brew install piknik` on macOS, or compile the source with `go build` using Go >= 1.24. The README lists all three options.
Does Piknik need a server to work?
Yes. The clipboard content transits over TCP via a staging server, which must be publicly accessible and reachable by clients on the configured port. You run it with `piknik -server`, and commands without a valid API key are rejected.
Can Piknik transfer files, not just text?
Yes. The README shows binary transfer with `pkc < kitten.gif` and `pkp > kittencopy.gif`, and archiving with `tar cvf - *.txt | pkc`. The stated constraint is that the content must fit in memory.
What happens if sender and receiver use different -cid labels in Piknik streaming mode?
The receiver fails with a decryption error. The label is bound into the stream key derivation and is never sent over the wire, so both sides must agree on the same value.
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/jedisct1-piknik)