The history
Copying
What PasteDaemon keeps when you copy something — text, formatting, files, images and where each came from — what it deliberately does not keep, and how long any of it stays.
Each time something is copied, PasteDaemon stores it as a new entry. Text, images and files copied in Finder are all kept, and the history persists across launches.
An entry is a value plus the history of what that value used to be. Each past value is kept with the time it was set and what set it — a trigger, an action, a variable, or you — and an entry keeps its 20 most recent values.
Entries come in two kinds, which differ only in whether they carry a name. Unnamed entries are the clipboard history. Named ones are variables — which is why a variable can be searched and pasted from the overlay exactly as a copy can.
Copying something the history already holds is a use, not a change: the entry moves to the top without gaining a version, and its timestamp updates. So something you reach for daily never ages out from under your hand.
That means the history holds each value once. However far down the list the entry sits, and whether or not it is pinned, copying that text again brings the same entry back to the top rather than adding a second row beside it — with its pin, its past values and everything else it carries. What is compared is what an entry holds now: a row you have typed over is a different thing from the value it used to hold, so copying that old value starts a new entry.
If you would rather the history stayed in the order things were first copied, switch off Bring a repeated copy back to the top in Copy/Paste preferences. A repeat then leaves the entry where it is and as it was; the copy is still on the clipboard, and triggers still run on it.
The same goes for a row that comes to say it some other way. Where a trigger rewrites a copy into text an older row already held — a rule turning every PROJ-1 into the same link — the older row is absorbed just as a copy would have absorbed it, and the row just written is the one that stands.
Appending to the copy before it
Hold ⌘ and tap C twice and what you have selected is added to the end of the copy before it, instead of being kept as a copy of its own. Three pieces from around a page — a name here, an order number there, a line of an address — become one item and one paste, joined by a newline. Both go on the clipboard together, so the next ⌘V pastes the lot.
It is off until you switch it on, under Copying in Copy/Paste preferences. It changes what the most worn chord on your Mac does, in every app, so nothing turns it on for you — and noticing the second tap needs the same Accessibility permission automatic pasting needs, which the pane will tell you about if it is missing.
The gesture is read narrowly, because every miss is a copy quietly joined to the last one. ⌘ has to stay down between the two taps — letting go of it is exactly what you do when you copy two separate things in a row — the taps have to be within half a second, and nothing may be pressed in between. ⌘⌥C and ⌘⇧C are other chords and are left alone, holding C down is one press however long you hold it, and a third tap starts a fresh pair rather than appending again.
What you append is not kept as an item of its own: it is half of one copy, so there is no second row for it, nothing is gathered, and no trigger fires on it — which also means a forget rule cannot protect text you append by hand. The item it grows comes to the top of the history holding both, with what it said before kept among its past values, so an append you did not mean is one step from being undone. The joined text is plain: two copies' formatting cannot be joined into one, and a file list with a sentence added to it is no longer the paths of a file.
An image cannot be appended to, and neither can a copy with nothing in front of it. Both say so and keep the copy as an ordinary one.
Keeping a selection without copying it
Select text in any app and choose Keep in PasteDaemon from the app menu's Services submenu, or from the bottom of the right-click menu. The text goes into your history as if you'd copied it, formatting included, and your clipboard stays as it was. The app you were in is recorded as where it came from, and your triggers run on it as they do on a copy.
It works while recording is paused, since you asked for it specifically, but not in an app on your excluded list. The HUD says when nothing was kept.
The same submenu can also run an action on the selection and put the result in its place.
Copying text off the screen
Some text can't be selected: a slide somebody is sharing in a call, a locked PDF, a frame of a video, a label in an app that won't let go of it. Choose Copy Text from Screen in the menu bar menu, or press the chord you set for it in General, and draw a box over the text with the same crosshair a screenshot uses. Press the space bar to take a whole window instead, or ⎋ to give up.
The words inside the box are read by Vision, the same way a copied picture is read, and put on your clipboard ready to paste. They arrive as a copy made in the app in front, so your triggers run on them and app: finds them later. The picture itself isn't kept. Like Keep in PasteDaemon, it works while recording is paused. While an app on your excluded list is in front the text is still copied, but not kept in your history. The HUD says so when the box holds no text.
The first time you use it, macOS asks to let PasteDaemon record the screen. It needs that to see other apps' windows. If you said no, turn it on in System Settings → Privacy & Security → Screen & System Audio Recording, then quit and reopen PasteDaemon.
Picking a colour off the screen
Choose Pick Colour from Screen in the menu bar menu, or press the chord you set for it in General, and the system's eyedropper appears, magnifying what is under the pointer. Click a pixel and its colour is copied as #rrggbb, lowercase, in sRGB, so it gets its swatch in the history and the ⌘L page shows its name and contrast. ⎋ gives up without copying anything.
Like Copying text off the screen it arrives as a copy made in the app in front, so triggers run on it, and it is kept while recording is paused. It needs no permission: macOS reads the pixel, not PasteDaemon.
Adding from a link
PasteDaemon answers pastedaemon:// links, so a launcher, Keyboard Maestro, a bookmarklet or PopClip can add to your history or open a search, with no API key:
| Link | Does |
|---|---|
pastedaemon://add?text=… | Adds the text to your history, without touching the clipboard |
pastedaemon://add?text=…&tags=work,to-read | The same, and tags it |
pastedaemon://search?q=… | Opens the overlay with that search typed in |
The text has to be URL-encoded — hello%20world for hello world. In Terminal:
open "pastedaemon://add?text=hello%20world&tags=work"
A bookmarklet that keeps the page you're on:
javascript:location.href='pastedaemon://add?tags=reading&text='+encodeURIComponent(location.href)
A link can only add or search. Any web page can open one, so it never runs an action: your triggers don't run on what a link adds, a forget trigger included, and a search that would be a command ($1 | upper) is refused rather than put in the bar. Nothing is ever sent back to whatever opened the link. For more than that, use the API.
Like Keep in PasteDaemon, a link adds while recording is paused, but not from an app on your excluded list. The app that opened the link is recorded as where it came from, so app:safari finds what a bookmarklet added.
Sending one to somebody
The share-link action makes the link for you. Run $1 | share-link on what you want to send, or $1 | share-link #work to tag it too, and send the link to somebody else who has PasteDaemon. When they open it, the text lands in their history.
The text is in the link itself, so anyone who can see the link can read it, and a long text makes a long link. Nothing is uploaded anywhere. Some chat apps don't make pastedaemon:// links clickable; if yours doesn't, the link still works pasted into Safari's address bar.
PopClip
To get a PopClip button that keeps the selected text, select these lines and choose Install Extension from PopClip's bar:
#popclip
name: PasteDaemon
icon: symbol:doc.on.clipboard
url: pastedaemon://add?text=***
Add &tags=popclip (or any tags you like) after the *** to file what it keeps.
What is not kept
- Concealed, transient and auto-generated copies. Pasteboard contents marked
org.nspasteboard.ConcealedType— the convention password managers use — are ignored, and so are those markedTransientType(passing through, such as a paste done by way of the clipboard) orAutoGeneratedType(made by an app rather than by you). - Anything copied while an excluded app is in front. No entry, no past value, no trigger.
- A copy carrying one of your ignored types — copies from your other devices by Universal Clipboard, say.
- A copy larger than the limit you set, if you set one. The HUD says how large it was.
- Anything at all, while recording is paused — except what you keep with the Copy to the history chord.
- An ordinary
⌘C, while you keep only copies made with the shortcut. - Anything a
forgettrigger catches. A trigger that recognises the shape of a thing that should never be kept — an API token, a one-time code — drops each such copy the instant it is made, and leaves the text on the clipboard to be pasted where it was going. The trigger can ask where the copy was made as well as what it says: a Pipeline gives true condition of| from-window-named login checkout bankcatches copies from pages with those words in their titles, since a browser puts the page's title in its window's.
A seal trigger is the other answer to the same copy: it is kept, but encrypted, shown as ••••••••, and pasted only after Touch ID. While the vault is open, the row shows the text when it is selected or the pointer rests on it.
Pausing
⌘T in the overlay, or Pause Recording in the menu bar, stops the app keeping anything. The system clipboard works as it always does and everything already in the history can still be used; nothing new is recorded and no trigger runs.
Resuming starts from whatever is on the clipboard then. What was copied while paused is passed over rather than arriving all at once, which is what pausing was for.
Because a paused history looks exactly like a working one, it says so in three places: the menu bar icon dims, the menu item reads Resume Recording, and the overlay carries a banner across the top. It is deliberately not saved — a pause is for the next few minutes, and one that survived a restart would go on quietly losing copies long after it was wanted. Every launch starts recording.
Pause Recording For in the menu bar pauses for the next copy, the next five, or a few minutes, and recording comes back on its own. With Clear history when recording is paused on in Copy/Paste preferences, turning recording off also empties the history, keeping the pins — but only a pause with no end does; one that ends on its own never clears.
Where a copy came from
Each copy remembers the app it was made in, and the overlay shows it: the app's icon with its name beside it, under the row's text. Which window a snippet came out of is often the fastest way to recognise it — three similar-looking URLs are told apart at a glance by the browser, the terminal and the chat app they were copied from.
Whoever is in front when the pasteboard changes is taken to be who copied, which is the only guess available: the pasteboard says nothing about where its contents came from. The poll is a quarter of a second behind at worst.
Like formatting and files, the source belongs to the value rather than to the entry, so the version list says where each past value came from. A copy from Safari that a trigger rewrote is still a copy from Safari and still shows Safari; values the app itself produced name the action instead, since "copied in PasteDaemon" is not news. Text typed into a variable was copied nowhere and shows nothing.
The window's title is kept too — a browser's page title, a document's name, a mail's subject — and a row's preview and its ⌘L page show it. window: finds copies by it, asking with ? reads it, and a trigger's from-window asks about it. It is read through the Accessibility permission, so without that, for an app with no window in front, and for copies made before PasteDaemon kept titles, there is no title. Nothing asks for one when the copy isn't kept — from an excluded app, or while recording is paused.
What is stored is the bundle identifier, the name and the window's title. The icon is looked up fresh, so it follows the app being updated or moved, and an app that is no longer installed leaves the row showing the name it was copied under.
Formatting
Text copied with formatting — bold, links, colour — keeps how it looked, so using it again from the history pastes it as it was copied. Rich text (with and without attachments) and HTML are stored alongside the plain text every other part of the app works in, and using an entry offers them back richest first: an app that can take one does, and an app that cannot still gets the text.
Formatting is carried through a change to the text. Actions and triggers read and write plain text, but when one changes formatted text, the result keeps the look of what it changed: $1 | upper on "Hello World" pastes "HELLO WORLD", and a proofread that fixes a word in a bold sentence leaves the sentence bold. Each character takes the look of the one it replaced, and words written in take the look of what stands before them, as typing does — though they never join a link. ⌘D shows the same comparison.
When a step writes mostly new text — summarize, translate, lines sorted into another order — styling laid over it would land in the wrong places, so the result is plain. So is the output of a step that writes markup, such as html-escape or rtf-source. Either way the formatted original stays behind the new value in that entry's history, where undo and the version list can reach it. Bringing a past value back brings its formatting with it. A single formatted shape larger than 256 KB is left behind; the plain text is kept either way.
Two shipped actions say which shape should go on the clipboard, instead of all of them:
unfmt— the text alone. No bold, no links, no colour, no fonts.html— the HTML of the copy in place of the richer shapes beside it. A web copy carries the page's own markup; a copy from a word processor carries rich text, which is converted.
Neither changes a character of the text, so either can sit anywhere in a chain, and where both are named the last one wins.
Run by hand — from the overlay, the menu bar, or a command like $2 | unfmt — the choice is about this paste: the entry keeps how it was copied, so pressing ↩ on that row later pastes it dressed as it always was. Named from a trigger, the choice is about the copy, because a trigger fires when something is copied and there is no paste yet to decide about. That is how "anything copied out of that app is plain text" gets said.
html gives the HTML of whatever look the text has at that point: $1 | upper | html gives the recased text's HTML, made afresh. Where a step rewrote too much for any look to be carried, there is no HTML to give, and it says so rather than pasting the old copy's markup over the new text. unfmt can always be honoured.
Four things make formatting rather than choosing among what a copy already had: a script action that declares its output, md-rich, which reads the text as Markdown and puts what it renders to on the clipboard, and rtf-rich and html-rich, which do the same with RTF and HTML source. All four are held to the rule above from that point on. rtf-source writes out the RTF a formatted copy carries, as text.
Files
Copying files in Finder stores an entry whose text is their paths, one to a line, and which remembers that those paths are files. Using it again puts the files back on the clipboard, so pasting into Finder copies them as it would have at the time. Only the files go on, so an app that takes text reads them its own way — Terminal pastes the path. To paste the paths as text anywhere, use ⌘⇧V.
One exception: copying a screenshot's floating preview (after ⌘⇧4, right-click the thumbnail in the corner → Copy) keeps the picture, not the file. That file is temporary, and macOS deletes it once the preview goes.
macOS only lets an app put a file on the clipboard if the app can open it. For files in your Desktop, Documents or Downloads folder, iCloud Drive, cloud storage or another disk, that means giving PasteDaemon Full Disk Access. The first time you paste a file from one of those places without it, PasteDaemon explains and offers to open System Settings; switch it on there, then quit and reopen PasteDaemon. Until you do, those files paste as their paths. PasteDaemon uses the access to hand back files you copied and, if you turn on searching their text, to read the documents you copy so a search finds them (below). It never changes them.
A copied document can be found by what it says. Turn on Search the text in copied files in Preferences → Search, and when you copy a PDF, a Word or RTF document, or a text file — Markdown, code, CSV — in Finder, PasteDaemon reads its text in the background and keeps the start of it, about ten pages, with the copy. Typing a word from inside it finds it, ?the lease agreement finds scan-0412.pdf, and the row shows a line of what it says under the file's name. Files already in your history are read as soon as you turn it on.
- Files in your Desktop, Documents or Downloads folder, iCloud Drive, cloud storage or on another disk are read only once PasteDaemon has Full Disk Access. When you turn the switch on without it, PasteDaemon explains and offers to open System Settings; switch it on there, then quit and reopen PasteDaemon. Choose Only Other Folders to read just the files kept elsewhere.
- The text is kept with the history, so if you sync, it syncs with the copy.
- Switch it off again and no file is opened, and what was read is forgotten.
Unlike an image, a file list is not inert. The paths are the entry's value, so filters read them, $1 names them, actions run on them and a search matches on them — a folder name finds files that are not shown by name in the row.
The shape goes exactly as far as the text it describes: text a filter has rewritten is paths no longer, so it pastes as text, and the copy as it was made stays behind it in that entry's history.
Files are looked for before text, because a copy in Finder puts a string on the pasteboard too — the bare file names — which is the least useful thing on offer. Only a real file copy answers as one: text that merely spells a path, or a file:// URL, is text.
Nothing is copied to a folder of the app's own. An entry holds paths, which are a promise about somewhere else, so what is still there is checked when the row is drawn — a row says how many of its files have gone — and again when it is used, where only the survivors go back on the clipboard. A list whose files have all gone still pastes as the paths it always was.
Images
An image copied to the clipboard becomes an entry like any other, and using it puts it back on the clipboard as it was copied. Where an app offers a picture and a string together — the address of an image on a web page, the name of a file — the text is what is kept: it is what the copy was about.
Every image is read. On its way into the history the picture is handed to Vision's accurate text recogniser and the words it finds are stored beside it, so a screenshot is searchable by what it says. The reading happens off the main thread, so the entry is on screen before it comes back; a very large screenshot can take a moment. The same picture copied twice is the entry that already holds it, and is not read again. If macOS fails to read a picture at all, it is read again the next time PasteDaemon starts.
An image answers to what it is and what it says: a query matches against PNG image · 1024×768 and against the words that were read, so typing an invoice number finds the screenshot of the invoice.
Otherwise an image is mostly inert. Most actions read and write text, and an image is not text:
- Only a trigger written for pictures runs on one — see Triggers on pictures.
- No action is offered, in the overlay or the menu bar, while the newest item is an image.
- A filter that reads text says so rather than reading a picture as empty.
- What acts on the entry rather than its text takes a picture too:
$1 | tag #shots,$1 | describe Logo,$1 | forgetand$1 | from Preview. - A picture can be kept in a variable whole —
$1 > $logo— and pasted from it as the picture; see Pictures, formatting and files. - An image entry gains a second value only from a trigger — a smaller picture, or the text read out of it — and the picture as copied stays in its history.
ocr is the one filter that reads the picture rather than text, which makes it the one command an image entry can be the start of — $1 | ocr. What it hands on is text, so the rest of the library follows it: $1 | ocr | trim > $address. It is typed rather than picked from a list, since the list of actions only appears while the newest item is text.
resize reads the picture too, and puts a copy of it at another size on the clipboard: $1 | resize 50% for half the size, $1 | resize 800 for 800 pixels wide, $1 | resize x600 for 600 high — each keeping the picture's shape — or $1 | resize 800x600 for exactly that, stretched if it has to be. The original stays in the history with the new one on top of it. It hands on a picture rather than text, so only another image filter can follow it — or a step that files the entry, such as tag: $1 | resize 800x100 | resize x50 is 400 by 50, the second step working on what the first left, and $1 | resize 50% | tag #small tags the smaller copy.
A copied image file works too. Photos copies the photo's file rather than the picture, and Finder copies files, so when the newest item is one image file, $1 | resize 50%, $1 | describe-image and the rest read the picture in it. The file itself is left as it was; what the filter makes is a new picture on top. (ocr still needs the picture itself.)
The other image filters work the same way:
| Filter | Does |
|---|---|
crop 800x600+100+50 | Cuts out a rectangle; crop alone takes off a border |
rotate, rotate 180 | Turns it clockwise, a quarter turn unless told |
flip, flip v | Mirrors it left to right, or top to bottom |
png, jpeg 80 | Writes it in that format |
fit 2MB | Compresses and shrinks it until it is under the size |
strip | Writes it again with no location or camera details |
remove-background | Keeps the subject and makes the rest transparent, as a PNG |
Every one of them writes the picture with nothing but its pixels (and the resolution it was saved at, so a Retina screenshot stays sharp), so none of them leaves a location in a photo. Three more read a picture into text, and can come first or after image filters: qr for what a QR code or barcode says, data-uri for the picture as a data: URI, and colors for the colours it is mostly made of. And qrcode goes the other way — copy a link, pick it from the menu bar, and a QR code of it is on the clipboard. Save a size you use often as a pipeline action starting from | — | resize 50% as half — and $1 | half does the same.
The bytes live in files beside the JSON rather than in it, named for a hash of their contents, so the same image copied twice is stored once. Images are held to limits of their own, so that a run of screenshots cannot push out the text that was in the history first: the 50 most recent images, and 200 MB of them together. A single image larger than 32 MB is not recorded at all, and the overlay says so at the time.
Objects
A copy in Keynote, Excel, PowerPoint, Numbers, Pages or Word carries more than text and a picture: the app's own data — the shape, the cells with their formulas, the slide. PasteDaemon keeps that too, so using the copy again from the history pastes the thing itself back into the app, not a picture of it or its text. Pasting it into any other app still gives that app the text or picture it can read.
- Text with an object beside it is still text: search, actions and triggers read it as always. The row shows the
#objecttag, and⌘Flists#objectamong its kinds. - A Keynote shape is kept with the picture Keynote makes of it, so it pastes as the shape into Keynote and as the picture anywhere else. Its row reads Keynote object · HEIF preview.
- A copy that is only an object, with no text and no picture, is a row of its own, such as Keynote object. Like an image, nothing reads it as text: no trigger fires on it, and a filter that names it says so. It pastes only into the app it came from, and PasteDaemon says so if you use it while another app is in front.
- Microsoft Office is the exception. Office apps only paste their own data back from their own copy in memory, not from a clipboard any other app wrote, including PasteDaemon: - PowerPoint slides paste back as slides while the PowerPoint you copied them from is still running. After you quit it, they paste as pictures. - Excel ranges paste back with their values and formatting, but not their formulas. The formulas are kept in the history; Excel just won't paste them back as cells.
- Editing the text with
⌘Edrops the object, as it drops formatting, and so does running an action that changes the text. When the item you edit is the newest one, your edited text goes on the clipboard as well, so⌘Vpastes the edit. Bringing the copy back from the version list brings the object back.⌘⇧Vpastes the text alone. - The pictures and PDFs an app draws of its own copy are not kept with the object: they are slow to make and can be enormous (a Keynote slide offers a 6 MB picture of 22 KB of slide). A copy whose own data takes longer than a tenth of a second to read, or comes to more than 32 MB, is kept as its text or picture alone.
- Objects stay on the Mac they were copied on. With sync on, the row appears on your other Macs and pastes its text there; one that was only an object says on another Mac.
The 100 most recent objects are kept, up to 200 MB together. Past that the oldest lose their object and keep their text or picture; only a row that was nothing but an object is removed.
Retention
How long is the only question the history asks. There is no cap on how many entries it holds. A count is the wrong question — a clipboard fills at a hundred copies one day and three the next, so the same number is a fortnight or an afternoon depending on the week.
Retention is answered once per kind of thing: text, images, file lists and objects each get one of 24 hours, 7 days, 1 month, 3 months or unlimited, set in Copy/Paste preferences. Anything older is dropped; anything newer is kept, however much of it there is.
Which kind an entry counts as is worked out from what it holds now, not from how it arrived. An image is an image; an entry that remembers its text is paths is a file list; a copy that was only an app's own data is an object; everything else is text — including text that carried an object beside it. So a file list a filter has rewritten is text from then on, and is kept for as long as text is.
Age is counted from when the entry last took its value, which is what the row already shows. A pin never expires — pinning is how an entry steps off the belt, and time is the belt.
The history is swept three times over, because each catches what the others cannot: at launch, before anything can be shown; when something is copied, alongside the image budget; and every five minutes while the app sits idle, which is the machine a retention is most for. Shortening a period sweeps immediately, so a change visibly takes effect while you are still looking at the pane.
Variables are never pruned at all. If something is worth keeping past its kind's retention, it wants either a pin or a name.
Where all this is kept
Everything is in ~/Library/Application Support/PasteDaemon:
| File | What is in it |
|---|---|
config.json | Settings, actions, triggers, abbreviations and variables. Laid out prettily with its keys in order — it is meant to be readable and editable by hand |
history.json | The clipboard history, pins included. Written compactly and off the main thread, since it is rewritten after every copy |
images/ | The bytes of copied images, one file each, named for a hash of their contents |
objects/ | Apps' own data from copies that carried some, one file per copy, named for a hash of its contents |
shell-history.json | The search bar's last 100 commands |
vault.key, vault.pub | The secrets vault's key pair. Deleting these makes every stored secret permanently unreadable |
A secret is written as ciphertext and its plain value is never on disk. The API key is not in config.json either — it is in the login keychain, because a credential in a plain-text file that every process running as you can read is a password written on the door.