Skip to content

adityabhalsod/clip-stacker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

clip-stacker logo

clip-stacker

A fast, lightweight clipboard manager for Linux desktops

Quick Install Build License: MIT


clip-stacker runs quietly in the background, captures everything you copy, and lets you pull up your full clipboard history with a single keystroke. Select any past item and it gets pasted instantly β€” just like the Windows 11 clipboard manager, but on Linux.

Built with C++20 and Qt 6 for speed and low resource usage. History is stored locally in SQLite. Packaged as a .deb for easy installation on Ubuntu, Debian, Linux Mint, Pop!_OS, and similar distributions.


Table of Contents


✨ Features

Feature Description
Clipboard History Saves plain text, rich text (HTML/RTF), images, and file URI lists
Instant Popup Press Ctrl+Super+V to open a searchable history panel near your cursor
Single-Click Paste Click any item β†’ it copies to clipboard and pastes into the active app
Pin & Favorite Pin important clips so they're never pruned; star favorites for quick access
Live Search Type to filter history entries in real time
System Tray Runs in the background; access history, settings, and quit from the tray icon
Auto-Start Optional autostart integration for GNOME, KDE, XFCE, and other freedesktop sessions
Deduplication Identical clips are merged instead of creating duplicates
Source Tracking Remembers which application produced each clip (X11)
Multi-Device Sync Share non-sensitive clips across machines via a shared folder
CLI Fallback clip-stacker --toggle-popup for desktops that block global hotkeys
Lightweight C++20, ~5 MB binary, minimal runtime memory

