Skip to content

russmatney/clawe

Repository files navigation

Clawe

Hi there! I’m Russ!

I’m putting together an overview of this whole project on my blog.

A stream covering the motivation and showing some of the namespaces is available on twitch.

I hope to cut it to something shorter and more presentable soon!

Buzz: This is an intergalactic emergency. I need to commandeer your vessel to Sector 12. Who’s in charge here?

All Aliens: [pointing up] The clawwwwwwwww[e]!

Alien #1: The claw is our master.

Alien #2: The claw chooses who will go and who will stay.

Woody: This is ludicrous.

For more on Clawe beyond the below readme, check out the clawe garden file on my blog.

Clawe is a clojure-centric window-manager, uh, -manager

It is named after the shape of your hand while trying to nail some of these key bindings.

It started as a CLojure-AWEsomewm experiement, but now cuts off any specific WM via a protocol, and can run on OSX (via yabai) as well.

Clawe is a clojure-based approach to managing your window manager’s configuration, and otherwise hacking scripts/automation together on your machine.

Clawe feature list

clawe.wm and clawe.wm.protocol

clawe.wm provides functions for working with your running clients and workspaces:

Ex:

  • clawe.wm/focus-client
  • clawe.wm/delete-workspace

These functions are implemented via a protocol, which means extending the same behavior to other window-managers is fairly reasonable. I’ve implemented it for AwesomeWM and Yabai so far, but am interested in pursuing i3 and bspwm as well.

Babashka-based

Much gratitude to borkdude and the clojure community at large!

Clawe would not be possible without the boon that Babashka has brought to the clojure ecosystem. Simplicity + performance!

Clawe uses process everywhere, to shell out and do everything. It’s the equivalent of $() in bash.

Nearly all of clawe’s commands are executed almost exclusively as babashka cli commands:

# Toggle open/closed emacs in the current workspace's directory
bb ~/russmatney/clawe/bb.edn -x clawe.toggle/toggle "emacs"

This is of course often better debugged in a clojure repl itself:

(comment (clawe.toggle/toggle "emacs"))

To cover in more detail

resources/clawe.edn

sxhkd/awesome config on linux

yabai/skhd config on osx

Future work

Break up clawe.edn usage into personal configs

refactor/hone keybindings implementation

Old methods

Clawe microscripts? uberjar?

Clawe has been through a few different iterations and experiements - at one point I was using carve to produce ‘micro’-scripts in an effort to improve performance.

Later I had an uberjar flow, which required rebuilding after code changes were made.

Lately I’m in favor of using the babashka/cli style - just run the scripts in place, call the functions directly with -x. This has been great and nice to debug both in the repl and via the terminal. It’s also simple, in that there are no built artifacts to worry about. I expect this method to stick!

Doctor, Tauri, and full-stack clojure

doctor and most of the other top-level namespaces in clawe are used in a full-on JVM or browser context. The above clawe features are all babashka-based, but with doctor, we get into support for topbars, dashboards, parsing org files, reviewing chess games, publishing blog posts… all sorts of rabbit holes.

It may have been wise to cut clawe at the above feature set (and I did just that before one day throwing up my hands and combining several repos together).

Instead I’ve been hacking deeper features right on top of it. Keeping things in the same repo lowers the barrier for trying out new things, and at this point the clawe repo has several runtimes.

Multiple runtimes

In particular, the ‘doctor’ backend is jvm based, and not all of the clojure dependencies are babashka compatible.

There are 4 runtimes to be aware of.

the ‘bash’ runtime (i.e. babashka)

the clawe and ralphie namespaces are intended to be consumed by babashka commands, and should be simple, fast, and (mostly) stateless. A clawe.edn config file is read for most of them to work, but that should be it.

the backend ‘server’ (doctor backend)

A backend server process running via the jvm - the typical clojure environment, providing a web api and sockets for connecting to the doctor frontend.

Worth noting - this server provides an nrepl for the clawe/ralphie namespaces to connect to, and is where most of clawe’s development happens.

the web frontend (doctor frontend)

A shadow-cljs process runs the typical frontend clojurescript environment.

Tauri topbar, doctor

Tauri is used, really just for it’s webview, to serve the topbar and a ‘native’ doctor web app (though I often work in a proper dev browser as well.)

Lately this is impled via `clove`, which wraps a Tauri app and exposes an api for launching transparent apps at arbitrary urls.

See the clove repo for install instructions.

Doctor features

With those runtime distinctions in mind…

Doctor is not quite as settled as clawe and ralphie, but it is centered around some core features:

  • Topbar
    • workspaces and their clients (current workspace, etc)
    • queued tasks (todos are parsed from org files and opted into via the doctor’s components)
  • Dashboard
    • in various views
      • org items (parsed and crud-able via russmatney/org-crud)
      • commits from repos (parsed via ralphie/git)
      • recent screenshots
      • recent games from lichess.org
    • setting wallpapers
  • Sockets via teknql/plasma
  • Database via tonsky/datascript

As more doctor features/interfaces settle down, I’ll update these docs with screenshots and usage details.

Rough Dev Notes

local symlinking

several local dirs are symlinked into public/assets/

# from clawe root dir
ln -s ~/Screenshots public/assets/screenshots
ln -s ~/gifs public/assets/clips
ln -s ~/Dropbox/wallpapers public/assets/wallpapers
l ~/russmatney/clawe/public/assets/
Name
candy-icons -> /home/russ/EliverLara/candy-icons/apps/scalable/
screenshots -> /home/russ/Screenshots/
wallpapers -> /home/russ/Dropbox/wallpapers/

This is a quick hack to let the web apps reference images on the machine (avoids a local image host).

Chessground

I manually copied the exported css and images into the project:

cp node_modules/chessground/assets/chessground.base.css node_modules/chessground/assets/chessground.brown.css node_modules/chessground/assets/chessground.cburnett.css public/css/.

tauri via russmatney/clove conf

clove is a barebones tauri cli. It accepts a title and url, then launches a tauri webview harness around that url. It sets the window to transparent by default, so if you want a background, be sure to set one!

The goal is to support local web apps (like the doctor frontend) without requiring a full browser to use them. I.e. don’t let your dashboard get lost in your browser tabs.

See the clove repo for install instructions.

Ping me!

I feel like this is kind of a crazy hack/dev environment - to me, getting to do wm-things in clojure and against a repl is the dream!

I’ve been building it up for a few years now, and am happy to give a tour and share more context.

Feel free to create an issue/discussion in this repo, ping me @russmatney on the clojurians slack, or pop in on one of my Twitch streams - I’d love to share more about it and show how it all fits together.

Dev Notes

Running tests

Clawe Unit tests

./test_runner.clj

Runs some babashka-based clawe unit tests.

JVM Unit tests

./bin/kaocha unit

CLJS tests

Bit of a wip for the moment, but hopefully there’s a one-line approach to running these soon.

Clawe integration tests

These tests exercise the window manager in place - i.e. this will create and destory workspaces in your current environment.

./bin/kaocha integration

These don’t run in CI, but are a useful way to debug or ensure basic clawe usage isn’t borked.

AwesomeWM tests

Expects a running awesomewm and fennel setup, which unfortunately is not well documented or easily created at the moment.

./bin/kaocha awesomewm