clawe overview video

Created: Apr 24, 2023Last modified: Apr 28, 2023
Word count: 1850Backlinks: 2

A video overview of the components that make up the clawe monorepo.

Relevant April 2023.

I did a stream covering clawe and this note on 4/28/23, here: https://www.twitch.tv/videos/1805970411?t=2h59m42s

I hope to crunch this into a shorter youtube video soon!

goals

> give context on clawe to passers-by

> primarily, be thorough. hopefully brief!

Clawe is a big dev-tools monorepo

I'm big on dev tools! Developers need to keep their knives sharp! Tools are super important for leverage. Work is about feedback loops and flow. Yada yada yada.

Clawe is a monorepo. Hooray!

When I first switched from osx to linux, I was unlocked - I started realizing I could just write bash to do the things I wanted. I was in i3, but had been all about hammerspoon and mjolnir + alfred.

I started with a universal movement command, but integrating with emacs, i3, browsers, tmux, and vim posed an interesting design challenge. How to manage all that complexity?

> devtools

  • window managers / desktop environments / ricing
  • keybindings

Clawe pillars/show-case

> Keybindings

> Rofi/Clawe-mx

> Ralphie - integration apis

ralphie offers nice data-driven apis

clawe.edn expresses them

clawe/wm/etc does whatever logic to make it work

> Native Widgets

clojure patterns that work for clawe

> maps as arugments, namespace keys

showcase

> bb tasks as rofi and tmux fire

