No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
miles d5ed62c9db
All checks were successful
Release Build / Create Release (push) Successful in 1s
Release Build / Publish to the Cargo registry (push) Successful in 42s
Release Build / Linux (binks-cli-linux-amd64) (push) Successful in 48s
Release Build / Linux (binks-cli-linux-arm64) (push) Successful in 1m21s
CI / Rust (push) Successful in 1m59s
CI / Cargo Audit (push) Successful in 25s
Merge pull request 'next' (#2) from next into main
Reviewed-on: #2
2026-11-02 15:57:58 -06:00
.cargo Rewrite the CLI for the Binks 0.8 API 2026-10-11 05:54:44 +00:00
.forgejo/workflows fix ci 2026-10-11 23:38:27 -05:00
src End quietly when the reader of binks' output goes away 2026-11-02 15:11:25 -06:00
tests Follow the server's refused uploads leaving the upload budget alone 2026-11-02 13:47:38 -06:00
.gitignore remove binks as a dependency, and work on cross-ci 2026-04-08 14:24:44 -05:00
Cargo.lock Update the dependencies and build against the Binks v0.9.0 tag 2026-11-02 15:48:38 -06:00
Cargo.toml Update the dependencies and build against the Binks v0.9.0 tag 2026-11-02 15:48:38 -06:00
CHANGELOG.md Call this 0.9.0 and say what changed since 0.8.1 2026-11-02 13:47:38 -06:00
README.md Call this 0.9.0 and say what changed since 0.8.1 2026-11-02 13:47:38 -06:00
rust-toolchain.toml Rewrite the CLI for the Binks 0.8 API 2026-10-11 05:54:44 +00:00

binks

Command-line client for Binks: paste text, upload files of any size (resumable, in parallel), shorten links, with passwords, end-to-end encryption, expiry and burn-after-reading. It needs a Binks 0.9 server (api_version 2 in /api/config) and refuses older ones; binks-cli 0.8 talks to Binks 0.8.

cargo install --path .            # installs the `binks` binary
binks config set server https://binks.example   # or export BINKS_URL

Usage

echo "hello" | binks                    # paste stdin; binary input becomes a file
binks paste "some text" -l rust         # text with syntax highlighting
binks paste "see diagram" -f d.png      # text with an attached file
binks upload video.mp4 -e 1w            # file, expires in a week
binks shorten https://example.com/long/url

binks get https://binks.example/abc     # print a text / download a file / print a link's target
binks get abc -o out.bin                # save under another name
binks get abc --info                    # metadata only; never counts as a read
binks delete abc                        # uses the deletion token saved at upload

Results go to stdout and everything else to stderr, so url=$(binks upload f) just works. --json prints machine-readable results (the server's item JSON, with the URL's #k= key and the deletion token), -q silences status output, -c copies the URL. -l takes a highlight.js language name such as rust, markdown or c++.

binks get reads the item's metadata first, which never counts as a read, then its content: a text prints, a file downloads (its note, if it has one, prints first and doesn't count), and a link prints its target. A burn-after-reading link's target counts as one of its reads, so --info doesn't show it.

Options work before or after the command:

Option
-e, --expiration 1h, 1d, 1w, 1m, 1y, never
-b, --burn-after N delete after N reads
-p, --password PW / -P password-protect (or unlock); -P prompts instead
--encrypted end-to-end encrypt; the key is appended to the URL as #k=...
--key KEY encryption key to use, or to decrypt with
--id ID custom ID
--server URL server (also BINKS_URL, or server in the config)
--token TOKEN API token (also BINKS_TOKEN)
--connections N parallel connections per transfer (default: chosen from the server's latency)
--chunk-size MIB upload chunk size (default: the server's)

Encryption happens locally: the server stores ciphertext and sees neither the file name, its type nor the paste's language. Pastes and files encrypted in the CLI open in the browser and vice versa, as long as the URL keeps its #k= fragment.

Large files are uploaded in chunks, in parallel parts over separate connections, and large downloads (32 MiB and up) are fetched as parallel byte ranges. A distant server (60 ms or more away) gets more connections (8 upload parts, 4 download ranges) since one connection can't fill a fast link over a long path; a nearby one gets 4 and 1. --connections overrides this.

Transfers ride out network drops and server restarts: a broken chunk or download resumes where it stopped, retrying for up to about half an hour while nothing gets through. If an upload is given up on (or you press Ctrl-C), run the same command again to resume it. A server asking to wait longer than five minutes (a rate limit) ends the transfer instead. Downloads stream to disk and never overwrite an existing file unless you pass --force. Burn-after-reading files are always downloaded over one connection.

Scanning. On servers that scan uploads, new files may be unavailable for a moment; binks get --wait waits instead of failing.

Accounts

binks login                  # signs in once and saves an API token for this machine
binks whoami
binks token create ci --scope upload --expires 30   # prints a token for scripts
binks token list
binks logout                 # revokes this machine's token
binks register               # when the server allows sign-ups

Signed-in users can delete their own content without a deletion token. A saved login token is only sent to the server it was created on (token_server in binks config).

Configuration

Settings live in ~/.config/binks/config.toml (BINKS_CLI_CONFIG overrides the path): binks config show | get | set | unset | edit | path | reset. Keys: server, expiration, burn_after, auto_copy, json_output, insecure, ca_cert, connections, chunk_size_mb, token, token_server. Deletion tokens and interrupted uploads are kept in ~/.local/state/binks/.

Shell completions: binks completions bash > ~/.local/share/bash-completion/completions/binks (also zsh, fish, powershell, elvish).

Development

cargo fmt --check && cargo clippy --all-targets -- -D warnings
cargo test

The integration tests in tests/cli.rs run the binary against an in-process Binks server, pulled in as a git dev-dependency (a Binks 0.9 one: the CLI refuses older servers). To test against a local server checkout, patch it in; the patch applies once the lock names it, so update that first (git checkout Cargo.lock undoes it):

P='patch."https://github.com/RaringM/binks".binks.path="../binks"'
cargo update --config "$P" -p binks && cargo test --config "$P"

E2EE test vectors (tests/data/e2ee-vectors.json) are shared with the server's web app.