Announcing the first release of Funnel

I’m proud to announce the first release of Funnel, a websocket message relay.

Funnel is a single puzzle piece in the development of the next generation of kaocha-cljs, but it is developed as a stand-alone generic component, applying the age old Unix philosophy of doing one thing well. Or as @dnolen recently put it:

Funnel is a websocket server. It simply sits and waits for connections from clients. When a client connects it announces itself by providing some metadata about itself (what funnel calls a “whoami map”).

{:funnel/whoami {:id "firefox-a53bc" :type :lambdaisland.chui.remote}}

This allows other clients to discover it.

{:funnel/query [:type :lambdaisland.chui.remote]}
{:funnel/clients ({:id "firefox-a53bc" :type :lambdaisland.chui.remote})}

Note that :id and :type are arbitrary, you can stick whatever you like in this whoami map.

Whenever a client sends a message to Funnel, Funnel will check if the message should be forwarded, either because the message has an explicit destination (:funnel/broadcast), or because other clients have previously subscribed with :funnel/subscribe.

This provides most of the protocol that Funnel understands, but what do you do with it?

Funnel is foremost intended for developer tooling that wants to communicate with JavaScript runtimes. The challenge here is that when dealing with browsers the communication has to be initiated by the browser. There is no good way of connecting to a browser tab, or even to discover that there is still an active tab to connect to.

This is especially annoying for short lived processes (say running a test runner from the command line, or invoking it from the REPL). You can spawn a browser and wait for it to connect back, but then you need some way to hold on that connection, or you are back to square one. When using funnel tooling like this can remain stateless, it doesn’t need to keep a background server and keep connection state.

As mentioned above we are using this for building the next generation of kaocha-cljs, which provides ClojureScript support for the Kaocha test runner, but here are some other possible use cases.

  • a remote object browser like REBL/Punk
  • ClojureScript REPL implementations that are aware of multiple runtimes and can switch between them
  • a custom developer dashboard for your app, that communicates directly with the app running in another browser window
  • browser plugins like Dirac that provide integration with other tools like your editor

The README has exhaustive documentation on how to use Funnel. We provide Graal native-image builds for ease of use, but also release to Clojars, so you have the choice of how to run it.

Looking forward to your feedback!


This is a great simplification of how to implement WS. I am inspired :slight_smile:

Nice work @plexus