PASTES.IO COMMAND LINE

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.

./deploy.sh 2>&1 | pastes
Installnpm i -g pastes
Authpastes login
Open SourceMIT, on GitHub
INSTALL

Get the CLI

Requires Node.js 20 or newer. It is a small download that pulls in nothing else, and there is nothing to configure afterwards.

# Install it globally
npm install -g pastes

# ...or run it without installing
npx pastes --help

Hitting a permissions error? On macOS and Linux a global install writes to a system directory, so it fails unless you prefix it with sudo. You can avoid that entirely: npx pastes installs nothing, and Node version managers such as nvm, fnm, or Volta keep global packages inside your home directory. On Windows the default location is already in your user profile, so no elevation is needed.

AUTHENTICATION

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.json

Approving 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.

OPEN SOURCE

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.

pastes-io/pastes-cli

CI AND SERVERS

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.log

The 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.

EVERYDAY USE

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 -e 1D
git diff | pastes -s diff
EVERYDAY USE

Pasting 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 --expire 1D
pastes secrets.env --password hunter2

# ...or set them yourself
pastes dump.txt --title "Prod dump" --syntax sql
EVERYDAY USE

Reading 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.

DESIGN

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 | pbcopy

When 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.

REFERENCE

Commands

CommandDescription
pastes [file]Create a paste from a file, or from piped stdin.
pastes loginConnect this machine to your account.
pastes logoutForget the stored API key.
pastes whoamiShow 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.
REFERENCE

Options

OptionDescription
-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-copyDo 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.
--jsonPrint the raw JSON response instead of the URL.
-q, --quietSuppress non-essential stderr output.
-h, --helpShow the full built-in reference.
REFERENCE

Environment variables

VariableEffect
PASTES_API_KEYAPI key to use. Overrides the stored config.
PASTES_API_URLAPI base URL. Defaults to https://pastes.io.
PASTES_CONFIG_HOMEDirectory holding config.json. Defaults to ~/.config/pastes, or %APPDATA%\pastes on Windows.
PASTES_NO_BROWSERNever launch a browser during login; only print the link.
REFERENCE

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.

ADVANCED

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.