Bink: Bookmarks are just data


This program may not work.
This program will change.
If this program crashes, you may not receive support.
Use this program at your own risk!

Please be kind!


Bookmarks should live in Git!

I gave up on managing bookmarks in web browsers long ago.

But I was thinking. We’re able to take care of source code. Improve it over time. And we’ve got this amazing thing called version control. And this other amazing thing called data. So why not combine them.

Bookmarks are just data.

But! Opening a bookmark must be nice. Run a command, select the bookmark, open in browser.

So I made a thing. Use it like this:

  1. Run $ bink in a terminal
  2. Select a bookmark
  3. It opens in your web browser

But the bookmarks are just a bunch of EDN files you can structure yourself in ~/.config/bink/provider/. Here’s an example:

;; from ~/.config/bink/provider/links.edn on my computer:
{:links [{:title "Clojure Deref" :href ""}
         {:title "Clojureverse" :href ""}]}

If you want to try it out, that’s awesome.

To add a bookmark, edit your link files. You can use as many files as you want. Just make sure the suffix is .edn.

Feel free to bug me about it on the babashka channel on the Clojurians Slack.

Teodor (

Here’s a small install script:

Or install it with bbin:

$ bbin install
$ bink


  1. I could provide curl one-liners with some “default” link collections
  2. I could push through to enable end-user launch stuff with babashka.process/shell or other things

Status as of 2022-09-21

  1. I think this is a nice idea
  2. I’m not yet using it daily myself
  3. I think bink has the potential to remove real friction for teams with lots of scattered resources, and remove friction jumping from place to place
    1. (though one could consider not depending on hundreds of external services “at all”)
  4. If you’re interested in this, I’d be happy to help / discuss.
  5. A more interesting scope than “bookmark manager” might be “babashka-powered command launcher”
    1. Could be layered on top of fzf or rofi or other things, user choice
    2. Launcher setup could be user config. And other people could help contribute launchers for their platform. Linux and MacOS users might have different preferences here.
  6. I wonder if providing your.domain/links.json or your.domain/links.edn might be an interesting convention.
    1. could link to babashka-related resources
      1. Though - security. Remote web sites should not be able to run code on your computer.
  7. Navigating to a random link is also an interesting use case
  8. Implementing datafy/nav and leveraging that could also be interesting.

Dev journal / working notes

Feel free to ignore this part :)

Or not.
Your choice.


CLI draft

# To open a link:
$ bink
# Select link with fzf
# Then it's opened in your browser.

# Add a link
$ bink add "Clojure Deref"

Nice to have / later: link providers. I could fetch links from multiple sources. Use one source with my team at work. Another for personal stuff.

A link provider could be an EDN file, a JSON file, an SQLite DB, an URL or a system command.

But! Let’s not start there. Or … It would be nice to be able to just symlink multiple files / programs into ~/.local/share/bink/providers.d/



Path Purpose
~/.config/bink/config.edn Bink main configuration file
~/.config/bink/provider/* Additional link providers

JSON file - interpret as JSON. EDN file - interpret as EDN.

What about programs? If they are executable, perhaps they should be run?

Perhaps an executable links.json should output JSON links on stdout. 🤔


{:links [{:title "Clojure Deref" :href ""}
         {:title "Clojureverse" :href ""}]}


    "links": [
        {"title": "Clojure Deref", "href": ""},
        {"title": "Clojureverse", "href": ""}


Idea: different providers in bink config.

Example configuration:

{:providers {clojure-community {:edn-file
                                {:path "~/.config/bink/provider/clojure.edn"}}
             stuff-from-work {:fn
                              (fn []
                                 (slurp "")

But. What do we do if loading all the links takes time? Do we cache? Or do we allow the slowdown?

If we select provider first then select link, we might not care too much about load time.

I can write a bink provider for

Hmm, that’s actually a very good idea.

And I want to configure which browser to use

To configure which browser to use, is :providers a good toplevel key?

I could extend the current thing.

{:providers {clojure-community {:file "~/.config/bink/provider/clojure.edn"
                                :open-fn (fn [{:keys [href]}]
                                           ( href))}
             teod-play {:fn (fn []
                                 (slurp "")))
                        :open-fn (fn [{:keys [href]}]
                                   (babashka.process/process ["firefox" "-new-window" href]))}
             stuff-from-work {:fn
                              (fn []
                                 (slurp "")

What about multiple providers?

  1. We could mash all links into one
  2. We could first select provider, then load links, then select link

A good next step is probably just supporting by iterbart usecase.