A fast, lightweight clipboard manager for Linux desktops
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.
- Features
- How It Works (60-Second Overview)
- Quick Install
- Getting Started
- Keyboard Shortcuts
- Configuration
- Build From Source
- Package as .deb
- Project Architecture
- GitHub Actions CI/CD
- Contributing
- Troubleshooting
- Privacy & Security
- License
| 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 |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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.debFedora / RHEL:
sudo dnf install ./clip-stacker_*_fedora_x86_64.rpmArch 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/hicolorSee Build From Source below.
After installation, start clip-stacker from your application menu or terminal:
clip-stackerA small icon appears in your system tray (notification area).
Copy text, images, files, or rich content normally (Ctrl+C, right-click β Copy, etc.). clip-stacker captures everything automatically in the background.
Press Ctrl+Super+V (Ctrl + Windows key + V). A popup appears near your cursor showing all your recent clips.
Click any item in the popup. clip-stacker will:
- Copy that item to your clipboard
- Close the popup
- Restore focus to the app you were using
- Automatically paste it (
Ctrl+V) into that app
That's it! You now have unlimited clipboard history.
- 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
| 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 |
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/).
Run the included helper script to add clip-stacker to your desktop session's autostart:
/usr/lib/clip-stacker/install-autostart.shOr manually copy the desktop entry:
cp /usr/share/applications/clip-stacker.desktop ~/.config/autostart/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-devFedora (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-develArch Linux:
sudo pacman -S --needed \
base-devel cmake ninja \
qt6-base qt6-declarative qt6-tools qt6-svg qt6-wayland \
libx11 libxtst libxfixes# 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)./build/clip-stacker./packaging/linux/build-deb.shcmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
cpack --config build/CPackConfig.cmake -G DEBOutput: clip-stacker_0.1.0_amd64.deb
Install the generated package:
sudo apt install ./clip-stacker_0.1.0_amd64.debββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 β β
βββββββββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββββββββββββββββ
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
| 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 |
Every push to main, beta, or alpha triggers a 3-job automated pipeline:
- Prepare β determines version, generates changelog, pushes git tag
- Build matrix β 5 parallel builds across distros and architectures
- 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.
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a branch for your feature or fix:
git checkout -b feat/my-feature
- Make your changes and test locally
- Commit using conventional commits:
git commit -m "feat: add dark theme support" git commit -m "fix: resolve paste delay on KDE"
- Push and open a Pull Request
| 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, *~) |
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+Vmanually. - 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.
- 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.
This project is licensed under the MIT License. See LICENSE for details.
Made with β€οΈ for the Linux desktop