Xiaoxing's Notes

Two Ways To Capture Links Into Org Files

January 31, 2021
756 words
3 minutes

The Good Way

I discovered this method somehow on the internet. I read it somewhere, but I can't find the source anymore, because, dah! I didn't have good integration between my web content and my org-mode notes yet before I found that solution, did I? The gist of it is to wrap emacsclient into a native mac app, so you can leverage URL scheme for apps, an excellent built-in feature of macOS.

But you don't want to create a real mac app, right? Good news, there's an app called Platypus, which allows you to create native Mac app from command line scripts. Being a native app, you can register your own URL scheme protocol (org-protocol of cause) that you can invoke system-wide. But it stopped working after I upgraded to Big Sur, as it would, of course. Then I found this on GitHub and later the same information on org-roam documentation, tried it quickly, still no luck for me. I am pretty sure it's my own fault during the process (7 steps or so?), but I am too old to patiently following other people's steps, so instead, I create my own way.

A Better Way

Cut to the chase, instead of hacking the system (Yes, I consider creating a fake app to trick the system into recognizing a URL scheme a hack). I decided to stick to the tool that's built for automation: Automator. Here's how.

Create a Quick Action

Create Quick Action

Make it look like this.

The full workflow

You can follow the screenshot up there. I will break it down now, so you know exactly what to do, and customise accordingly.

Quick Action Config


The workflow receives Automatic (Nothing), because you can look at the dropdown list, there isn't an ideal option based on our needs (you will know how I mean it in a second). Also, choose your default browser app there, for me it's Safari.

Run JavaScript

you can run AppleScript if you prefer it, but I never familiar myself enough to use it fluently. Here is the code.

function run(input, parameters) {

    const safari = Application('Safari');
    const tab = safari.windows[0].currentTab; const url = encodeURIComponent(tab.url());
    const name = encodeURIComponent(tab.name());

    return [url, name];

To summarise the code: find the front-most tab from Safari (or another browser of your choosing), return the url and the name (i.e. the <title/>). We need both the URL and the name information from the tab, that's why the options in the "workflow receives" can't help me.

Run Shell Script


/usr/local/bin/emacsclient --no-wait "org-protocol://roam-ref?template=r&ref=$1&title=$2" -a 'open -a /Applications/Emacs.app'

This is my way of capturing the link, i.e. using org-roam and roam-ref sub-protocol. Of course, you can change it to whatever way you'd like it to be. $1 would be the url, and $2 is the name, from the previous step.

Launch Emacs


So that Emacs is called to the front and focused.

Test it out

Now is a good time to test and debug it.

Run and debug the workflow

Save it

Then you can find it in the services menu for Safari.

Capture link service in Safari menu

Assign a shortcut to it in system preferences.

Assign a keyboard shortcut

Why is it Better?

  • The Better Way is an all-in-one solution. You keep all the implementation details within this Quick Action. It's totally self-contained. For comparison, with the Good Way, you need to maintain the following things:
    1. A native mac App, which is an Application bundle, which is hard to version control. Also subject to break after macOS update.
    2. Complicated URL for invoking the app, it's not fun scattering something like this everywhere.
  • Being an all-in-one solution, with the Better Way, you can pack it up and share it, version control it, make it downloadable.
  • With the Better Way, you can easily assign keyboard shortcuts to Quick Actions; In contrast, browser bookmark is a mouse-clicking action.
  • With the Good Way, You are kind of limited to browsers since it's easy to create a special bookmark that invokes the org-protocol URL scheme. If you want to capture other things, you need a totally different solution, like Alfred actions or, guess what, Automator.
  • With the Good Way, After the org-protocol is invoked, Emacs is not brought to the front, at least for me. Maybe there are ways to improve that, but I just don't bother.
  • With the Better Way, You don't need to create a fake app, it feels cleaner, doesn't it? Apps are, well Apps, not scripts. Maybe I have OCD.

Talk to me if you have any questions or different opinions, I am open to any suggestions. Let's make each other's life easier; even though that we are strangers. That's how awesome us nerds are.

Read more stories about "emacs" ->