- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| cmd/klipdev | ||
| internal | ||
| go.mod | ||
| go.sum | ||
| klip.go | ||
| klip_darwin.go | ||
| klip_linux.go | ||
| klip_windows.go | ||
| README.md | ||
klip
Native clipboard access for Go — Linux (Wayland/X11), macOS, Windows.
Built to actually solve the "copied a password, program exited, clipboard went blank" problem you get on Wayland with most clipboard libraries: on Linux, klip shells out to wl-copy/xclip/xsel, which fork and keep serving the clipboard after your process exits. On macOS it uses pbcopy/osascript; on Windows it talks to the Win32 clipboard API directly. No cgo.
Install
go get plutolab.org/klip
Usage
cb := klip.NewClipboard()
// plain copy
cb.Write(ctx, []byte("hello"), klip.WriteOptions{})
// copy a secret: hint clipboard managers to keep it out of history,
// and clear it after the first paste where supported
cb.Write(ctx, []byte(password), klip.WriteOptions{
Secret: true,
ClearOnPaste: true,
})
// clear now, but only if the clipboard still holds what we wrote
cb.Clear(klip.DirectCompare([]byte(password)))
// clear unconditionally
cb.Clear(klip.Always)
Options
WriteOptions field |
Linux | macOS | Windows |
|---|---|---|---|
Secret (hide from clipboard history) |
wl-copy --sensitive; no-op on xclip/xsel |
org.nspasteboard.ConcealedType/TransientType |
ExcludeClipboardContentFromMonitorProcessing |
ClearOnPaste |
wl-copy --paste-once / xclip -loops 1; no-op on xsel |
not supported | not supported |
ClearOnPaste/paste-once only exists where the OS lets a process serve its own clipboard selection on request (Wayland, X11). macOS and Windows hand clipboard content to the OS immediately, with no way to observe a paste, so there's nothing to hook there.
Clearing on a timeout
klip has no background timer of its own — a library can't safely spawn one that outlives your process without doing something surprising to every program that imports it. Instead:
Clear(cmp ClearComparator) error/ClearAfter(cmp ClearComparator, d time.Duration) error— verify-then-clear, and sleep-then-verify-then-clear. Call these from your own worker process.klip.LaunchDetached(exePath, args, payload) error— spawns that worker as a real detached process (survives your program exiting), deliveringpayloadvia stdin.
Your app registers its own worker entry point (a hidden subcommand, same idea as gopass unclip), calls LaunchDetached right after Write, and has that worker call ClearAfter.
Known gaps
- Linux: KDE's Klipper re-asserts old content after a plain clear. A fix exists (
clearKlipperHistoryininternal/clipboard_linux.go) but isn't wired in yet — it works by wiping Klipper's entire history, not just the one entry, which isn't always the right tradeoff. macOS/Windows: unverified beyond compiling — no Mac/Windows machine in the loop yet.verified now.