Skip to content

Repository files navigation

PaperCut

Interactive terminal pastebin & log analysis canvas
Pipe any terminal output to a secure share link — ANSI colors, filters, JSON trees, and line deep-links.

CI Version v1.2.0 Release npm papercut-cli License Node.js Docker Security Roadmap

yarn build 2>&1 | papercut
# → https://your-host/paste/V1StGXR8_Z

Why PaperCut?

Most pastebins dump plain text. PaperCut turns build logs and terminal streams into a developer workspace: virtualized scrolling for huge files, log-level filters, fuzzy/regex search, expandable JSON, and GitHub-style #L12 links — self-hosted on SQLite with zero analytics.

CLI Zero npm deps · stdin upload · clipboard share card
Canvas ANSI · filters · grep · JSON tree · line links
Self-host Docker + SQLite · password pastes · expiry
Privacy No analytics · no IP/body logging in app code

Features

  • Fast CLI — zero npm dependencies; read stdin, upload, print a share card, copy the URL
  • ANSI-aware viewer — terminal colors and styles in the browser
  • Virtualized log list — comfortable browsing of very large logs
  • Log level filters — DEBUG / INFO / WARN / ERROR / FATAL toggles
  • JSON inspector — expandable trees for structured log lines
  • Search & grep — local keyword or /regex/flags
  • Line linking#L120 / #L120-L125 deep links
  • Private pastes — password-protected links (--private)
  • Expiry — auto-delete after 1h, 1d, 7d, …
  • Privacy-minded — no analytics; you control the data plane
  • SQLite — zero-config persistence for simple deploys

Architecture

stdin ──► papercut CLI ──POST /api/pastes──► Next.js server
                                              │
                                         SQLite (pastes)
                                              │
                         browser ◄── /paste/[id] (log canvas)
Path Role
cli/ Lightweight Node CLI — npm package papercut-cli (npx papercut-cli)
server/ Next.js (App Router) API + log canvas UI

Quick start (development)

Requirements: Node.js ≥ 20 · pnpm 9.x

git clone https://github.com/ArianAr/PaperCut.git
cd PaperCut
pnpm install
cp .env.example server/.env.local
# Set PASTE_AUTH_SECRET to a long random value
pnpm dev
# another terminal
echo -e '\033[31merror\033[0m\n[INFO] all good' | pnpm cli --url http://localhost:3000

Open the printed URL in your browser.


CLI usage

some-command 2>&1 | papercut
some-command 2>&1 | papercut --private
some-command 2>&1 | papercut --expire 1d
some-command 2>&1 | papercut --url https://papercut.example.com
Flag / env Description
-p, --private Password-protect (prompt or PAPERCUT_PASSWORD)
--expire <time> 30m, 1h, 1d, 7d, …
--url <base> Server origin (or PAPERCUT_URL)
-V, --version Print CLI version
-h, --help Show help

Docker (self-host)

export PASTE_AUTH_SECRET="$(openssl rand -hex 32)"
export PAPERCUT_PUBLIC_URL="http://localhost:3000"
docker compose up --build -d
App http://localhost:3000
SQLite volume papercut-data/data/papercut.db
Health GET /api/health
docker build -t papercut .
docker run --rm -p 3000:3000 \
  -e PASTE_AUTH_SECRET="$PASTE_AUTH_SECRET" \
  -e PAPERCUT_PUBLIC_URL=http://localhost:3000 \
  -v papercut-data:/data \
  papercut

For custom domain + HTTPS, put nginx/Caddy/Traefik in front — see docs/deploy.


Environment variables

See .env.example.

Variable Description Default
PAPERCUT_PUBLIC_URL Base URL for share links request origin
DATABASE_PATH SQLite file path ./data/papercut.db
MAX_PASTE_SIZE Max body size (bytes) 10485760 (10 MiB)
PASTE_AUTH_SECRET HMAC secret for unlock cookies required in production
UNLOCK_RATE_LIMIT Unlock attempts / window 10
UNLOCK_RATE_WINDOW_MS Unlock window (ms) 600000
CREATE_RATE_LIMIT Creates / window 60
CREATE_RATE_WINDOW_MS Create window (ms) 600000
PAPERCUT_METRICS Enable GET /api/metrics (1/true/yes/on) off
TRUSTED_PROXY_HOPS X-Forwarded-For hops to trust (0 = ignore XFF; use 1 behind a proxy) 0
COOKIE_SECURE Force Secure cookies (1/0); else from public URL auto
REDIS_URL Shared rate limits across instances (optional) off (in-memory)

HTTP API (stable for 1.x)

Method Path Description
POST /api/pastes JSON { content, expire?, password? } or text/plain body + X-PaperCut-Expire / X-PaperCut-Password headers (streaming CLI)
GET /api/pastes/:id Paste body or 401 + { locked: true }
POST /api/pastes/:id/unlock { password } → httpOnly unlock cookie
GET /api/health Liveness/readiness (+ expired purge)
GET /api/metrics Opt-in counters (PAPERCUT_METRICS); 404 when disabled

UI: /paste/:id · deep links #L12, #L12-L20.


Privacy

  • No analytics SDKs in application code
  • Paste bodies and client IPs are not intentionally logged
  • Rate limiting may use X-Forwarded-For in memory only
  • Optional metrics (PAPERCUT_METRICS) expose counters only (creates, successful unlocks, 429s) — never content or IPs
  • Public pastes are capability URLs — use --private for sensitive data

Documentation

Doc
Changelog Release history
Roadmap Planned features after 1.0
Deploy guide Reverse proxy, HTTPS, SQLite backup
Contributing Dev setup, CI, labels, release checklist
Security Supported versions & vulnerability reporting
Releases Git tags (vX.Y.Z)

Status

Current version: 1.2.0 · CLI on npm · 1.x API compatibility · roadmap: ROADMAP.md

Disclaimer

Most of this project was developed with AI assistance. Changes are peer reviewed, checked, and tested by humans before they land on main (CI, code review, and maintainer oversight). AI does not replace human accountability for what ships.

License

GPL-3.0-only

About

Interactive terminal pastebin & log analysis canvas. Pipe logs to a shareable link with ANSI colors, filters, JSON trees, and line deep-links. Self-hostable (SQLite + Docker), zero-dep CLI.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages