sentriz / cliphist Goto Github PK
View Code? Open in Web Editor NEWwayland clipboard manager with support for multimedia
License: GNU General Public License v3.0
wayland clipboard manager with support for multimedia
License: GNU General Public License v3.0
cliphist won't preserve the clipboard after the copy source is closed unless the picker is run
for example, I copied text from Brave Browser, and then closed it, and tried to paste, and no data was pasted.
it works if I open the picker first though...
am I just launching it wrong or something or is this a new feature?
i launch it like this:
wl-paste --watch cliphist store
On sway cliphists rocks with wl-clipboard.
On i3 I currently configured greenclip.
Is this project works only with wl-clipboard / other wl based protocols ? Or can the command be piped properly to support x11/xclip too ?
I have tried these so far just for curiosity:
cliphist list | rofi -dmenu | cliphist decode | xclip -selection c -
xclip -selection c $(cliphist list | rofi -dmenu | cliphist decode)
dumbly without any luck.
When I trigger it like this:
$ rofi -modi clipboard:/home/stratos/dotfiles/bin/wayland_cliphist_images.sh -show clipboard -show-icons
grep: (standard input): binary file matches
I get the above grep message on the console and an empty rofi window.
My partial cliphist list
shows this:
$ cliphist list
201 rofi -modi clipboard:/home/stratos/dotfiles/bin/wayland_cliphist_images.sh -show clipboard -show-ic
200 cliphist-rofi-img
199 cliphist list \ | grep -Fv '<meta http-equiv="content-type"'
198 #!/usr/bin/env bash tmp_dir="/tmp/cliphist" rm -rf "$tmp_dir" if [[ -n "$1" ]]; then cliphist dec
197 binary data image/png
196 SN850X
There is one image copied in there
Am I "holding it wrong"?
BTW, I use:
wl-paste --watch cliphist store
to copy items to my clipboard (running in hyprland)
EDITED: To replace wayland with hyprland!
Hi again. Can we have (or maybe we already have?) a way to paste the previous (or prior to last) clipboard entry, without launching the picker? I have little knowledge of how the clipboard works, but I guess it would involve piping this item to wl-paste
?... Thank you!
After performing cliphist wipe
, enumeration continues from the last number rather than resetting.
When I take a screenshot and attempt to go to it with "cliphist list | tofi | cliphist decode | wl-copy
" wl-paste reports that it's text/plain, I can't figure out why
wl-paste -l
text/plain
text/plain;charset=utf-8
TEXT
STRING
UTF8_STRINGh
I have
exec wl-paste --watch cliphist store
exec wl-paste --type image --watch cliphist store
in my sway config, any advice?
I suddenly start getting a:
❯ cliphist list
panic: runtime error: slice bounds out of range [::3771442824] with length 2147483647
goroutine 1 [running]:
go.etcd.io/bbolt.unsafeByteSlice(...)
go.etcd.io/[email protected]/unsafe.go:27
go.etcd.io/bbolt.(*leafPageElement).value(...)
go.etcd.io/[email protected]/page.go:143
go.etcd.io/bbolt.(*Cursor).keyValue(0xc000069e50?)
go.etcd.io/[email protected]/cursor.go:374 +0x172
go.etcd.io/bbolt.(*Cursor).Last(0xc000069e50)
go.etcd.io/[email protected]/cursor.go:82 +0x18a
main.list(0x1?, {0x55cbb70a9cf8, 0xc000012018})
go.senan.xyz/cliphist/cliphist.go:226 +0x105
main.glob..func2({0x55cbb7094d40?, 0xc0001101b0?, 0x7ffdff9c008c?})
go.senan.xyz/cliphist/cliphist.go:73 +0xc5
main.main()
go.senan.xyz/cliphist/cliphist.go:42 +0x149
that I do not know how to debug.
I thought some items in the history might trigger it, but trying to wipe all fails again:
❯ cliphist wipe
panic: runtime error: slice bounds out of range [::3771442824] with length 2147483647
goroutine 1 [running]:
go.etcd.io/bbolt.unsafeByteSlice(...)
go.etcd.io/[email protected]/unsafe.go:27
go.etcd.io/bbolt.(*leafPageElement).value(...)
go.etcd.io/[email protected]/page.go:143
go.etcd.io/bbolt.(*node).read(0xc001579d50, 0x7fbe4dbe6000)
go.etcd.io/[email protected]/node.go:172 +0x374
go.etcd.io/bbolt.(*Bucket).node(0xc000112140, 0x8?, 0xc001578000)
go.etcd.io/[email protected]/bucket.go:680 +0x1a5
go.etcd.io/bbolt.(*node).childAt(0xc001578000?, 0x1?)
go.etcd.io/[email protected]/node.go:77 +0x45
go.etcd.io/bbolt.(*Cursor).node(0xc000104db0?)
go.etcd.io/[email protected]/cursor.go:393 +0xc7
go.etcd.io/bbolt.(*Bucket).Delete(0xc000112140, {0x7fbe4dbe6050, 0x8, 0x8})
go.etcd.io/[email protected]/bucket.go:332 +0xf5
main.wipe(0x0?)
go.senan.xyz/cliphist/cliphist.go:318 +0x165
main.glob..func6({0x55b3bc999d40?, 0xc0001081b0?, 0x7ffc3684608c?})
go.senan.xyz/cliphist/cliphist.go:132 +0xb4
main.main()
go.senan.xyz/cliphist/cliphist.go:42 +0x149
So I am stuck.
Running under latest version of hyprland on latest arch. Not sure what other dbug info you might need.
Thanks!
OS: Arch Linux
WM: wayfire, sway
Cliphist version: 0.3.0
How to reproduce:
Executing cliphist list | bemenu | cliphist delete
more than once/several times (via keybinding) will freeze bemenu
.
Haven't tried piping cliphist
into a different menu implementation...
Anyway, thanks for this little clipboard helper!
cliphist provokes this command to fail (returns No selection)
echo test | wl-copy --paste-once
wl-paste
When cliphist is stopped, the commands work as expected .
This issue provoke some applications to not work correctly (swayshot).
See full discusion here.
Good morning? evening? I don't really know.
Anyway, Could it be possible to add the vendor directory either in the the git itself or in a tarball for all release ?
I am asking because over on Gentoo, we need to have the Go dependencies bundled with the source. As such I created this repo with the only change being adding vendor and removing .github.
If you can not do it, it's no bother.
Copying an image from the web and running
$ wl-paste -l
image/png
text/html
text/x-moz-url
And after re-copying it from cliphist
$ wl-paste -l
text/plain
text/plain;charset=utf-8
TEXT
STRING
UTF8_STRING
It only seems to preserve the text/html
part of the clipboard.
It would be very nice if cliphist managed to keep all the properties, meaning we could copy old images from the web from the history.
Thank you for the nice software so far :)
keepassxreboot/keepassxc#10233 (comment)
Code snippet from keepassxc
mime->setData("x-kde-passwordManagerHint", QByteArrayLiteral("secret"));
hi !
corrently i use x11 with dwm to sync both clipboards:
autocutsel -fork -selection CLIPBOARD &
autocutsel -fork -selection PRIMARY &
Is this possible also with cliphist in wayland ?
currently i use this line to start cliphist:
wl-paste --watch cliphist store &
to show clipboard i use this line:
cliphist list | rofi -dmenu -p Clipboard | cliphist decode | wl-copy
thanks !
cliphist wipe
doesn't reset the count.
While rofi doesn't support variable-height elements, a fixed value can be specified with -eh
. It would be really nice if multi-line content took advantage of this.
This could be implemented as a dmenu
using -drun-display-format "{<row1>}$'\n'{<row2>}"
, but cliphist list
probably(?) needs to be decoded first
I'm using cliphist with dmenu and functionally it is perfect. I just have one cosmetic issue, which is a little square that appears to the right of the history item number, as seen in this screenshot.
I've tried different fonts (as in dmenu -fn Hack
) and no luck getting rid of the square. Do you know what that square is doing there, and if it is possible to remove it?
previously, I used this to limit history to 1000 lines
clipman pick --max-items=1000 -t rofi
But, I don't find any option to control history count in cliphist
something like this would be very useful
cliphist list --max-items=1000 | rofi -dmenu | cliphist decode | wl-copy
As in rofi's -display-columns _n_
option?
Example: cliphist list | tofi -display-columns 2 | cliphist decode | wl-copy
would only show me the second column of the cliphist
output. This is useful because the first column is a number that has little utility for the human user.
Is this possible with cliphist to save last copied item so that we do not need to re-copy it again from history?
I'd like the db to live in memory, rather than needing to worry about wiping it. Is it possible to specify the location of the DB with either an env var or an option?
If not maybe you would be open to adding this as a feature?
Either way thank you for this tool!
I simply run cliphist list
in terminal whenever I need to access some previously copied short text. But currently the newest items are way above, requiring a scroll. Maybe it wouldn't be a problem to implement an alternative "list", which would show newest entries at the bottom?
Thanks!
I am trying to get cliphist to delete an item in the list from a menu selection and I am hoping someone can help.
I have tried:
cliphist list | rofi -dmenu | cliphist delete
but it says: "please provide a delete query" so instead I tried
cliphist list | rofi -dmenu > cliphist delete
The command doesn't give an error but it doesn't remove the item.
Any help would be great.
Thanks.
Use case: I would like to be able to delete many entries in cliphist
without wiping all the entries. The entries I want to delete are not related in their contents, so delete-query
isn't suitable for the job. This would be particularly useful for use with pickers that support selecting multiple items.
Potential implementations:
delete
so that when it takes os.Stdin
, iterate over the lines (assuming each entry one wants to delete is on a newline, which is at least how rofi
returns row selections) and try to delete each (i.e., attempt ID extraction, go from there). One can probably batch the database operations or at least reuse the same session/connection/whatever?Alternatives:
Is there any interest in contributions that would satisfy this use-case? If so, would you prefer any particular implementations? Do you think this functionality would be a good addition to the core of cliphist
(i.e., not a script/contrib)?
Thanks for your work and time <3
I run cliphist as a systemd user service started after a sway session target:
[Unit]
Description=wayland clipboard manager
BindsTo=sway-session.target
[Service]
Type=simple
ExecStart=/usr/bin/wl-paste --watch cliphist store
[Install]
WantedBy=sway-session.target
When I suspend my laptop and resume it later, cliphist (or wl-paste?) will not register new clipboard entries until I restart the unit.
Is this known behaviour of wl-paste? Should one configure systemd to restart it after suspend?
Hey. I have been looking for a clipboard manager for Wayland and noticed this project. It looks great! Though I have been having some trouble getting it to work right in my Sway config. I am guessing this is operator error on my part, but I wanted to reach out just to make sure.
I installed cliphist
via Go.
My Sway config then had the following added
# Clipboard
bindsym $mod+Shift+v exec "cliphist list | wofi --dmenu | cliphist decode | wl-copy"
…
exec --no-startup-id swaymsg 'workspace 1; wl-paste --type text --watch cliphist store &' #Stores only text data
exec --no-startup-id swaymsg 'workspace 1; wl-paste --type image --watch cliphist store &' #Stores only image data
However whenever I do $mod+Shift+v
I get the following screen even when the clipboard has values:
But when I run cliphist list | wofi --dmenu | cliphist decode | wl-copy
from a terminal I get the following:
Any ideas what I might be doing wrong?
The following scripts support:
They do not support informing cliphist about the mime type; they are also a bit inefficient as many commands are started to make this setup work. A pure go/rust solution might be better suited for efficiency.
#! /bin/bash
# This script is designed to preserve the exact contents of th
# A note about newline preserving string handling in bash
#
# $ mycommand <<< "${foo}" – # appends a newline
# $ echo -n "${foo}" | mycommand # preserves newline
# $ foo="$(cat)" # preserves newline
# $ foo="$(</dev/stdin)" # preserves newline
# $ $'\n' # String literal with explicit newline handling
# $ LF=$'\n' # Line feed (newline) as a variable
# $ "${LF}" # Regular string literal with newlines
# $ wl-copy -n # trims newlines - DOES NOT PRESERVE NEWLINES
# $ wl-copy # preserves newlines
# $ wl-paste -n # preserves newlines
# $ wl-paste # adds a newline - DOES NOT PRESERVE NEWLINES
set -e
SCRIPT_SOURCE="$0"
DEBUG="falsfalse"
LF=$'\n'
log() {
echo >&2 "$@"
}
dbg() {
if check "${DEBUG}"; then
log "$@"
fi
}
show_newlines() {
printf "%q" "$1"
}
exc() {
if check "${DEBUG}"; then
local stdin; stdin="$(cat)"
log -e "$ $*\n< $(show_newlines "${stdin}")"
echo -n "${stdin}" | "$@"
else
"$@"
fi
}
panic() {
log "Panic:" "$@"
exit 1
}
bool() {
if "$@"; then
echo true
else
echo false
fi
}
check() {
test "$1" = "true"
}
cmd_sync_write() {
local src_args; src_args=()
local dst_args; dst_args=()
local remember; remember="false"
local primary; primary="false"
while (( "$#" > 0 )); do
case "$1" in
"--primary") # Write to primary selection
primary="true"
;;
"--remember") # Notify cliphist
remember="true"
;;
*)
panic "Unknown sync parameter: $1"
esac
shift
done
if check "${primary}"; then
dst_args+=("--primary")
else
src_args+=("--primary")
fi
local nu; nu="$(</dev/stdin)"
local nu_mime; nu_mime="$(wl-paste --list "${src_args[@]}" | head -n1)"
local cur; cur="$(wl-paste -n "${dst_args[@]}")"
local cur_mime; cur_mime="$(wl-paste --list "${dst_args[@]}" | head -n1)"
local novel; novel="$(bool test "${nu}" != "${cur}" -o "${nu_mime}" != "${cur_mime}")"
if check "${DEBUG}"; then
dbg "sync_write!" \
"remember=${remember}" \
"novel=${novel}" \
"primary=${primary}" \
"nu=${nu_mime}:$(show_newlines "${nu}")" \
"cur=${cur_mime}:$(show_newlines "${cur}")" \
-- src_args = "${src_args[@]}" \
-- dst_args = "${dst_args[@]}" \
-- '$@' = "$@"
fi
# Send clipboard data to cliphist
if check "${remember}"; then
# TODO: Support mime
echo -n "${nu}" | exc cliphist store
fi
# Avoid infinite update loops by detecting if the destination clipboard contains the data already
if check "${novel}"; then
echo -n "${nu}" | exc exec wl-copy --type "${nu_mime}" "${dst_args[@]}"
fi
}
cmd_watch() {
if (( "$#" > 1 )); then
panic -e "Spurious arguments: ${*}${LF}Just specify a single argument --primary or --clipboard"
fi
local mode; mode="$1"; shift || panic "Please specify --primary or --clipboard"
local primary; primary="false"
case "${mode}" in
"--primary")
# From primary, to cliboard; to cliphist via the clipboard handler
primary="false"
;;
"--clipboard")
# From clipboard, to primary and cliphist
primary="true"
;;
*)
panic "Unknown mode: ${mode}. Please specify --primary or --clipboard"
esac
local watch_opts; watch_opts=()
local sync_opts; sync_opts=()
if [[ "$primary" = "true" ]]; then
# primary -> clipboard -> cliphist
watch_opts=("--primary" "${watch_opts[@]}")
else
# clipboard -> primary, cliphist
sync_opts=("--remember" "${sync_opts[@]}")
sync_opts=("--primary" "${sync_opts[@]}")
fi
exc exec wl-paste -n "${watch_opts[@]}" -w bash "${SCRIPT_SOURCE}" sync_write "${sync_opts[@]}"
}
main() {
local cmd; cmd="$1"; shift || panic "Specify a command"
if [[ "$cmd" = "sync_write" ]]; then
cmd_sync_write "$@"
elif [[ "$cmd" = "watch" ]]; then
cmd_watch "$@"
else
panic "Unknown command ${cmd}"
fi
}
main "$@"
[Unit]
Description=Cliphist clipboard manager
After=sway.target
Wants=sway.target
Requires=cliphist-watch-primary.service
Requires=cliphist-watch-clipboard.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
[Install]
WantedBy=default.target
[Unit]
Description=Cliphist clipboard manager
PartOf=cliphist.service
ReloadPropagatedFrom=cliphist.service
[Service]
Type=simple
ExecStart=/usr/bin/bash "%Y/cliphist.helper.sh" watch --primary
Restart=always
RestartSec=1
TimeoutStopSec=10
KillMode=mixed
[Unit]
Description=Cliphist clipboard manager
PartOf=cliphist.service
ReloadPropagatedFrom=cliphist.service
[Service]
Type=simple
ExecStart=/usr/bin/bash "%Y/cliphist.helper.sh" watch --clipboard
Restart=always
RestartSec=1
TimeoutStopSec=10
KillMode=mixed
Hi,
Thanks for this project!
I would like to package this for NixOS and it will be really nice to have a proper release with a License.
It would be amazing if cliphist also provided the ability to have a separate db from the cliphist (sniphist?) that was somehow editable (if even only text at first) and allowed one to pull up and filter selections from both multiline text snippets, images etc... in rofi or dmenu.
Basically, think of it as a saved, persistent clipboard of things you often copy-paste. Personally, I've got a heap of these in text like ¯\(ツ)/¯, gpg pub key, etc etc... (plus gif memes would be great as well... =] ).
thanks for considering it either way!
I was using clipman in Swaywm for a while, but I saw your project and decide to try it.
Unfortunately very quickly my bemenu list was full of duplicates(typically for my work).
Is it possible to remove duplicates in output?
I've recently switched to wayland, Hyprland, on arch linux so I'm still looking for x alternative apps and this felt very similar to what I used on x, my fork of clipmenu to support images.
Except, problems in copying images :(
I'm using the fix from #33 (and on the readme)
wl-paste --type text --watch cliphist store
wl-paste --type image --watch cliphist store
when copying an image, there's the html, the actual image, and some gibberish in the history:
❯ cliphist list
157 ftypavifavifmif1miafMA1Bmeta(hdlrpictlibavifpitm
156 binary data image/png
155 <meta http-equiv="content-type" content="text/html; charset=utf-8"><img id="image" class="fit-width"
With only wl-paste --type image --watch cliphist store
there's no gibberish but sometimes there's an extra image (jpeg here) entry, which I can't paste anywhere:
❯ cliphist list
167 binary data image/jpeg
166 binary data image/png
My suspect for the gibberish is copying the same image again, its random but very likely.
It also happens when I copy an image for the first time so not so sure, but it is more likely for it to happen on a second copy.
So my question is, same as issue #33, can I only copy the image and not the html? with text support as well while not copying images...
and, well, can I not get that gibberish? I do not know the source of it so if someone could replicate it, it would be nice to know.
Should I have instead commented on the closed #33? But there's the gibberish too.
I'm new to collaborating on github so dunno. You can close this issue and I'll comment there instead if that's the case :)
On the latest version of the program the wipe command doesn't reset the history counter.
As for now the only option to do it is to delete the db file entirely.
Arch Linux, aur/cliphist package
Instead of having an infinite history, an option to toggle a max length would be pretty nice.
If that certain length is reached, the last entry is cleared to save space.
It should be relatively easy, since 'cliphist delete' already exists.
Is that something you would consider implementing?
I was wondering if you had any idea how I could use rofi instead of dmenu for selection items.
Hi,
I need visual/audio feedback for a successful copy.
In Pano it is supported by default.
In CopyQ I use this script:
copyq:
if ( isClipboard() )
execute('pw-play', '/home/azzamsa/sounds/slick.ogg')
Is this possible with a cliphist?
Any scripting idea?
Thank you for cilphist! 🍨
cliphist list | <picker> --dmenu | cliphist decode | wl-copy
usually invokes the picker & escaping it clears the clipboard. Is there anyway I can modify above command so that clipboard does not clear on quitting the picker without selecting the last clip ?
it would be nice if there was an option to only remember words/phrases that have minimum number of characters.
i can contribute this if this is not already possible
I suggest releasing this package for openSUSE Tumbleweed, I don't think there will be any dependencies problems because openSUSE Tumbleweed is a rolling release distro an it offers a similar service like the AUR of Arch Linux but called openSUSE Build Service.
If it sounds interesing to you maybe is worth taking a look at it. https://build.opensuse.org/
It is pretty annoying to have both html data and the raw image when i copy the image from my browser, is there a way i can possibly blacklist or get rid of that html data entirely and only copy the raw image?
Personally, I don't quite understand the purpose or benefit of seeing the ids next to the copied test. I would just like to see the copied test. Would it be possible to add an option that prints the copied items without the ids? Thanks for the awesome program!
As a user of bemenu
I wish to fit my width screen fully when preview history using cliphist list
command and let bemenu truncate on its own if needed. Something like cliphist list -w 999
. Now the value is hardcoded and equal to 100.
What do you think?
I use KeePassXC as my password manager, but sometimes I need to copy a password out of it. KeePassXC automatically clears the system clipboard after 10 seconds, so the password can't be pasted somewhere by accident. But the password still remains in cliphist's history, which I don't really want. Is there a way to ignore programs like password managers entirely?
How do i use it with rofi?
Is it possible to have video type support?
Running cliphist list | dmenu | cliphist decode | wl-copy
without a selection (i.e. pressing ESC to close dmenu) and pasting afterwards leads to a blank paste.
Since dmenu
returns nothing, cliphost decode
can't find anything, and nothing is passed onto wl-copy hence clearing the current clipboard selction.
To remedy this, I made this tiny helper script. This saves the last output, and in case dmenu
it reverts back to the most recent clipboard entry.
#!/bin/bash
# If $NEW is run, and no selection was made
# pasting would result in an empty string
# This helper script eliminates that
PREVIOUS=$( wl-paste )
NEW=$( cliphist list | dmenu | cliphist decode )
echo $NEW
if [ ! -z "$NEW" -a "NEW" != " " ]; then
echo $NEW | wl-copy
else
echo $PREVIOUS | wl-copy
fi
Is it possible to anchor text so that it stays even after clearing history, as it works in greenclip?
cliphist doesn't seem to store any text with 2 letters or less, for example it doesn't store ab
, but stores emoji and japanese characters just fine.
Hi, were wondering if there were a time metadata associated to each clipboard entry.
I’m not a fan of having my clipboard populated with possible passwords and all.
Currently, I have a timer who will wipe my clipboard every 10 min, but that means that sometimes, the database will be wiped just after I have copied an item, forcing me to copy the item when the paste didn’t work.
Is there a way to set up a wipe for only 10min old entries and plus ? This would mean that each entry will always be available in the database for a set amount of time.
Thank you :D
Are you planning on adding an option to clear the history without having to delete them 1 by 1?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.