From copyq-scripting
Create, rename, reorder, and remove CopyQ tabs; move or copy items between tabs; deduplicate; pin items; and clear history selectively. Use when organising clipboard history into named buckets (Links, Snippets, Code, etc.) or doing bulk cleanup.
npx claudepluginhub danielrosehill/claude-code-plugins --plugin copyq-scriptingThis skill uses the workspace's default tool permissions.
CopyQ organises clipboard history into tabs. The default tab is `&clipboard`. Additional tabs are user-created and persist across restarts.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
CopyQ organises clipboard history into tabs. The default tab is &clipboard. Additional tabs are user-created and persist across restarts.
copyq tab # list tabs
copyq addTab "Links"
copyq addTab "Snippets"
copyq renameTab "Old" "New"
copyq removeTab "Links" # confirms via GUI; use eval to bypass
Bypass GUI confirmation when scripting:
copyq eval -- 'removeTab("Links")'
Every CLI subcommand can be prefixed with tab NAME:
copyq tab "Snippets" add "my snippet"
copyq tab "Snippets" count
copyq tab "Snippets" read 0
Inside scripting:
tab('Snippets'); // changes the *current* tab for this script
add('item');
copyq add "single item"
copyq add "item 1" "item 2" "item 3" # appends to top
copyq tab "Notes" add "scoped to Notes"
# Add with explicit MIME (e.g. HTML)
copyq write 0 text/html "<b>bold</b>" text/plain "bold"
No native "move" subcommand — script it:
# Move row 5 from current tab to "Archive"
copyq eval -- '
var item = getItem(5);
tab("Archive");
var n = count();
setItem(n, item); // append to Archive
tab(""); // back to default
remove(5);
'
For copy (don't remove from source):
copyq eval -- '
var item = getItem(0);
tab("Snippets");
setItem(count(), item);
'
copyq remove 0 # top item
copyq remove 0 1 2 # multiple rows
copyq eval -- '
// Remove rows matching a regex
for (var i = count() - 1; i >= 0; i--) {
if (str(read(i)).match(/^DRAFT:/)) remove(i);
}
'
Iterate descending when removing — removing row N shifts higher rows down by one.
copyq eval -- '
while (count() > 0) remove(0);
'
Or clear all tabs:
copyq eval -- '
var ts = tabs();
for (var ti = 0; ti < ts.length; ti++) {
tab(ts[ti]);
while (count() > 0) remove(0);
}
'
copyq eval -- '
var seen = {};
for (var i = count() - 1; i >= 0; i--) {
var t = str(read(i));
if (seen[t]) remove(i);
else seen[t] = true;
}
'
CopyQ supports pinning via the GUI (right-click → Pin). From script:
copyq eval -- '
setItem(0, Object.assign(getItem(0), {"application/x-copyq-pinned": ""}));
'
Pinned items are skipped by maxitems eviction.
copyq select 5 # moves row 5 to top of tab (row 0)
For arbitrary moves, getItem + remove + setItem at target row.
copyq eval -- '
var ts = tabs();
for (var i = 0; i < ts.length; i++) {
tab(ts[i]);
print(ts[i] + ": " + count() + " items\n");
}
'