🎬 How It Works (60-Second Overview)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  You copy something (Ctrl+C, right-click β†’ Copy, etc.)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  clip-stacker captures the clipboard content silently    β”‚
β”‚  and stores it in a local SQLite database                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Press Ctrl+Super+V β†’ popup appears near your cursor     β”‚
β”‚  Click any item β†’ it pastes into the previously active   β”‚
β”‚  application (just like Windows 11's Win+V)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“¦ Quick Install

Option A β€” Download a package

Go to the Releases page and download the package for your distro and architecture:

Package Distros Architectures
.deb Ubuntu 22.04+, Debian, Linux Mint, Pop!_OS amd64
.rpm Fedora 37+, openSUSE, RHEL, AlmaLinux, Rocky x86_64, aarch64
.tar.gz Arch Linux, and any other distro x86_64, aarch64

Ubuntu / Debian:

sudo apt install ./clip-stacker_*_ubuntu_amd64.deb

Fedora / RHEL:

sudo dnf install ./clip-stacker_*_fedora_x86_64.rpm

Arch Linux (and other distros β€” tarball):

sudo tar -xzf clip-stacker_*_arch_x86_64.tar.gz -C /
sudo update-desktop-database /usr/share/applications
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor

Option B β€” Build from source

See Build From Source below.


πŸš€ Getting Started

Step 1 β€” Launch the app

After installation, start clip-stacker from your application menu or terminal:

clip-stacker

A small icon appears in your system tray (notification area).

Step 2 β€” Copy things as usual

Copy text, images, files, or rich content normally (Ctrl+C, right-click β†’ Copy, etc.). clip-stacker captures everything automatically in the background.

Step 3 β€” Open clipboard history

Press Ctrl+Super+V (Ctrl + Windows key + V). A popup appears near your cursor showing all your recent clips.

Step 4 β€” Paste a previous item

Click any item in the popup. clip-stacker will:

  1. Copy that item to your clipboard
  2. Close the popup
  3. Restore focus to the app you were using
  4. Automatically paste it (Ctrl+V) into that app

That's it! You now have unlimited clipboard history.

Step 5 β€” Explore more features

  • Search: Type in the search box at the top of the popup to filter history
  • Pin items: Right-click β†’ Pin to prevent an item from being pruned
  • Tray menu: Right-click the tray icon for quick access to History, Settings, and Quit
  • Auto-start: Enable auto-start so clip-stacker launches when you log in

⌨ Keyboard Shortcuts

Shortcut Action
Ctrl+Super+V Open/close clipboard history popup
Enter Paste the highlighted item
↑ / ↓ Navigate through history items
Escape Close the popup
Type in search Filter history entries in real time

βš™οΈ Configuration

Right-click the tray icon β†’ Settings to configure:

Setting Description Default
History limit Maximum number of entries to keep 500

Settings are stored via Qt's QSettings mechanism (~/.config/clip-stacker/).

Enable auto-start

Run the included helper script to add clip-stacker to your desktop session's autostart:

/usr/lib/clip-stacker/install-autostart.sh

Or manually copy the desktop entry:

cp /usr/share/applications/clip-stacker.desktop ~/.config/autostart/

πŸ”¨ Build From Source

Prerequisites

Ubuntu / Debian (22.04+):

sudo apt update
sudo apt install -y \
  build-essential \
  cmake \
  ninja-build \
  qt6-base-dev \
  qt6-declarative-dev \
  qt6-tools-dev \
  qt6-svg-dev \
  qt6-wayland \
  libx11-dev \
  libxtst-dev \
  libxfixes-dev

Fedora (37+):

sudo dnf install -y \
  gcc-c++ cmake ninja-build \
  qt6-qtbase-devel qt6-qtdeclarative-devel qt6-qttools-devel \
  qt6-qtsvg-devel qt6-qtwayland-devel \
  libX11-devel libXtst-devel libXfixes-devel

Arch Linux:

sudo pacman -S --needed \
  base-devel cmake ninja \
  qt6-base qt6-declarative qt6-tools qt6-svg qt6-wayland \
  libx11 libxtst libxfixes

Compile

# Clone the repository
git clone https://github.com/adityabhalsod/clip-stacker.git
cd clip-stacker

# Configure (Debug build)
cmake -S . -B build

# Configure (Release build β€” recommended)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release

# Build using all available CPU cores
cmake --build build -j$(nproc)

Run

./build/clip-stacker

πŸ“¦ Package as .deb

Using the helper script

./packaging/linux/build-deb.sh

Using CMake/CPack directly

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
cpack --config build/CPackConfig.cmake -G DEB

Output: clip-stacker_0.1.0_amd64.deb

Install the generated package:

sudo apt install ./clip-stacker_0.1.0_amd64.deb

πŸ— Project Architecture

High-Level Design

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Application Layer                           β”‚
β”‚   ApplicationController  β€” bootstraps services and wiring          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    UI Layer       β”‚   Core Layer     β”‚   Platform Layer             β”‚
β”‚                   β”‚                  β”‚                              β”‚
β”‚  PopupController  β”‚  HistoryManager  β”‚  HotkeyManager (X11 grab)   β”‚
β”‚  TrayController   β”‚  ClipboardDB     β”‚  InputSimulator (XTest)      β”‚
β”‚  SettingsDialog   β”‚  ClipboardListen β”‚  SyncEngine (shared folder)  β”‚
β”‚                   β”‚  HistoryListModelβ”‚                              β”‚
β”‚                   β”‚  SettingsManager β”‚                              β”‚
β”‚                   β”‚  Logger          β”‚                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Source Tree

clip-stacker/
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── release.yml          # CI/CD pipeline
β”œβ”€β”€ assets/
β”‚   └── icons/
β”‚       └── clip-stacker.svg     # App icon
β”œβ”€β”€ packaging/
β”‚   └── linux/
β”‚       β”œβ”€β”€ build-deb.sh         # One-command .deb builder
β”‚       β”œβ”€β”€ clip-stacker.desktop.in  # Desktop entry template
β”‚       └── install-autostart.sh # Autostart helper
β”œβ”€β”€ resources/
β”‚   β”œβ”€β”€ qml/
β”‚   β”‚   β”œβ”€β”€ Main.qml            # QML popup definition
β”‚   β”‚   └── components/
β”‚   β”‚       └── HistoryDelegate.qml
β”‚   └── resources.qrc           # Qt resource bundle
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.cpp                # Entry point
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   └── ApplicationController.cpp/.h
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ ClipboardDatabase.cpp/.h   # SQLite persistence
β”‚   β”‚   β”œβ”€β”€ ClipboardEntry.h           # Data model
β”‚   β”‚   β”œβ”€β”€ ClipboardListener.cpp/.h   # Live clipboard monitor
β”‚   β”‚   β”œβ”€β”€ HistoryListModel.cpp/.h    # Qt model for the popup
β”‚   β”‚   β”œβ”€β”€ HistoryManager.cpp/.h      # History coordination
β”‚   β”‚   β”œβ”€β”€ HotkeyManager.cpp/.h      # X11 global hotkey
β”‚   β”‚   β”œβ”€β”€ InputSimulator.cpp/.h      # Synthetic paste (XTest)
β”‚   β”‚   β”œβ”€β”€ Logger.cpp/.h             # Logging
β”‚   β”‚   β”œβ”€β”€ SettingsManager.cpp/.h    # App settings
β”‚   β”‚   └── SyncEngine.cpp/.h         # Multi-device sync
β”‚   └── ui/
β”‚       β”œβ”€β”€ PopupController.cpp/.h     # Popup window logic
β”‚       β”œβ”€β”€ SettingsDialog.cpp/.h      # Settings UI
β”‚       └── TrayController.cpp/.h      # System tray
β”œβ”€β”€ CMakeLists.txt               # Build system
β”œβ”€β”€ LICENSE                      # MIT License
└── README.md                    # This file

Technology Stack

Component Technology
Language C++20
GUI Framework Qt 6.4+ (Widgets + QML)
Build System CMake 3.24+
Database SQLite (via Qt6::Sql)
Global Hotkey X11 XGrabKey passive grab
Paste Simulation X11 XTest XTestFakeKeyEvent
Focus Tracking EWMH _NET_ACTIVE_WINDOW
Packaging CPack DEB generator
CI/CD GitHub Actions

🚒 GitHub Actions CI/CD

Every push to main, beta, or alpha triggers a 3-job automated pipeline:

  1. Prepare β€” determines version, generates changelog, pushes git tag
  2. Build matrix β€” 5 parallel builds across distros and architectures
  3. Release β€” collects all packages and publishes the GitHub Release

Package matrix (5 artefacts per release):

Format Target Distros amd64 / x86_64 arm64 / aarch64
.deb Ubuntu 22.04+, Debian, Mint, Pop!_OS βœ“ β€”
.rpm Fedora 37+, openSUSE, RHEL, AlmaLinux βœ“ βœ“
.tar.gz Arch Linux, generic / other distros βœ“ βœ“

Branch β†’ Release channel mapping:

Branch Channel Version Example Pre-release?
main Stable v0.1.0 No
beta Beta v0.1.0-beta.3 Yes
alpha Alpha v0.1.0-alpha.7 Yes

See .github/workflows/release.yml for the full workflow.


🀝 Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a branch for your feature or fix:
    git checkout -b feat/my-feature
  3. Make your changes and test locally
  4. Commit using conventional commits:
    git commit -m "feat: add dark theme support"
    git commit -m "fix: resolve paste delay on KDE"
  5. Push and open a Pull Request

What to commit

Commit Don't commit
Source code (src/) build/ directory
QML files (resources/qml/) cmake-build-*/
Icons (assets/) _CPack_Packages/
Packaging scripts (packaging/) *.deb files
CMakeLists.txt, README.md, .gitignore, LICENSE *.sqlite, *.log
GitHub workflows (.github/) Editor temp files (*.swp, *~)

πŸ”§ Troubleshooting

Ctrl+Super+V does not open the popup
  • The global hotkey requires an X11 session. It will not work on pure Wayland.
  • Another application may have already grabbed this shortcut. Check your desktop environment's keyboard settings.
  • Workaround: Use the tray icon menu, or bind a custom shortcut to:
    clip-stacker --toggle-popup
The app does not paste automatically after selecting an item
  • Automatic paste requires X11 XTest support.
  • On Wayland, clip-stacker copies the item to your clipboard, but you need to press Ctrl+V manually.
  • Some sandboxed applications (Flatpak/Snap) may block synthetic input.
I see generated files in git status

These are build artifacts. Make sure your .gitignore is up to date:

git checkout -- .gitignore
git clean -fd build/ _CPack_Packages/
The tray icon does not appear
  • Make sure your desktop environment supports the system tray (also called the notification area or status notifier).
  • On GNOME, install the AppIndicator extension.
  • On KDE, the tray should work out of the box.
Build fails with missing Qt modules

Install all required dependencies for your distribution. See Build From Source for distribution-specific commands.


πŸ”’ Privacy & Security

  • All data stays local. Clipboard history is stored in a SQLite database on your machine.
  • No network calls. clip-stacker does not phone home, send telemetry, or contact any server.
  • Sensitive content handling. The app uses heuristics to detect sensitive content (e.g., passwords) and can skip storing them.
  • Sync is opt-in. Shared-folder sync only exports non-sensitive entries and is entirely local (no cloud).
  • Logs and databases are runtime artifacts stored locally and are excluded from Git via .gitignore.

πŸ“„ License

This project is licensed under the MIT License. See LICENSE for details.


Made with ❀️ for the Linux desktop

About

A Linux clipboard manager built with C++ and Qt 6, featuring global hotkeys, clipboard history, system tray integration, and fast auto-paste into the active window.

Topics

Resources

License

Stars

Watchers

Forks

Contributors