Clawe supports several integrations

  • org files (org-roam directories)
  • heavy lifting is done by russmatney/org-crud
  • awesomeWM, yabai (other window-managers can impl clawe's wm-protocol)
  • keybindings
  • window management
  • notifications
  • rofi/osx-rofi-like
  • git repos
  • local screenshots/gifs/assets (assets still to be impled)
  • wallpapers
  • pomodoros
  • static blog building (for an org-roam-based blog)
  • browsers (via brotab)
  • lichess games (yep)

(this list reminds me of yodo's integrations )

tech choices

> clojure

>> Why clojure?

This could go on a bit too long. Too much love to share.

>>> repl-driven development (and debugging)

>>> lisp

opinionated, but structured editing is quite excellent.

(lisps unlock the simplicity of repl-driven development)

>>> full-stack language, cljc (clojure-conditional)

The dream of the 90s (isomorphic javascript) is alive in clojure!

>>> BABASHKA!

More than just front+back end clojure!

Now we're in the blissful land of bash scripting.

>>> clojure as a language and standard library

clojure is highly performant

very little code to do pretty much everything

>>> mmm, i love me some nil-punning

>>>> TODO nil-punning examples in clawe?

>>> datalog, datascript

Expressive, data-driven ( constraint-based ) database query engines

>>> malli

if you want the 'features' of types. (i.e. crashing)

>> Why clojure for clawe?

>>> repl-driven means simpler debugging

ex: testing your keybindings in your editor

No more editing some whacky lua/i3/bash and then rerunning it.

>>> repl-driven means incremental state (i.e. live-reload)

You should only need to restart the whole thing (awesomeWM, i'm looking at you)

on the rarest of occasions

>>> clojure + tauri: web apps as native app

Tauri is basically a newer electron.

Tauri as a simple native web view.

>>> BABASHKA

We can run the same logic for scripting as on the backend as on the frontend!

>> Why clojure on the frontend?

>>> hiccup (+ clojure datastructures) rules

>>> better than js on the frontend

We just wrap react and then do whatever we want.

JS (and TS) are just so much code, and not much benefit to all the extra fluff.

Plus there's lots of nonsense... it honestly feels like arguing osx over linux.

>>> better than AwesomeWM widgets, polybar

Styling awesomeWM widgets vs writing hiccup and adding tailwind classes is not much fun, especially given the feedback loop of editing clojure on shadowcljs.

And then there's handling a datamodel - I want to send workspaces full of data into rich little components, full of metadata.

>>> tailwind (beats awesomewm/polybar/rofi ricing)

Tailwind css is an excellent tool for staying in the code and still getting everything out of css's latest features. That plus hiccup+cljs means you can write the structure, styling, and logic all in a cljs file, with live-reloading and repl-driven dev. It's glorious!

>>> probably a show-don't-tell moment, lets see some examples

>> BABASHKA: clojure for bash

clojure all the things!

Now we're able to re-use our code when writing fancy dev-tooling scripts over many different integrations.

clojure as a glue language

>>> supports great clj libraries

>>>> tick - universal datetime parsing/comparing/formatting
>>>> babashka.fs, babashka.process

Note that these are also consumable by 'backend' clojure code!

>>>> org-crud

You know, if your keybindings need to parse your org-roam files, for example.

Not that anyone asked...

>>> runs fast

> cljs

> tailwind

clawe components

> Opinion: monorepos

> ralphie

Ralphie gets into the nitty-gritty of the integrations, and presents reasonable map-based functions for the other parts of clawe to consume.

>> does not depend on any clawe namespaces

>> can run completely via babashka

>> integrations (i.e. namespaces/functions)

>>> ralphie.browser

>>> ralphie.spotify

>>> ralphie.tmux

>>>> (tmux/fire {:tmux.fire/command "echo 'hi'" :tmux/session "dev"})

This will create the session if it doesn't exist, and create a new pane (via split) if the default one is busy.

Very useful for running any script/task/app, and keeping an eye on its logs.

>>> ralphie.emacs

>>> ralphie.awesome

>>> ralphie.yabai

> clawe.* (clawe's self-titled namespace)

>> can run completely via babashka

>> implies a knowledge of the users' clawe.config

>> manages the current workspaces and clients

>> most clawe bindings are executed via babashka's -x support

Tho there is some in-lining of functions in awesome-wm, kind of a fun performance hack.

I dug into building and stripping down bb uberscripts (with carve ), and building jars, but the -x performance proved to be the same AND no building-it overhead. It does have the problem of running the live code, so there's no clawe executable - right now it runs the code as-is from the machine's local repo.

>> features

>>> clawe toggle

>>> clawe-mx

Inspired by emacs' interactive commands (m-x) - clawe-mx was originally a

rofi-menu expressing a macro called defcom, but it's grown to include a number

of fancy actions, including:

  • clone + create workspace for repo currently visited in a browser tab

>>> workspace-context features

I have a strong opinion on workspace usage. (Note that this is note a required opinion for working with clawe).

I create workspace per repo, and have workspace-context as an input to several keybindings.

  • Ex: mod + enter -> toggle open/close/focus the workspace's tmux session
  • Ex: mod + shift + enter -> toggle open/close/focus the workspace's emacs session
  • clawe-mx suggests tmux/fire of the wsp-repo's babashka tasks

>> show yabai/sxhkd file with bindings

>> show skhd fallback

>> show awesome fennel inlining

>> clawe config - data-driven behaviors

A config file defining workspaces and clients, along with behaviors for them.

(e.g. how should a client react to a toggle request?)

This has not yet been broken out of the repo, but can be done without much effort (blog.config works the same without the file being local - it's likely just updating the paths and then providing a reasonable default/example config).

> doctor

>> full-stack clojure script

>> frontend via shadow-cljs

>> backend via the jvm

Undertow? Ring? I can't recall, there's so little to it.

>> topbar

like polybar, but cljs + tailwind + datascript

>> widgets

>>> dashboard

A widget full of widgets, running via clove ( tauri ), togglable via clawe toggle

>>> todos, focus widget

manages todos from org

>>> blog

manages reviewing and publishing org-roam notes

>>> pomodoros

>>> events (screenshots, clips, commits, chess games...)

A review app? Maybe I should mention yodo?

> garden

This is where org-crud meets clawe/doctor's note and todo domain. Intended to support whatever features we need from integrating the mindgarden.

> blog (danger.russmatney.com)

I originally implemented a clerk -based blog, but that process taught me how simple hiccup and slurp/spit can be, and i drooled over a proper clawe integration and using the clawe dashboard to manage publishing to multiple platforms (integrations like dev.to, reddit, mastodon, etc).

> db

A datascript db, mostly consumed by doctor, but optionally available to ralphie and clawe (and other babashka needs).

I've not explored this much, but I'm hopeful it's reasonably accessible.

> other namespaces

>> components.*, api.*, hooks.*, pages.core

Intended to support agnostic full-stack features.

At one point doctor wasn't the only full-stack app, but I've recently deleted expo to keep things focused for now.

The hope with some of the components.* in particular is that they can be uix and doctor.ui.db independent, so they are reusable in the backend blog/hiccup work.

>> chess.*

the lichess integration. Perhaps this should be moved to ralphie? It was originally a separate repo.

I owe a licensing update related to some of the components.chess code!!

>> screenshots.core, clips.core, wallpapers.core

Perhaps these should live in ralphie, but I'm reluctant to add db.core deps to ralphie namespaces.

I'm also reluctant to bury these in doctor, when they can still reasonably be consumed by clawe.

I'm also reluctant to bury these in clawe, which i hope to not litter with lots of integration-style namespaces.

Mostly I'm just reluctant... whatever, it's fine for now.

>> git.core

Similar to screenshots/wallpapers. Perhaps they _do_ belong in clawe... but I hate long namespaces if I can help it.

>> item.core

Often, working with a generic item is useful and common enough, so this namespace exists to provide resonable shared logic across integrations.

>> dates.tick, util

Utility libs, usable everywhere.

>> defthing/defkbd

An old but still used for linux-keybindings abstraction.

demo time!

> defkbd repl-ing

> tmux/fire repl-ing

> clawe mx

> repo clone and new workspace creation

> doctor topbar

> doctor dashboard (pomodoros, focus, todos)

> doctor topbar current task

> doctor todos updating on org-file-save

> screenshots coming into 'today'

> clawe blog note publishing

yodo aside

In 2020, I spent an awful lot of time working on the end of todo apps, an idea I called 'Yodo'. The idea was to develop an app to cut out the overhead and just tell me the next thing on my list. It should be smart enough to make suggestions based on time of day, day of week, weather, current status of sprint, pomodoros, everything.

It was a great build, but at the end it was trapped in a web-app, and didn't dip quite low enough to be useful when working on other things. Ultimately, I dropped it in favor of: let's just make stuff for a while. I had some tastes of success making some scrappy love2d games, and then I got pulled into contract work for another year and a half.

Along the way, I ran into babashka, and I started ralphie, which eventually led to clawe for the window-management features. I also pulled the org bit of yodo OUT of yodo and into org-crud.

Several abstractions and refactors later ( defthing, expo, org-blog ), we're at today. Whow knows where we'll be next time?

key must-mentions

> teknql/plasma, websockets as functions, react-hooks like backend data access

plasma's defhandler lets you write backend functions in cljc files, then call them from cljs. Like, actually.

Then defstream lets you keep those requests up to date.

You consume them on the frontend via 'hooks' apis.

>> the power of defhandler

> russmatney/org-crud

caveats

> ricing and personal tools - it's personal and opinionated

> clojure, emacs, lisp... it's a non-zero investment!

It takes time to get comfortable with these tools.

counter: it's much easier now than it was even 5 years ago (because doom emacs is five years further along).

some questions

> can ralphie depend on db.core?

> how do we minimize clawe_mx's (and other clawe keybinding's) performance?


Backlinks