Compare commits

..

No commits in common. "c0a1d5c2d7480d43b9d266f703e1c67efe970cf8" and "590bc6f567aa164b763005e4487fb13b12e89cc4" have entirely different histories.

3 changed files with 70 additions and 254 deletions

View file

@ -29,22 +29,16 @@ Can we call the following /applications/? I guess.
* Agentic Interface
Ethic issues aside, Im [[https://technobabble.bearblog.dev/fine-ill-try-ai/][trying AI]] … primarily because my company requires my participation. I appreciate the approaches from my fellow Emacsians, for while VSCode may be a fine editor, it cant compete with my creation here.
** Agent Shell
Installing Xenodiums [[https://github.com/xenodium/agent-shell][agent-shell]], requires his [[https://github.com/xenodium/acp.el][ACP package]] for accessing the installed [[https://agentclientprotocol.com/][ACP libraries]], and his [[https://github.com/xenodium/shell-maker][shell-maker]] package.
Installing Xenodiums [[https://github.com/xenodium/agent-shell][agent-shell]], requires installing the ACP libraries:
#+BEGIN_SRC emacs-lisp
(use-package acp
:straight (:type git :host github :repo "xenodium/acp.el"))
(use-package shell-maker
:straight (:type git :host github :repo "xenodium/shell-maker"))
(use-package agent-shell
:straight (:type git :host github :repo "xenodium/agent-shell")
:after acp
:custom
(agent-shell-display-action '(display-buffer-in-previous-window))
:config
(ha-leader "a i" '("agent chat" . agent-shell))
@ -59,179 +53,6 @@ Installing Xenodiums [[https://github.com/xenodium/agent-shell][agent-shell]]
(when (string-match-p "\\*agent-shell-diff\\*" (buffer-name))
(evil-emacs-state)))))
#+END_SRC
*** Notifications
When my /artificial intern/ completes a task, I have long since nipped out to the kitchen, put the kettle on ... buttering scones... and getting crumbs and bits of food out of those round brown straw mats that the teapot goes on.
I would like the /intern/ to notify me when it needs attention, so I noticed the [[https://github.com/zackattackz/agent-shell-notifications/][agent-shell-notifications]] project can connect the =agent-shell= project with the [[https://github.com/konrad1977/knockknock/][knock-knock]] project (which is similar to my [[https://howardism.org/Technical/Emacs/beep-for-emacs.html][beep project]]).
#+BEGIN_SRC emacs-lisp
(use-package knockknock
:straight (knockknock :type git :host github :repo "konrad1977/knockknock")
:init
(setq knockknock-border-color "brown")
(setq knockknock-border-width 2)
(setq knockknock-default-duration 4)
:config
(advice-add 'knockknock-notify :after #'beep-beep))
#+END_SRC
Testing it out:
#+BEGIN_SRC emacs-lisp :tangle no
(knockknock-notify :title "Attention"
:message "Claude needs attention"
:icon "nf-md-robot_confused")
#+END_SRC
The configuration for [[https://github.com/zackattackz/agent-shell-notifications/][agent-shell-notifications]] and hook it to the =agent-shell-notifications-provider=:
#+BEGIN_SRC emacs-lisp
(use-package agent-shell-notifications
:straight (agent-shell-notifications
:type git
:host github
:repo "zackattackz/agent-shell-notifications")
:hook
;; Enable notifications in each agent-shell buffer
(agent-shell-mode . agent-shell-notifications-mode)
:config
;; Notification display timeout in seconds (0 = never expire (the default), -1 = backend default)
;; (setq agent-shell-notifications-timeout 5)
;; Seconds to wait before notifying when the shell is already visible (default: 10)
;; (setq agent-shell-notifications-idle-timeout 30)
;; Use the knockknock backend instead of the default libnotify
(setq agent-shell-notifications-provider 'agent-shell-notifications-knockknock)
;; While that code is _supposed_ to do this, I seem to need to do this manually:
(require 'agent-shell-notifications-knockknock))
#+END_SRC
I might switch to [[https://github.com/cxa/agent-shell-macext#start-of-content][agent-shell-macext]] if I cant get KnockKnock to work well on my Linux system.
*** Agent Skills
The following pulls in [[https://github.com/xenodium/emacs-skills][emacs-skills]], a Claude Agent skills for Emacs:
#+BEGIN_SRC emacs-lisp
(use-package emacs-skills
:straight (:type git :host github :repo "xenodium/emacs-skills"))
#+END_SRC
The most helpful is =/open= that you run afterwards to pull the changes into buffers for complete review. Use the =/highlight= variation to see the changes highlighted.
*** Agent Sidebar
Using the [[https://github.com/cmacrae/agent-shell-sidebar][agent-shell-sidebar]] project, we can easily open/close the Agent buffer window:
#+BEGIN_SRC emacs-lisp
(use-package agent-shell-sidebar
:after agent-shell
:straight (:host github :repo "cmacrae/agent-shell-sidebar")
:bind (("s-i" . agent-shell-sidebar-toggle-focus)
("s-I" . agent-shell-sidebar-toggle)))
#+END_SRC
*** Claude Code
To begin install the dependencies:
#+BEGIN_SRC emacs-lisp :tangle no
(use-package agent-shell
:ensure-system-package
((claude . "brew install claude-code")
(claude-agent-acp . "npm install -g @agentclientprotocol/claude-agent-acp")))
#+END_SRC
And point Emacs to it:
#+BEGIN_SRC emacs-lisp
(use-package agent-shell
:config
(setq agent-shell-preferred-agent-config (agent-shell-anthropic-make-claude-code-config)
agent-shell-anthropic-claude-acp-command
`,(file-expand-wildcards "/opt/homebrew/Cellar/node/*/bin/claude-agent-acp")))
;; /opt/homebrew/Cellar/node/26.0.0/bin/claude-agent-acp
#+END_SRC
*** Cursor
Cursor, through ACP constantly drops its token on the floor. This annoyance makes me want to use something else.
The Cursor interface requires installing the ACP libraries, and a suggestion to install the [[https://github.com/blowmage/cursor-agent-acp-npm][cursor-agent-acp]] project:
#+BEGIN_SRC sh
npm install -g @blowmage/cursor-agent-acp
#+END_SRC
Appears we need to install the [[https://github.com/zalab-inc/cursor_agent][cursor-agent]] CLI as well. Install it with this command:
#+BEGIN_SRC sh
curl https://cursor.com/install -fsSL | bash
#+END_SRC
Or can we do both of these through Emacs:
#+BEGIN_SRC emacs-lisp :tangle no
(use-package agent-shell
:ensure-system-package
((cursor-agent . "brew install cursor-cli")
(claude-agent-acp . "npm install -g @blowmage/cursor-agent-acp")))
#+END_SRC
Change the *default browser* to Workdays favorite, Chrome, and login:
#+BEGIN_SRC sh
cursor-agent login
#+END_SRC
Now the Emacs configuration:
#+BEGIN_SRC emacs-lisp :tangle no
(use-package agent-shell
:custom
(agent-shell-cursor-command `,(file-expand-wildcards "/opt/homebrew/Cellar/node/*/bin/cursor-agent-acp"))
:config
(setq agent-shell-preferred-agent-config (agent-shell-cursor-make-agent-config)))
#+END_SRC
*** Gemini
First install the [[https://github.com/google-gemini/gemini-cli][gemini-cli]]:
#+BEGIN_SRC sh
brew install gemini-cli
#+END_SRC
And lets make that the default now:
#+BEGIN_SRC emacs-lisp :tangle no
(use-package agent-shell
:config
(setq agent-shell-preferred-agent-config (agent-shell-google-make-gemini-config)))
#+END_SRC
** AI Code Interface
While the =agent-shell= offers a /vibe-codey/ interface to Chatbots, the [[https://github.com/tninja/ai-code-interface.el][ai-code-interface]] offers a more /programmatic/ interface.
#+BEGIN_SRC emacs-lisp
(use-package ai-code
:straight (:host github :repo "tninja/ai-code-interface.el")
:config
;; use codex as backend, other options are 'claude-code, 'gemini,
;; 'github-copilot-cli, 'opencode, 'grok, 'cursor, 'kiro,
;; 'codebuddy, 'aider, 'eca, 'agent-shell, 'claude-code-ide,
;; 'claude-code-el
(ai-code-set-backend 'gemini)
;; Enable global keybinding for the main menu
(global-set-key (kbd "C-c a") #'ai-code-menu)
;; Optional: Enable @ file completion in comments and AI sessions
(ai-code-prompt-filepath-completion-mode 1)
;; Optional: Ask AI to run test after code changes, for a tighter build-test loop
;; (setq ai-code-auto-test-type 'ask-me)
;; Optional: In AI session buffers, SPC in Evil normal state triggers the prompt-enter UI
;; (with-eval-after-load 'evil (ai-code-backends-infra-evil-setup))
;; Optional: Set up Magit integration for AI commands in Magit popups
(with-eval-after-load 'magit
(ai-code-magit-setup-transients)))
#+END_SRC
* Git and Magit
Can not live without [[https://magit.vc/][Magit]], a Git porcelain for Emacs. I stole the bulk of this work from Doom Emacs.

View file

@ -2,7 +2,7 @@
#+author: Howard X. Abrams
#+date: 2025-11-24
#+filetags: emacs hamacs
#+lastmod: [2026-06-15 Mon]
#+lastmod: [2026-02-04 Wed]
A literate programming file for configuring Hammerspoon.
@ -21,65 +21,69 @@ Ive created left and right ~Meh~ keys on my Moonlanders:
To create special key bindings, I can:
#+BEGIN_SRC lua
----------------------------------------------------------------------
-- Launcher replaces iCanHazShortcuts
----------------------------------------------------------------------
-- Launcher replaces iCanHazShortcuts
hs.hotkey.bind({"alt", "ctrl", "shift"}, "T", function()
hs.application.launchOrFocus("iTerm")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "T", function()
hs.application.launchOrFocus("iTerm")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "S", function()
hs.application.launchOrFocus("Slack")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "S", function()
hs.application.launchOrFocus("Slack")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function()
hs.application.launchOrFocus("Safari")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
hs.application.launchOrFocus("Spotify")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function()
-- hs.osascript.applescriptFromFile("~/bin/chrome.scr")
hs.execute("~/bin/chrome.scr")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function()
hs.application.launchOrFocus("Firefox")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "B", function()
hs.application.launchOrFocus("Microsoft Outlook")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function()
-- hs.osascript.applescriptFromFile("~/bin/chrome.scr")
hs.execute("~/bin/chrome.scr")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Z", function()
hs.application.launchOrFocus("zoom.us")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "B", function()
hs.application.launchOrFocus("Microsoft Outlook")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function()
hs.application.launchOrFocus("KeepassXC")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Z", function()
hs.application.launchOrFocus("zoom.us")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
hs.application.launchOrFocus("VLC")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "A", function()
hs.application.launchOrFocus("Cursor")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "E", function()
hs.execute("FOR_WORK=yes open -a /Applications/Emacs.app")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function()
hs.application.launchOrFocus("KeepassXC")
end)
-- Special Emacs Guys
-- Right Meh key:
hs.hotkey.bind({"alt", "ctrl", "shift"}, "X", function()
hs.execute("~/bin/emacs-capture")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "E", function()
hs.execute("FOR_WORK=yes open -a /Applications/Emacs.app")
end)
-- Left Meh key:
hs.hotkey.bind({"cmd", "alt", "ctrl", "shift"}, "X", function()
hs.execute("~/bin/emacs-capture-clock")
end)
-- Special Emacs Guys
-- Right Meh key:
hs.hotkey.bind({"alt", "ctrl", "shift"}, "X", function()
hs.execute("~/bin/emacs-capture")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "M", function()
hs.execute("~/bin/emacs-capture-meeting")
end)
-- Left Meh key:
hs.hotkey.bind({"cmd", "alt", "ctrl", "shift"}, "X", function()
hs.execute("~/bin/emacs-capture-clock")
end)
-- Current music system is actually in Emacs:
hs.hotkey.bind({"alt", "ctrl", "shift"}, "R", function()
hs.execute("/opt/homebrew/bin/emacsclient -s work -e '(ready-player-toggle-play-stop)'")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "M", function()
hs.execute("~/bin/emacs-capture-meeting")
end)
-- Current music system is actually in Emacs:
hs.hotkey.bind({"alt", "ctrl", "shift"}, "R", function()
hs.execute("/opt/homebrew/bin/emacsclient -s work -e '(ready-player-toggle-play-stop)'")
end)
#+END_SRC
* Zoom
Library extensions to Hammerspoon are called /spoons/, and most of these are a simple Lua script, =init.lua= stored in the =Spoons= subdirectory. We grab these with a =git clone=, typically. To use the Zoom spoon, clone it:
@ -209,35 +213,26 @@ My company gave me a nice monitor … maybe a little too nice, as I dont care
-- Centering a window on the large monitors at Work:
function centerWindow()
local win = hs.window.focusedWindow()
if not win then return end -- Safety check in case no window is focused
local win = hs.window.focusedWindow()
local app = win:application()
local f = win:frame()
local app = win:application()
local screen = hs.screen.find("DELL P3424WE")
local maxBounds = screen:frame() -- This gets the absolute coordinates of that specific monitor
-- Magic numbers figured out by trial and error:
f.x = 600
f.y = 30
f.w = 2200
f.h = 1470
-- 2. Define your desired size
local desiredW = 2200
local desiredH = 1470
if app then
local name = app:name()
if name == "Slack" or name == "iTerm2" then
desiredH = 1200
if app then
local name = app:name()
-- If the application is Slack, adjust the height
if name == "Slack" or name == "iTerm2" then
f.h = 1200
end
end
end
-- 3. Calculate relative position based on the external monitor's bounds
-- This centers the window perfectly on the target screen
local f = {
x = maxBounds.x + ((maxBounds.w - desiredW) / 2),
y = maxBounds.y, -- + ((maxBounds.h - desiredH) / 2),
w = desiredW,
h = desiredH
}
win:setFrame(f)
hs.alert.show("Centered Window")
win:setFrame(f)
hs.alert.show("Centered Window")
end
hs.hotkey.bind({"cmd", "alt", "ctrl", "shift"}, "Y", centerWindow)

View file

@ -87,7 +87,7 @@
mn (multi lsft lctl lalt lmet n) mm (multi lsft lctl lalt lmet m) m, (multi lsft lctl lalt lmet ,) m. (multi lsft lctl lalt lmet .) m/ (multi lsft lctl lalt lmet /)
m (tap-hold $tap-time $hold-time m (layer-while-held HYPER))
v (tap-hold $tap-time $hold-time v (layer-while-held MEGA)))
c (tap-hold $tap-time $hold-time c (layer-while-held MEGA)))
;; The base layer is fairly normal, except we all out aliases defined
;; above, os the @a is both a `tap-hold' feature as well as a regular
@ -98,7 +98,7 @@
` 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \
@caps @a @s @d @f @g @h @j @k @l @; ' ret
lsft z x c @v b n @m , . / rsft
lsft z x @c v b n @m , . / rsft
@h lctl lalt lmet spc rmet ralt)
;; The other layer is our `symbols' which allows me to hold down the