clipse-demo.mp4
If moving to a new release of clipse
please review the changelog.
clipse
is a configurable, TUI-based clipboard manager application written in Go with minimal dependency. Though the app is optimized for a Linux OS using a dedicated window manager, clipse
can also be used on any Unix-based system. Simply install the package and bind the open command to get your desired clipboard behavior. Further instructions for setting this up can be found below.
This requires a system clipboard. I would recommend using wl-clipboard
(Wayland) or xclip
(X11/macOs) to get the best results. You can also use xsel
and termux-clipboard
, but these will not allow you to copy images.
Does not require any additional dependency, but may require you to use a terminal environment that's compatible with termenv.
- Persistent history
- Supports text and image
- Customizable UI theme
- Customizable file paths
- Customizable maximum history limit
- Filter items using a fuzzy find
- Image and text previews
- Mult-selection of items for copy and delete operations
- Bulk copy all active filter matches
- Pin items/pinned items view
- Vim-like keybindings for navigation available
- Run on any Unix machine with single binary for the clipbboard monitor and TUI
- Optional duplicates
- Ability to set custom key bindings
A customizable TUI allows you to easily match your system's theme. The app is based on your terminal's theme by default but is editable from a custom_theme.json
file that gets created when the program is run for the first time. See the library for some example themes to give you inspiration.
An example custom_theme.json
file:
{
"UseCustom": true,
"TitleFore": "#ffffff",
"TitleBack": "#6F4CBC",
"TitleInfo": "#3498db",
"NormalTitle": "#ffffff",
"DimmedTitle": "#808080",
"SelectedTitle": "#FF69B4",
"NormalDesc": "#808080",
"DimmedDesc": "#808080",
"SelectedDesc": "#FF69B4",
"StatusMsg": "#2ecc71",
"PinIndicatorColor": "#FFD700",
"SelectedBorder": "#3498db",
"SelectedDescBorder": "#3498db",
"FilteredMatch": "#ffffff",
"FilterPrompt": "#2ecc71",
"FilterInfo": "#3498db",
"FilterText": "#ffffff",
"FilterCursor": "#FFD700",
"HelpKey": "#999999",
"HelpDesc": "#808080",
"PageActiveDot": "#3498db",
"PageInactiveDot": "#808080",
"DividerDot": "#3498db",
"PreviewedText": "#ffffff",
"PreviewBorder": "#3498db",
}
You can also easily specify source config like custom paths and max history limit in the apps config.json
file. For more information see Configuration section.
The clipse
binary, installable from the repository, can run on pretty much any Unix-based OS, though currently optimized for Linux. Being terminal-based also allows for easy integration with a window manager and configuration of how the TUI behaves. For example, binding a floating window to the clipse
command as shown at the top of the page using Hyprland window manager on NixOs.
Note that working with image files will require one of the following dependencies to be installed on your system:
- Linux (X11) & macOS: xclip
- Linux (Wayland): wl-clipboard
See below for instructions on getting clipse installed and configured effectively.
Due to how irregularly the stable branch of Nixpkgs is updated, you may find the unstable package is more up to date. The Nix package for clipse
can be found here
Direct install
nix-env -iA nixpkgs.clipse # OS == NixOs
nix-env -f channel:nixpkgs -iA clipse # OS != NixOs
Nix shell
nix shell -p clipse
System package
environment.systemPackages = [
pkgs.clipse
];
If building clipse
from the unstable branch as a system package, I would suggest referencing this article for best practice. The derivation can also be built from source using the following:
{ lib
, buildGoModule
, fetchFromGitHub
}:
buildGoModule rec {
pname = "clipse";
version = "1.1.0";
src = fetchFromGitHub {
owner = "savedra1";
repo = "clipse";
rev = "v${version}";
hash = "sha256-Kpe/LiAreZXRqh6BHvUIn0GcHloKo3A0WOdlRF2ygdc=";
};
vendorHash = "sha256-Hdr9NRqHJxpfrV2G1KuHGg3T+cPLKhZXEW02f1ptgsw=";
meta = {
description = "Useful clipboard manager TUI for Unix";
homepage = "https://github.com/savedra1/clipse";
license = lib.licenses.mit;
mainProgram = "clipse";
maintainers = [ lib.maintainers.savedra1 ];
};
}
Thank you @raininja for creating and maintaining the AUR package!
Installing with yay
yay -S clipse
Installing from pkg source
git clone https://aur.archlinux.org/clipse.git && cd clipse && makepkg -si
Thank you @RadioAndrea for creating and maintaining the COPR package!
dnf copr enable azandure/clipse
Linux arm64
wget -c https://github.com/savedra1/clipse/releases/download/v1.1.0/clipse_1.1.0_linux_arm64.tar.gz -O - | tar -xz
Linux amd64
wget -c https://github.com/savedra1/clipse/releases/download/v1.1.0/clipse_1.1.0_linux_amd64.tar.gz -O - | tar -xz
Linux 836
wget -c https://github.com/savedra1/clipse/releases/download/v1.1.0/clipse_1.1.0_linux_836.tar.gz -O - | tar -xz
Darwin arm64
wget -c https://github.com/savedra1/clipse/releases/download/v1.1.0/clipse_1.1.0_darwin_arm64.tar.gz -O - | tar -xz
Darwin amd64
wget -c https://github.com/savedra1/clipse/releases/download/v1.1.0/clipse_1.1.0_darwin_amd64.tar.gz -O - | tar -xz
go install github.com/savedra1/[email protected]
git clone https://github.com/savedra1/clipse
cd clipse
go mod tidy
go build -o clipse
As mentioned earlier, to get the most out of clipse
, it's recommended to bind the two primary key commands to your system's config. The first key command is to open the clipboard history TUI:
clipse
The second command doesn't need to be bound to a key combination, but rather to the system boot to run the background listener on start-up:
clipse -listen
The above command creates a nohup
process of clipse --listen-shell
, which if called on its own will start a listener in your current terminal session instead. If nohup
is not supported on your system, you can use your preferred method of running clipse --listen-shell
in the background instead.
Note: The following examples are based on bash/zsh shell environments. If you use something else like foot
or fish
, you may need to construct the command differently, referencing the relevant documentation.
Add the following lines to your Hyprland config file:
exec-once = clipse -listen # run listener on startup
windowrulev2 = float,class:(clipse) # ensure you have a floating window class set if you want this behavior
windowrulev2 = size 622 652,class:(clipse) # set the size of the window as necessary
bind = SUPER, V, exec, <terminal name> --class clipse -e 'clipse'
# Example: bind = SUPER, V, exec, alacritty --class clipse -e 'clipse'
Add the following commands to your ~/.config/i3/config
file:
exec --no-startup-id clipse -listen # run listener on startup
bindsym $mod+V exec --no-startup-id urxvt -e "$SHELL" -c "i3-msg 'floating enable' && clipse" # Bind floating shell with TUI selection to something nice
Add the following config to your ~/.config/sway/config
file:
exec clipse -listen # run the background listener on startup
bindsym $mod+V exec <terminal name> -e sh -c "swaymsg floating enable, move position center; swaymsg resize set 80ppt 80ppt && clipse" # Bind floating shell with TUI selection to something nice
The native terminal on MacOs will not close once the clipse
program completes, even when using the -fc
argument. You will therefore need to use a different terminal environment like Alacritty to achieve the "close on selection" effect. The bindings used to open the TUI will then need to be defined in your settings/window manager.
Every system/window manager is different and hard to determine exactly how to achieve the more ‘GUI-like’ behavior. If using something not mentioned above, just refer to your systems documentation to find how to:
- Run the
clipse -listen
/clipse --listen-shell
command on startup - Bind the
clipse
command to a key that opens a terminal session (ideally in a window)
If you're not calling clipse
with a command like exec <terminal name> -e sh -c
and want to force the terminal window to close on selection of an item, use the -fc
arg to pass in the $PPID
variable so the program can force kill the shell session. EG clipse -fc $PPID
. Note that the $PPID variable is not available in every terminal environment, like fish terminal where you'd need to use $fish_pid instead.
The configuration capabilities of clipse
will change as clipse
evolves and grows. Currently, clipse supports the following configuration:
- Setting custom paths for:
- The clipboard history file
- The clipboard binaries directory (copied images and other binary data is stored in here)
- The debug log file
- The clipboard UI theme file
- Setting a custom max history limit
- Custom themes
- If duplicates are allowed
- Setting custom key bindings
- Image display mode
clipse
looks for a base config file in $CONFIG_DIR/clipse/config.json
($CONFIG_DIR
being $XDG_DATA_HOME
or $HOME/.config
), and creates a default file if it does not find anything. The default config looks like this:
{
"historyFile": "clipboard_history.json",
"maxHistory": 100,
"allowDuplicates": false,
"themeFile": "custom_theme.json",
"tempDir": "tmp_files",
"logFile": "clipse.log",
"keyBindings": {
"choose": "enter",
"clearSelected": "S",
"down": "down",
"end": "end",
"filter": "/",
"home": "home",
"more": "?",
"nextPage": "right",
"prevPage": "left",
"preview": "t",
"quit": "q",
"remove": "x",
"selectDown": "ctrl+down",
"selectSingle": "s",
"selectUp": "ctrl+up",
"togglePin": "p",
"togglePinned": "tab",
"up": "up",
"yankFilter": "ctrl+s"
},
"imageDisplay": {
"type": "basic",
"scaleX": 9,
"scaleY": 9,
"heightCut": 2
}
}
Note that all the paths provided (the theme, historyFile
, and tempDir
) are all relative paths. They are relative to the location of the config file that holds them. Thus, a file config.json
at location $HOME/.config/clipse/config.json
will have all relative paths defined in it relative to its directory of $HOME/.config/clipse
.
Absolute paths starting with /
, paths relative to the user home dir using ~
, or any environment variables like $HOME
and $XDG_CONFIG_HOME
are also valid paths that can be used in this file instead.
Currently these are the supported options for imageDisplay.type
:
basic
kitty
sixel
The scaleX
and scaleY
options are the scaling factors for the images. Depending on the situation, you need to find suitable numbers to ensure the images are displayed correctly and completely. You can make adjustments based on this implementation.
clipse
is more than just a TUI. It also offers a number of CLI commands for managing clipboard content directly from the terminal.
# Operational commands
clipse -a <arg> # Adds <arg> directly to the clipboard history without copying to system clipboard (string
clipse -a # Adds any standard input directly to the clipboard history without copying to the system clipboard.
# For example: echo "some data" | clipse -a
clipse -c <arg> # Copy the <arg> to the system clipboard (string). This also adds to clipboard history if currently listening.
clipse -c # Copies any standard input directly to the system clipboard.
# For example: echo "some data" | clipse -c
clipse -p # Prints the current clipboard content to the console.
# Example: clipse -p > file.txt
# TUI management commands
clipse # Open Clipboard TUI in persistent/debug mode
clipse -fc $PPID # Open Clipboard TUI in 'force kill' mode
clipse -listen # Run a background listener process
clipse --listen-shell # Run a listener process in the current terminal (useful for debugging)
clipse -help # Display menu option
clipse -v # Get version
clipse -clear # Wipe all clipboard history except for pinned items
clipse -clear-images # Wipe all images from the history
clipse -clear-text # Wipe all text items from the clipboard history
clipse -clear-all # Wipe entire clipboard history
clipse keep # Keep the TUI open after selecting an item to copy (useful for debugging)
clipse -kill # Kill any existing background processes
You can also view the full list of TUI key commands by hitting the ?
key when the clipse
UI is open.
When the app is run for the first time it creates a /home/$USER/.config/clipse
dir containing config.json
, clipboard_history.json
, custom_theme.json
and a dir called tmp_files
for storing image data. After the clipse -listen
command is executed, a background process will be watching for clipboard activity and adding any changes to the clipboard_history.json
file, unless a different path is specified in config.json
.
The TUI that displays the clipboard history with the defined theme should then be called with the clipse
command. Operations within the TUI are defined with the BubbleTea framework, allowing for efficient concurrency and a smooth UX. delete
operations will remove the selected item from the TUI view and the storage file, select
operations will copy the item to the systems clipboard and exit the program.
The maximum item storage limit defaults at 100 but can be customized to anything you like in the config.json
file.
I would love to receive contributions to this project and welcome PRs from everyone. The following is a list of example future enhancements I'd like to implement:
-
Image previews in TUI view -
Pinned items -
Warn on deleting pinned items -
Color theme customizations for all UI elements - Customizations for:
-
max history limit -
config file paths -
Duplicates allowed -
key bindings -
image preview display render type
-
-
Option to disable duplicate items - Auto-forget based on where the text was copied
-
Multi-select feature for copying multiple items at once - Categorized pinned items with potentially different tabs/views
- System paste option (building functionality to paste the chosen item directly into the next place of focus after the TUI closes)
- Packages for:
- apt
-
dnf - brew
- other
- Theme/config adjustments made available via CLI
- Your custom theme for the library
- debug mode (eg
clipse --debug
/ debug file / system alert on panic) - Cross compile binaries for
wl-clipboard
/xclip
to remove dependency - TUI / theming enhancements:
-
Menu theme -
Filter theme -
Clear TUI view on select and close (mirror close effect fromq
oresc
)
-
- Private mode (eg
clipse --pause 1
)
Clipse crashes when I enter certain characters into the search bar
See issue #148. This is caused by the fuzzy find algo (within the BubbleTea TUI framework code) crashing when it encounters non-compatible characters in the history file, such as an irregular image binary pattern or a rare non-ascii text character. The fix is to to remove the clipboard entry that contains the problematic character. I would recommend pinning any items you do not want to lose and running clipse -clear
.
My terminal window does not close on selection, even when using clipse -fc $PPID
Some terminal environments reference system variables differently. For example, the fish terminal will need to use $fish_pid
instead. To debug this error you can run echo $PPID
to see what gets returned. To get the "close on selection" effect for macOs, you will need to install a different terminal environment like Alacritty
._
Is there risk of multiple parallel processes running?
No. The clipse
command kills any existing TUI processes before opening up and the clipse -listen
command kills any existing background listeners before starting a new one.
High CPU usage?
When an image file has an irregular binary data pattern it can cause a lot of strain on the program when clipse
reads its history file (even when the TUI is not open). If this happens, you will need to remove the image file from the TUI or by using clipse -clear-images
. See issue #33 for an example.
My copied entries are not recorded when starting the clipse listener on boot with a systemd service
There may be a few ways around this but the workaround discovered in issue #41 was to use a .desktop
file, stored in ~/.config/autostart/
. Eg:
[Desktop Entry]
Name=clipse
Comment=Clipse event listener autostart.
Exec=/home/usrname/Applications/bin/clipse/clipse_1.1.0_linux_amd64/clipse --listen %f
Terminal=false
Type=Application
Copying images from a browser does not work correctly
Depending on the clipboard utility you are using (wl-clipboard
/xclip
etc) the data sent to the system clipboard is read differently when copying from browser locations.
If using wayland
, copying images from your browser should now work from most sites if using v1.0.4
or later. This may copy the binary data as well as the metadata sting as a separate entry. Some sites/browsers may add the browser image data to the stdin in a way that wl-clipboard
does not recognize.
If using x11
, MacOs
or other and copying browser images does not work, feel free to raise and issue (or a PR) detailing which sites/browser engines this does not work with for you.