Skip to content

JeffOtano/goodbye-shortcut

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Goodbye Shortcut

Goodbye Shortcut

The open source migration tool for teams moving from Shortcut to Linear.
No signup. No external migration service. Just paste your tokens and go.

CI CodeQL Quick StartFeaturesHow It WorksContributing

Why Goodbye Shortcut?

Migrating between project management tools sucks. Most solutions require:

  • Signing up for yet another service
  • Trusting a third party with your API tokens
  • Paying for "enterprise" features
  • Waiting for support tickets

Goodbye Shortcut is different:

  • 100% open source — Run it yourself, audit the code
  • No external migration service — You run the app yourself
  • No signup — Just paste your API tokens
  • No cost — Free forever

🚀 Quick Start

git clone https://github.com/JeffOtano/goodbye-shortcut.git
cd goodbye-shortcut
npm install
npm run dev

Then open localhost:3000:

  1. Get your Shortcut API Token
  2. Get your Linear API Key
  3. Paste them in the app
  4. Click migrate

That's it.

For production webhook mode, copy environment variables:

cp .env.example .env.local

To verify production readiness locally:

npm run lint
npm run typecheck
npm run test:run
npm run build

To run live API smoke validation with your own keys:

npm run test:live

See LIVE_TESTING.md for environment setup and report output.

Run infrastructure schema bootstrap (for production mode):

npm run infra:init

✨ Features

Migration Modes

Mode Description Best For
One-Shot Migrate everything at once Teams ready to switch
Team-by-Team Migrate gradually Large organizations
Real-Time Sync Live bidirectional synchronization Parallel rollout and cutover

What Gets Migrated

Shortcut Linear
Stories Issues
Epics Projects
Iterations Cycles
Labels Labels
Comments Comments
External Links Attachments
Estimates Estimates

Operational Safeguards

  • Dry run mode for safe planning before writing to Linear
  • Idempotent re-runs that reuse existing Labels/Projects/Cycles/Issues when possible
  • Per-entity stats and error reporting (attempted/created/reused/failed)
  • Team-targeted runs for staged migration rollout
  • Persisted migration history and downloadable JSON run reports
  • Retry failed stories directly from migration results

Real-Time Sync

  • Dedicated Sync dashboard at /sync with start/pause/resume/stop controls
  • Direction modes: Shortcut -> Linear, Linear -> Shortcut, Bidirectional
  • Conflict policies: Newest Wins, Shortcut Wins, Linear Wins, Manual
  • Cursor-based incremental sync using updated_at and updatedAt
  • Continuous polling sync engine with configurable interval
  • Signed webhook verification with replay protection (when webhook secrets are configured)
  • Webhook trigger endpoints:
    • POST /api/webhooks/shortcut
    • POST /api/webhooks/linear

🔐 Production Webhook Security

For production, configure webhook secrets and run sync with server-side credentials:

Variable Required Purpose
GOODBYE_PRODUCTION_MODE Recommended (true for durable mode) Enables queue-backed webhook processing
GOODBYE_POSTGRES_URL Required in durable mode Postgres for cursors/jobs/events
GOODBYE_REDIS_URL Required in durable mode Redis for BullMQ queue + locks
GOODBYE_SHORTCUT_TOKEN Yes (for webhook-only operation) Shortcut API token for sync jobs
GOODBYE_LINEAR_TOKEN Yes (for webhook-only operation) Linear API key for sync jobs
GOODBYE_LINEAR_TEAM_ID Yes (for webhook-only operation) Target Linear team
GOODBYE_SHORTCUT_WEBHOOK_SECRET Recommended Verifies Shortcut Payload-Signature
GOODBYE_LINEAR_WEBHOOK_SECRET Recommended Verifies Linear Linear-Signature
GOODBYE_WEBHOOK_SHARED_SECRET Optional Shared fallback secret for both providers
GOODBYE_LINEAR_WEBHOOK_TOLERANCE_MS Optional Timestamp drift tolerance for Linear signed events (default: 300000ms)
GOODBYE_SYNC_WORKER_CONCURRENCY Optional Concurrent durable sync workers
GOODBYE_SYNC_SCHEDULER_ENABLED Optional Enables periodic scheduler enqueue
GOODBYE_SYNC_SCHEDULER_INTERVAL_SECONDS Optional Polling interval for scheduler jobs

Behavior:

  • If webhook secrets are configured, unsigned/invalid webhook deliveries are rejected.
  • Linear signed events must include a fresh webhookTimestamp.
  • Replay attempts are rejected within a rolling TTL window.
  • Webhook endpoints enforce per-IP rate limiting to reduce abuse and burst failures.
  • If GOODBYE_* credentials are configured, per-request token headers are optional.
  • In durable mode, webhooks return 202 and process asynchronously via queue workers.

🔒 How It Works

┌──────────────┐       ┌──────────────┐       ┌──────────────┐
│   Shortcut   │──────▶│ Your Browser │──────▶│    Linear    │
│     API      │       │  (the app)   │       │     API      │
└──────────────┘       └──────────────┘       └──────────────┘
                              │
                              ▼
                       localStorage
                    (tokens stay here)

Your tokens are not stored by this app. The app calls provider APIs directly (via same-origin proxy routes when needed).


🏠 Self-Hosting

Vercel (One Click)

Deploy with Vercel

Docker

docker compose up --build

This starts:

  • app (Next.js server)
  • worker (durable sync job processor)
  • scheduler (optional periodic sync enqueuer)
  • postgres (durable cursor/job/event store)
  • redis (durable queue + locks)

Manual

npm run build
npm start

For durable production mode, run these in separate processes:

npm run worker:sync
npm run worker:scheduler

🧱 Durable Production Mode

Set GOODBYE_PRODUCTION_MODE=true with GOODBYE_POSTGRES_URL and GOODBYE_REDIS_URL.

When enabled:

  • Webhook routes enqueue durable sync jobs instead of running inline.
  • Worker process executes jobs with retries/backoff.
  • Cursors and job/event history are stored in Postgres.
  • Redis provides queue durability and worker coordination.

This mode is recommended for teams that need:

  • high reliability under webhook bursts
  • resumable/retryable server-side sync
  • auditable sync job history

🛠 Tech Stack

Technology
Framework Next.js 16
Language TypeScript
Styling Tailwind CSS
Components shadcn/ui
Storage localStorage

🤝 Contributing

We'd love your help making Goodbye Shortcut even better!

# 1. Fork the repo
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/goodbye-shortcut.git

# 3. Create a branch
git checkout -b my-feature

# 4. Make your changes and commit
git commit -m "Add my feature"

# 5. Push and open a PR
git push origin my-feature

See CONTRIBUTING.md for detailed guidelines.

Project standards:


📄 License

MIT — do whatever you want. See LICENSE.


Built for teams ready to say goodbye to Shortcut.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages