Skip to content

LidPush

License PRs Welcome Buy Me A Coffee

A desktop tool for pushing local projects to GitHub — cleanly, without the junk. ...

Built by Lidprex Labs. Parent Company Lidprex .


What it does

You pick a local folder, you pick a GitHub repo from your account, you click push. LidPush handles the rest: it strips node_modules, build artifacts, caches, and any detected secrets before anything hits GitHub. Your original folder stays untouched — the cleaning happens on a temporary copy.

The problem it solves is real. A project that starts at 80 files can quietly balloon to 150+ after a few installs and builds. GitHub's file limits become a problem, and more importantly, you end up pushing gigabytes of dependency folders that have no business being in version control. LidPush catches all of that before the push happens.


Stack

Layer What
Desktop Tauri v2
Frontend React 18 + TypeScript
Backend Axum (Rust, embedded, no separate process)
Git git2-rs (libgit2 — no Git install required)
Database Neon PostgreSQL (push history, user records)
Auth GitHub OAuth 2.0

The Axum server starts on a random port every launch and requires a one-time secret header on every request. Nothing is accessible from outside the machine.


Building from source

You'll need Rust (1.77+), Node.js (20+), and the Tauri CLI. Nothing else.

# Install Tauri CLI if you don't have it
cargo install tauri-cli --version "^2"

# Install frontend deps
npm install

# Dev mode (hot reload on both React and Rust changes)
npm run tauri dev

# Production build → outputs an NSIS installer under src-tauri/target/release/bundle/
npm run tauri build

First compile takes a while — Rust is building ~150 crates. After that, incremental builds on the Rust side take 5–15 seconds, and React changes reload instantly without recompiling Rust at all.


Configuration

Two things need your values before the app works:

1. GitHub OAuth App

Go to github.com/settings/developers → OAuth Apps → New OAuth App.

Field Value
Application name LidPush
Homepage URL anything (your site or lidprex.onrender.com)
Authorization callback URL http://localhost:52189/auth/callback

Copy the Client ID and generate a Client Secret. Open src-tauri/src/auth.rs and paste them:

const CLIENT_ID: &str = "your_client_id_here";
const CLIENT_SECRET: &str = "your_client_secret_here";

2. Neon PostgreSQL

Create a free project at neon.tech. Copy the connection string and open src-tauri/src/db.rs:

const NEON_URL: &str = "postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require";

Then run the schema once in the Neon SQL editor:

CREATE TABLE IF NOT EXISTS users (
    id         SERIAL PRIMARY KEY,
    github_id  BIGINT UNIQUE NOT NULL,
    username   TEXT NOT NULL,
    avatar_url TEXT,
    last_seen  TIMESTAMP DEFAULT NOW(),
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS pushes (
    id              SERIAL PRIMARY KEY,
    repo_name       TEXT NOT NULL,
    files_pushed    INTEGER DEFAULT 0,
    files_cleaned   INTEGER DEFAULT 0,
    secrets_blocked INTEGER DEFAULT 0,
    created_at      TIMESTAMP DEFAULT NOW()
);

That's it. Run npm run tauri dev and it should work.


App icon

Icons go in src-tauri/icons/. Tauri expects specific filenames:

src-tauri/icons/
├── 32x32.png
├── 128x128.png
├── 128x128@2x.png
├── icon.ico          ← Windows taskbar + titlebar
├── icon.icns         ← macOS (ignore if Windows-only)
└── icon.png          ← 512×512 source

The fastest way to generate all sizes from a single PNG:

# Install the Tauri icon generator
cargo install tauri-cli --version "^2"  # already installed if you followed above

# Drop your 512×512 source image as icon.png in src-tauri/icons/
# then run:
npm run tauri icon src-tauri/icons/icon.png

That command generates every required size and format automatically. If you skip this step, Tauri uses its own placeholder icon and the taskbar will show the default Tauri logo.

For the .ico file specifically (Windows titlebar), make sure it contains both 16×16 and 32×32 layers. Most icon converters online do this by default when you give them a PNG.


How the internals work

LidPush.exe
│
├── Tauri WebView
│   └── React app (the UI you see)
│       └── calls internal API via fetch to 127.0.0.1:RANDOM_PORT
│
└── Axum HTTP server (spawned at startup, random port)
    ├── /auth/url        opens browser for GitHub OAuth
    ├── /auth/callback   catches the OAuth redirect, stores token in Windows Credential Manager
    ├── /auth/status     checks if a token exists
    ├── /github/repos    lists your GitHub repos
    ├── /push/start      runs the clean + git2 push pipeline
    └── /push/history    reads push records from Neon DB

The port is randomized on every launch. The React frontend learns the port at startup via a Tauri IPC call (invoke("get_server_port")). Every request also requires an x-lidpush-secret header containing a UUID that's generated fresh each launch. This means nothing on the machine can accidentally or maliciously call the internal API without knowing both values.

The GitHub token never touches the React side. It's stored in and retrieved from Windows Credential Manager via the keyring crate. The frontend only sees success/failure responses.


Cleaning logic

Before any push, LidPush scans the project and removes:

  • Dependency folders: node_modules, venv, .venv, vendor, Pods
  • Build output: dist, build, target, out, bin, .next, .nuxt
  • Caches: __pycache__, .pytest_cache, .gradle, .m2, .npm
  • Lock files: package-lock.json, yarn.lock, pnpm-lock.yaml
  • OS junk: .DS_Store, Thumbs.db, desktop.ini
  • Temp/compiled: *.pyc, *.log, *.tmp, *.class, *.o

It also scans text files for secret patterns before the push: GitHub tokens, AWS keys, private key blocks, Stripe keys, Discord tokens, and generic API_KEY=... patterns. If anything matches, it's flagged in the activity log. The push still goes through (it's a warning, not a block) but it's visible.

This is the same logic as RepoPrep, rewritten in Rust. It's considerably faster on large repos.


Language support

The UI ships in five languages, switchable from the titlebar dropdown without restarting:

  • English
  • Arabic (العربية)
  • Russian (Русский)
  • Hindi (हिन्दी)
  • Chinese (中文)

Translations live in src/i18n/index.ts. Adding a new language means adding one object to that file.


License

Apache-2.0 license © 2026 Lidprex Labs

Support

LidPush is completely free and open-source. If it saves you time or helps your workflow, consider supporting the project:

Buy Me A Coffee

Your support covers infrastructure costs and helps us build more privacy-first tools.

About

A desktop tool for pushing local projects to GitHub — cleanly, without the junk

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages