Open source · Git-friendly · Self-hosted

Short links,
full control. edge-fast. git-tracked. lightning quick. self-hosted. open source.

A fast URL shortener you own. Manage links from your terminal, track them in git, and serve redirects from the edge.

clipr
$ clipr shorten https://example.com/very/long/path
✓ Shortened https://example.com/very/long/path
https://clpr.sh/x7k9m2

Shorten a URL

Paste any URL below to see how clipr generates short links.

Demo mode — install clipr to create persistent short links.

Everything you need

A complete URL shortening stack — from terminal to edge — with zero vendor lock-in.

Edge-Fast Redirects

Cloudflare Worker serves 302 redirects from 300+ locations. Sub-millisecond KV lookups.

GET /:slug → 302
⌨️

CLI-First Workflow

Shorten, list, delete, and deploy from your terminal. Pipe-friendly output for scripting.

clipr shorten <url>
📁

Git-Tracked Database

URLs live in a JSON file you commit alongside your code. Full history, diffs, and code review.

git commit urls.json
🎯

UTM Tracking Built-In

Attach utm_source, utm_medium, and utm_campaign to any link. Appended automatically on redirect.

--utm-source twitter
🔒

Self-Hosted & Open Source

No third-party services. Deploy to your own Cloudflare account. MIT licensed.

wrangler deploy

Link Expiration

Set expiry dates on links. The worker returns 410 Gone for expired slugs automatically.

--expires 2026-12-31
🏷️

Custom Slugs

Use meaningful slugs like /docs or /launch. Random slugs generated if you prefer.

--slug my-link
📦

Bulk Import

Import URLs from JSON or CSV. Export your database anytime for backup.

clipr import urls.csv
📱

QR Codes

Generate QR codes for any short link. Download as SVG or PNG.

clipr qr my-link
📄

JSON Output

Every command supports --json for machine-readable output. Pipe to jq, scripts, or CI.

clipr list --json
🚀

Deploy to KV

One command pushes your local urls.json to Cloudflare KV for the worker to serve.

clipr deploy
🏷️

Tag System

Organize links with tags. Filter by tag in the CLI or dashboard.

--tags marketing,q1
🔍

Search & Filter

Find links by slug, URL, or description. Client-side search in the dashboard.

clipr list --search docs
🧹

Zero Dependencies

Core package has a single 4KB dependency. No bloat, no supply chain risk.

1 dep (4KB)
📝

TypeScript API

Import and use programmatically. Full type safety with exported types.

import { shorten } from 'clipr'
🏠

Monorepo Ready

Built as a pnpm monorepo. Core, CLI, web, and worker packages work together.

pnpm --filter @clipr/*

Before & After

The Old Way
the old way
1. Copy the long URL from your browser
2. Open Bitly / TinyURL in a new tab
3. Paste the URL, click "Shorten"
4. Copy the short URL
5. Paste into your spreadsheet
6. No versioning. No CLI. No API.
7. Pray the service doesn't shut down
The clipr Way
clipr
$ clipr shorten https://example.com/long/path
✓ Shortened → https://clpr.sh/x7k9m2
$ git add urls.json
$ git commit -m "add short link for launch page"
✓ 1 file changed, 8 insertions(+)
$ clipr deploy
✓ Deployed 13 URLs to Cloudflare KV

Get started in seconds

Quick Start
npm — quick start
$ npx clipr shorten https://example.com
Global Install
npm — global
$ npm install -g clipr
Quick Start
pnpm — quick start
$ pnpm dlx clipr shorten https://example.com
Global Install
pnpm — global
$ pnpm add -g clipr
Quick Start
yarn — quick start
$ yarn dlx clipr shorten https://example.com
Global Install
yarn — global
$ yarn global add clipr
Quick Start
bun — quick start
$ bunx clipr shorten https://example.com
Global Install
bun — global
$ bun add -g clipr
Quick Start
brew — quick start
$ brew install clipr
Global Install
brew — global
$ brew install clipr
Use as a library
@clipr/core
$ npm install @clipr/core
import { JsonBackend } from '@clipr/core';
const backend = new JsonBackend('./urls.json');
const slug = await backend.shorten('https://example.com');

See it in action

Real commands, real output.

Shorten a URL
$ clipr shorten https://example.com/long/path
✓ Shortened → https://clpr.sh/x7k9m2
Custom slug
$ clipr shorten https://docs.example.com --slug docs
✓ Shortened → https://clpr.sh/docs
List all links
$ clipr list
3 shortened URLs:
https://clpr.sh/x7k9m2 → https://example.com/...
https://clpr.sh/docs → https://docs.example.com
UTM tracking
$ clipr shorten https://example.com \
--utm-source twitter --utm-medium social
✓ UTM params will be appended on redirect
Link expiration
$ clipr shorten https://promo.com --expires 2026-12-31
✓ Link expires on 2026-12-31
Delete a link
$ clipr delete x7k9m2
✓ Deleted slug "x7k9m2"
JSON output
$ clipr list --json
[{"slug":"docs","url":"https://docs.example.com",...}]
Link info
$ clipr info docs
Slug: docs
Target: https://docs.example.com
Created: 2026-03-15
Initialize
$ clipr init --base-url https://clpr.sh
✓ Created urls.json
Deploy to KV
$ clipr deploy --namespace-id abc123
ℹ Deploying 12 URLs to KV...
✓ Deployed 12 URLs to Cloudflare KV
Set config
$ clipr config baseUrl https://clpr.sh
✓ baseUrl set to "https://clpr.sh"

Use as a library

Import @clipr/core in your own tools.

@clipr/core exports

  • JsonBackend Read/write urls.json storage backend
  • generateSlug() Generate a random URL-safe slug
  • validateUrl() Validate http/https URLs
  • validateSlug() Validate slug format and reserved words
  • appendUtm() Append UTM parameters to a URL
  • resolveConfig() Merge partial config with defaults
$ npm install @clipr/core
@clipr/core — usage example
// app.ts
import { JsonBackend, validateUrl, appendUtm } from '@clipr/core';
const backend = new JsonBackend('./urls.json');
// Validate and shorten
const url = 'https://example.com/launch';
if (validateUrl(url)) {
const slug = await backend.shorten(url);
console.log(`Created: ${slug}`);
}
// Append UTM params
const tracked = appendUtm(url, {
source: 'twitter',
medium: 'social',
});