Pipe anything. Get a link.
pastes turns any command's output into a shareable paste. It is small and quick to
install, prints only the URL on stdout so it composes with other tools, and signs in over SSH on
machines with no browser.
Create your first link
Works on the free plan. Requires Node.js 20 or newer; no global install needed.
1. Sign in
npx pastes login Open the approval link, sign in or create a free account, and approve your code. Wait for the terminal to confirm sign-in.
2. Share a sample
printf 'Hello from my terminal\n' | npx pastes Using PowerShell?
'Hello from my terminal' | npx pastes You’ll get a pastes.io link. Open it to see your sample. Free pastes expire after one month.
npm i -g pastespastes loginMIT, on GitHubGet the CLI
Requires Node.js 20 or newer. Install globally for the shorter pastes command, then run pastes login before sharing.
# Install it globally
npm install -g pastes
# ...or run it without installing
npx pastes --helpHitting a permissions error? Use npx pastes to download and run
the package without installing it globally. A Node version manager is another way to keep global
packages in your user directory.
Signing in
pastes login shows a short code that you approve in any browser — your laptop,
your phone, whatever is nearest. Because the code is displayed rather than typed into a browser
on the same machine, this works over SSH on a server with no desktop.
$ pastes login
Your code: ABCD-2345
Approve at: https://pastes.io/cli
Waiting for approval... Logged in as [email protected]
Key saved to ~/.config/pastes/config.jsonApproving creates an API key and hands it to the terminal that asked for it. The key appears as Pastes CLI in your profile, where you can revoke it at any time. Codes expire after ten minutes and can only be used once.
Only approve a code you started yourself. Anyone holding a code you approve gets an API key that can create, read, and delete pastes on your account.
Read the code before you trust it
pastes is open source under the MIT licence. That matters more here than it might
elsewhere: the CLI stores an API key on your machine, and you should not have to take our word
for how it handles that. The whole thing is a few hundred lines you can read in one sitting.
Auditable
See exactly where your key is written, what is sent to pastes.io, and that nothing goes anywhere else.
Verifiable builds
Every release is published by a GitHub Actions workflow with npm provenance, so the package you install is traceable to the commit that built it.
Yours to change
MIT licensed, so fork it, script around it, or vendor it into your own tooling. Issues and pull requests are welcome.
Running without a login
In CI, containers, and cron jobs there is nobody to approve anything. Set PASTES_API_KEY instead and skip the login entirely.
# CI, containers, cron — no login step, no browser
export PASTES_API_KEY=your-api-key
pastes < build.logThe key is read from --api-key first, then PASTES_API_KEY, then
the stored config file. The environment variable always wins over a stored key, so a
production box can override a stale login without touching disk. Create keys in your profile.
Piping command output
Anything on stdin becomes a paste. With no title given, the first meaningful line of the input is used, which is usually the error you care about.
# Anything on stdin becomes a paste
./deploy.sh 2>&1 | pastes
kubectl logs pod-1 | pastes -t "pod-1 crash" -s logs
docker compose logs --tail 500 | pastes -s logs
git diff | pastes -s diffPasting files
Pass a path and the title comes from the filename, while the syntax is inferred from its
extension — .py becomes Python, .log becomes Logs, and so on. Both
can be overridden.
# Title and syntax are inferred from the filename
pastes server.py
pastes nginx.log
pastes example.txt --password example-password
# ...or set them yourself
pastes dump.txt --title "Prod dump" --syntax sqlReading and managing pastes
pastes get frosty-mole-8821 # print content to stdout
pastes get frosty-mole-8821 > out.txt # save it to a file
pastes ls # your most recent pastes
pastes ls "crash" # search them
pastes rm frosty-mole-8821 # delete one you own
pastes whoami # which account is this key on?pastes ls prints tab-separated slugs and titles, so pastes ls | cut -f1 gives you a plain list of slugs to feed into other commands.
It composes
The paste URL is the only thing written to stdout. Progress messages, warnings, and errors all go to stderr, so you can capture the URL without parsing anything out of it.
# Only the URL goes to stdout, so it composes
url=$(pastes < error.log)
curl -X POST "$SLACK_WEBHOOK" -d "{\"text\":\"Build failed: $url\"}"
# Everything else goes to stderr, so this stays clean
pastes < error.log 2>/dev/null | pbcopyWhen stdout is a terminal the URL is also copied to your clipboard. In a pipeline it is
not, since you are already consuming the output. Use --no-copy to turn that off
entirely.
Commands
| Command | Description |
|---|---|
pastes [file] | Create a paste from a file, or from piped stdin. |
pastes login | Connect this machine to your account. |
pastes logout | Forget the stored API key. |
pastes whoami | Show which account the current key belongs to. |
pastes get <slug> | Print a paste's content to stdout. |
pastes ls [query] | List your pastes, optionally filtered by a search query. |
pastes rm <slug> | Delete a paste you own. |
Options
| Option | Description |
|---|---|
-t, --title <title> | Paste title. Defaults to the filename, or the first line of input. |
-s, --syntax <slug> | Syntax highlighting. Defaults to the syntax inferred from the filename, else txt. |
-e, --expire <code> | 10M, 1H, 1D, 1W, 2W, 1M, 6M, 1Y, N, SD. Defaults to 1M. Free accounts must
use 1M. |
-p, --password <pw> | Protect the paste with a password. |
--no-copy | Do not copy the URL to the clipboard. |
--api-key <key> | Use this key for one command, ignoring the environment and config. |
--api-url <url> | Point at a different host. Useful for local development. |
--json | Print the raw JSON response instead of the URL. |
-q, --quiet | Suppress non-essential stderr output. |
-h, --help | Show the full built-in reference. |
Environment variables
| Variable | Effect |
|---|---|
PASTES_API_KEY | API key to use. Overrides the stored config. |
PASTES_API_URL | API base URL. Defaults to https://pastes.io. |
PASTES_CONFIG_HOME | Directory holding config.json. Defaults to ~/.config/pastes, or %APPDATA%\pastes on Windows. |
PASTES_NO_BROWSER | Never launch a browser during login; only print the link. |
Exit codes
0Success.1Request failed — network error, rejected key, rate limit.2Usage error — bad flag, no input, no API key configured.Quotas are shared with the HTTP API. Free accounts have per-window and daily creation limits plus a daily cap on reads and searches; Pro raises the creation limits and removes the read cap. See limits and quotas or pricing.
Use it as a library
The same package exports a typed client, so a Node script can create pastes without shelling out.
import { PastesClient } from 'pastes';
const client = new PastesClient({
apiUrl: 'https://pastes.io',
apiKey: process.env.PASTES_API_KEY
});
const { success } = await client.createPaste({
title: 'Build log',
content: log,
syntax: 'logs'
});
console.log(success.paste_url);The CLI is open source and MIT licensed — view it on npm or read the source on GitHub. Prefer plain HTTP? See the API documentation.