{"id":21387152,"url":"https://github.com/russmatney/clawe","last_synced_at":"2025-07-13T15:31:40.705Z","repository":{"id":39625127,"uuid":"327964260","full_name":"russmatney/clawe","owner":"russmatney","description":"Clojure REPL-based WM hacking on linux and osx","archived":false,"fork":false,"pushed_at":"2024-04-14T02:23:01.000Z","size":3336,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-04-14T19:19:39.933Z","etag":null,"topics":["awesomewm","babashka","clojure","yabai"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/russmatney.png","metadata":{"files":{"readme":"readme.org","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"russmatney","patreon":"russmatney"}},"created_at":"2021-01-08T17:06:08.000Z","updated_at":"2024-04-17T18:53:30.602Z","dependencies_parsed_at":"2023-09-28T03:07:57.334Z","dependency_job_id":"9401cc02-7b3f-4aa5-a449-c1a34a21087a","html_url":"https://github.com/russmatney/clawe","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/russmatney/clawe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/russmatney%2Fclawe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/russmatney%2Fclawe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/russmatney%2Fclawe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/russmatney%2Fclawe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/russmatney","download_url":"https://codeload.github.com/russmatney/clawe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/russmatney%2Fclawe/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265162856,"owners_count":23720849,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awesomewm","babashka","clojure","yabai"],"created_at":"2024-11-22T12:11:59.916Z","updated_at":"2025-07-13T15:31:40.699Z","avatar_url":"https://github.com/russmatney.png","language":"Clojure","funding_links":["https://github.com/sponsors/russmatney","https://patreon.com/russmatney","https://www.patreon.com/russmatney"],"categories":[],"sub_categories":[],"readme":"#+TITLE: Clawe\n#+startup: overview\n\n#+html: \u003cdiv id=\"header\" align=\"center\"\u003e\n#+html: \u003cdiv id=\"badges\"\u003e\n#+html:   \u003ca href=\"https://mastodon.gamedev.place/@russmatney\"\u003e\n#+html:     \u003cimg src=\"https://img.shields.io/badge/Mastodon-teal?style=for-the-badge\u0026logo=mastodon\u0026logoColor=white\" alt=\"Mastodon Badge\"/\u003e\n#+html:   \u003c/a\u003e\n#+html:   \u003ca href=\"https://www.twitch.tv/russmatney\"\u003e\n#+html:     \u003cimg src=\"https://img.shields.io/badge/Twitch-purple?style=for-the-badge\u0026logo=twitch\u0026logoColor=white\" alt=\"Twitch Badge\"/\u003e\n#+html:   \u003c/a\u003e\n#+html:   \u003ca href=\"https://www.patreon.com/russmatney\"\u003e\n#+html:     \u003cimg src=\"https://img.shields.io/badge/Patreon-red?style=for-the-badge\u0026logo=patreon\u0026logoColor=white\" alt=\"Patreon Badge\"/\u003e\n#+html:   \u003c/a\u003e\n#+html:   \u003ca href=\"https://discord.gg/PQvfdApHFQ\"\u003e\n#+html:     \u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/758750490015563776?style=for-the-badge\u0026logo=discord\u0026logoColor=fff\u0026label=discord\" /\u003e\n#+html:   \u003c/a\u003e\n#+html: \u003c/div\u003e\n#+html:\n#+html: \u003ch1\u003e\n#+html:   Hi there! I'm Russ!\n#+html:   \u003cimg src=\"https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif\" width=\"30px\"/\u003e\n#+html: \u003c/h1\u003e\n#+html: \u003c/div\u003e\n\nLately: I'm refactoring away from 'managing' each wm config - clawe\nwill instead provide a useful CLI for doing some wm things.\n\n--\n\nI'm putting together an overview of this whole project [[https://russmatney.com/note/clawe_overview_video.html][on my blog]].\n\nA stream covering the motivation and showing some of the namespaces is available\n[[https://www.twitch.tv/videos/1805970411?t=2h59m42s][on twitch]].\n\nI hope to cut it to something shorter and more presentable soon!\n\n--\n\n#+begin_quote Toy Story\nBuzz: This is an intergalactic emergency. I need to commandeer your vessel to Sector 12. Who's in charge here?\n\nAll Aliens: [pointing up]  The clawwwwwwwww[e]!\n\nAlien #1: The claw is our master.\n\nAlien #2: The claw chooses who will go and who will stay.\n\nWoody: This is ludicrous.\n#+end_quote\n\nFor more on Clawe beyond the below readme, check out the [[https://russmatney.com/note/clawe.html][clawe garden file]] on my blog.\n\n* Clawe is a clojure-centric window-manager, uh, -manager\nIt is named after the shape of your hand while trying to nail some of these key\nbindings.\n\nIt started as a CLojure-AWEsomewm experiement, but now cuts off any specific WM\nvia a protocol, and can run on OSX (via yabai) as well.\n\nClawe is a clojure-based approach to managing your window manager's\nconfiguration, and otherwise hacking scripts/automation together on your\nmachine.\n\n** Clawe feature list\n- Dev against your environment with a clojure repl!\n  - No more write-compile-restart-loop!\n  - Instead, debug by connecting to a running clojure repl and execing the code.\n- Define your keybindings as clojure functions\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/defs/bindings.clj][clawe.defs.bindings namespace]]\n- Configurable, toggle-able clients that can be repo-workspace aware\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/toggle.clj][clawe.toggle namespace]]\n- [[https://github.com/davatorium/rofi][Rofi]] (or via [[https://github.com/chipsenkbeil/choose][choose]] on osx) for listing available commands\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/m_x.clj][clawe.mx]] and [[https://github.com/russmatney/clawe/blob/master/src/ralphie/rofi.clj][ralphie.rofi]] namespaces\n- Useful Babashka-based namespaces\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/browser.clj][ralphie.browser]]\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/clipboard.clj][ralphie.clipboard]]\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/emacs.clj][ralphie.emacs]]\n  - [[https://github.com/russmatney/clawe/blob/master/src/ralphie/git.clj][ralphie.git]]\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/notify.clj][ralphie.notify]]\n  - [[https://github.com/russmatney/clawe/blob/master/src/ralphie/screenshot.clj][ralphie.screenshot]]\n  - [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/tmux.clj][ralphie.tmux]]\n  - [[https://github.com/russmatney/clawe/tree/master/src/ralphie][all ralphie namespaces]]\n- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/git.clj#L101][suggesting git clones based on the clipboard and current tabs]]\n\n** ~clawe.wm~ and ~clawe.wm.protocol~\n[[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/wm.clj][clawe.wm]] provides functions for working with your running clients and\nworkspaces:\n\nEx:\n\n- ~clawe.wm/focus-client~\n- ~clawe.wm/delete-workspace~\n\nThese functions are implemented via a [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/wm/protocol.clj][protocol]], which means extending the same\nbehavior to other window-managers is fairly reasonable. I've implemented it for\nAwesomeWM and Yabai so far, but am interested in pursuing i3 and bspwm as well.\n\n- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/awesome.clj][ralphie.awesome]]\n- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/yabai.clj][ralphie.yabai]]\n** Babashka-based\nMuch gratitude to borkdude and the clojure community at large!\n\nClawe would not be possible without the boon that [[https://github.com/babashka/babashka][Babashka]] has brought to the\nclojure ecosystem. Simplicity + performance!\n*** [[https://github.com/babashka/process][process]]\nClawe uses process everywhere, to shell out and do everything. It's the\nequivalent of ~$()~ in bash.\n*** [[https://github.com/babashka/cli][cli]]\nNearly all of clawe's commands are executed almost exclusively as babashka cli commands:\n\n#+begin_src sh\n# Toggle open/closed emacs in the current workspace's directory\nbb ~/russmatney/clawe/bb.edn -x clawe.toggle/toggle \"emacs\"\n#+end_src\n\nThis is of course often better debugged in a clojure repl itself:\n\n#+begin_src clojure\n(comment (clawe.toggle/toggle \"emacs\"))\n#+end_src\n** To cover in more detail\n*** ~resources/clawe.edn~\n*** sxhkd/awesome config on linux\n*** yabai/skhd config on osx\n** Future work\n*** Break up ~clawe.edn~ usage into personal configs\n*** refactor/hone keybindings implementation\n** Old methods\n*** Clawe microscripts? uberjar?\nClawe has been through a few different iterations and experiements - at one\npoint I was using carve to produce 'micro'-scripts in an effort to improve\nperformance.\n\nLater I had an uberjar flow, which required rebuilding after code changes were\nmade.\n\nLately I'm in favor of using the babashka/cli style - just run the scripts in\nplace, call the functions directly with ~-x~. This has been great and nice to\ndebug both in the repl and via the terminal. It's also simple, in that there are\nno built artifacts to worry about. I expect this method to stick!\n* Doctor, Tauri, and full-stack clojure\n~doctor~ and most of the other top-level namespaces in clawe are used in a\nfull-on JVM or browser context. The above clawe features are all babashka-based,\nbut with ~doctor~, we get into support for topbars, dashboards, parsing org\nfiles, reviewing chess games, publishing blog posts... all sorts of rabbit holes.\n\nIt may have been wise to cut clawe at the above feature set (and I did just\nthat before one day throwing up my hands and combining several repos together).\n\nInstead I've been hacking deeper features right on top of it. Keeping things in\nthe same repo lowers the barrier for trying out new things, and at this point\nthe clawe repo has several runtimes.\n\n** Multiple runtimes\nIn particular, the 'doctor' backend is jvm based, and not all of the\nclojure dependencies are babashka compatible.\n\nThere are 4 runtimes to be aware of.\n*** the 'bash' runtime (i.e. babashka)\nthe ~clawe~ and ~ralphie~ namespaces are intended to be consumed by babashka\ncommands, and should be simple, fast, and (mostly) stateless. A clawe.edn\nconfig file is read for most of them to work, but that should be it.\n*** the backend 'server' (doctor backend)\nA backend server process running via the jvm - the typical clojure environment,\nproviding a web api and sockets for connecting to the doctor frontend.\n\nWorth noting - this server provides an nrepl for the clawe/ralphie namespaces to\nconnect to, and is where most of clawe's development happens.\n*** the web frontend (doctor frontend)\nA shadow-cljs process runs the typical frontend clojurescript environment.\n*** Tauri topbar, doctor\nTauri is used, really just for it's webview, to serve the topbar and a 'native'\ndoctor web app (though I often work in a [[https://www.mozilla.org/en-US/firefox/developer/][proper dev browser]] as well.)\n\nLately this is impled via `clove`, which wraps a Tauri app and exposes an api\nfor launching transparent apps at arbitrary urls.\n\nSee the [[https://github.com/russmatney/clove][clove repo]] for install instructions.\n** Doctor features\nWith those runtime distinctions in mind...\n\nDoctor is not quite as settled as clawe and ralphie, but it is centered around\nsome core features:\n\n- Topbar\n  - workspaces and their clients (current workspace, etc)\n  - queued tasks\n    (todos are parsed from org files and opted into via the doctor's components)\n- Dashboard\n  - in various views\n    - org items (parsed and crud-able via [[https://github.com/russmatney/org-crud][russmatney/org-crud]])\n    - commits from repos (parsed via ~ralphie/git~)\n    - recent screenshots\n    - recent games from [[https://lichess.org][lichess.org]]\n  - setting wallpapers\n- Sockets via [[https://github.com/teknql/plasma][teknql/plasma]]\n- Database via [[https://github.com/tonsky/datascript][tonsky/datascript]]\n\nAs more doctor features/interfaces settle down, I'll update these docs with\nscreenshots and usage details.\n* Rough Dev Notes\n** local symlinking\nseveral local dirs are symlinked into public/assets/\n\n#+begin_src sh\n# from clawe root dir\nln -s ~/Screenshots public/assets/screenshots\nln -s ~/gifs public/assets/clips\nln -s ~/Dropbox/wallpapers public/assets/wallpapers\n#+end_src\n\n#+begin_src\nl ~/russmatney/clawe/public/assets/\nName\ncandy-icons -\u003e /home/russ/EliverLara/candy-icons/apps/scalable/\nscreenshots -\u003e /home/russ/Screenshots/\nwallpapers -\u003e /home/russ/Dropbox/wallpapers/\n#+end_src\n\nThis is a quick hack to let the web apps reference images on the machine\n(avoids a local image host).\n\n** Chessground\nI manually copied the exported css and images into the project:\n\n#+begin_src sh\ncp node_modules/chessground/assets/chessground.base.css node_modules/chessground/assets/chessground.brown.css node_modules/chessground/assets/chessground.cburnett.css public/css/.\n#+end_src\n\n** tauri via ~russmatney/clove~ conf\n\n~clove~ is a barebones tauri cli. It accepts a title and url, then launches a\ntauri webview harness around that url. It sets the window to transparent by\ndefault, so if you want a background, be sure to set one!\n\nThe goal is to support local web apps (like the doctor frontend) without\nrequiring a full browser to use them. I.e. don't let your dashboard get lost in\nyour browser tabs.\n\nSee the [[https://github.com/russmatney/clove][clove repo]] for install instructions.\n\n* Ping me!\nI feel like this is kind of a crazy hack/dev environment - to me, getting to do\nwm-things in clojure and against a repl is the dream!\n\nI've been building it up for a few years now, and am happy to give a tour and\nshare more context.\n\nFeel free to create an issue/discussion in this repo, ping me ~@russmatney~ on\nthe clojurians slack, or pop in on [[https://www.twitch.tv/russmatney][one of my Twitch streams]] - I'd love to share\nmore about it and show how it all fits together.\n\n* Dev Notes\n** Running tests\n*** Clawe Unit tests\n#+begin_src sh\n./test_runner.clj\n#+end_src\n\nRuns some babashka-based clawe unit tests.\n\n*** JVM Unit tests\n#+begin_src sh\n./bin/kaocha unit\n#+end_src\n*** CLJS tests\nBit of a wip for the moment, but hopefully there's a one-line approach to\nrunning these soon.\n\n*** Clawe integration tests\nThese tests exercise the window manager _in place_ - i.e. this will create and\ndestory workspaces in your current environment.\n\n#+begin_src sh\n./bin/kaocha integration\n#+end_src\n\nThese don't run in CI, but are a useful way to debug or ensure basic clawe usage\nisn't borked.\n\n*** AwesomeWM tests\nExpects a running awesomewm and fennel setup, which unfortunately is not well\ndocumented or easily created at the moment.\n\n#+begin_src sh\n./bin/kaocha awesomewm\n#+end_src\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussmatney%2Fclawe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frussmatney%2Fclawe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussmatney%2Fclawe/lists"}