Compare commits

..

3 commits

Author SHA1 Message Date
Howard Abrams
c0a1d5c2d7 Adding agent skills to Claude. 2026-06-17 15:39:24 -07:00
Howard Abrams
f5881248f9 Details on Claude, Cursor, and Gemini
This also includes the knockknock notification system, which works
well enough.
2026-06-17 11:12:10 -07:00
Howard Abrams
d3065fb559 Fixed a bug in the Kanata keyboard layout 2026-06-15 14:53:34 -07:00
3 changed files with 254 additions and 70 deletions

View file

@ -29,16 +29,22 @@ Can we call the following /applications/? I guess.
* Agentic Interface * 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. 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 ** Agent Shell
Installing Xenodiums [[https://github.com/xenodium/agent-shell][agent-shell]], requires installing the ACP libraries: 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.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package acp (use-package acp
:straight (:type git :host github :repo "xenodium/acp.el")) :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 (use-package agent-shell
:straight (:type git :host github :repo "xenodium/agent-shell") :straight (:type git :host github :repo "xenodium/agent-shell")
:after acp :after acp
:custom
(agent-shell-display-action '(display-buffer-in-previous-window))
:config :config
(ha-leader "a i" '("agent chat" . agent-shell)) (ha-leader "a i" '("agent chat" . agent-shell))
@ -53,6 +59,179 @@ Installing Xenodiums [[https://github.com/xenodium/agent-shell][agent-shell]]
(when (string-match-p "\\*agent-shell-diff\\*" (buffer-name)) (when (string-match-p "\\*agent-shell-diff\\*" (buffer-name))
(evil-emacs-state))))) (evil-emacs-state)))))
#+END_SRC #+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 * 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. 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 #+author: Howard X. Abrams
#+date: 2025-11-24 #+date: 2025-11-24
#+filetags: emacs hamacs #+filetags: emacs hamacs
#+lastmod: [2026-02-04 Wed] #+lastmod: [2026-06-15 Mon]
A literate programming file for configuring Hammerspoon. A literate programming file for configuring Hammerspoon.
@ -32,12 +32,8 @@ To create special key bindings, I can:
hs.application.launchOrFocus("Slack") hs.application.launchOrFocus("Slack")
end) end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
hs.application.launchOrFocus("Spotify")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function() hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function()
hs.application.launchOrFocus("Firefox") hs.application.launchOrFocus("Safari")
end) end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function() hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function()
@ -53,14 +49,14 @@ To create special key bindings, I can:
hs.application.launchOrFocus("zoom.us") hs.application.launchOrFocus("zoom.us")
end) end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "A", function()
hs.application.launchOrFocus("Cursor")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function() hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function()
hs.application.launchOrFocus("KeepassXC") hs.application.launchOrFocus("KeepassXC")
end) end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
hs.application.launchOrFocus("VLC")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "E", function() hs.hotkey.bind({"alt", "ctrl", "shift"}, "E", function()
hs.execute("FOR_WORK=yes open -a /Applications/Emacs.app") hs.execute("FOR_WORK=yes open -a /Applications/Emacs.app")
end) end)
@ -214,23 +210,32 @@ My company gave me a nice monitor … maybe a little too nice, as I dont care
function centerWindow() function centerWindow()
local win = hs.window.focusedWindow() local win = hs.window.focusedWindow()
local app = win:application() if not win then return end -- Safety check in case no window is focused
local f = win:frame()
-- Magic numbers figured out by trial and error: local app = win:application()
f.x = 600 local screen = hs.screen.find("DELL P3424WE")
f.y = 30 local maxBounds = screen:frame() -- This gets the absolute coordinates of that specific monitor
f.w = 2200
f.h = 1470 -- 2. Define your desired size
local desiredW = 2200
local desiredH = 1470
if app then if app then
local name = app:name() local name = app:name()
-- If the application is Slack, adjust the height
if name == "Slack" or name == "iTerm2" then if name == "Slack" or name == "iTerm2" then
f.h = 1200 desiredH = 1200
end 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) win:setFrame(f)
hs.alert.show("Centered Window") hs.alert.show("Centered Window")
end end

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 /) 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)) m (tap-hold $tap-time $hold-time m (layer-while-held HYPER))
c (tap-hold $tap-time $hold-time c (layer-while-held MEGA))) v (tap-hold $tap-time $hold-time v (layer-while-held MEGA)))
;; The base layer is fairly normal, except we all out aliases defined ;; 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 ;; 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 ` 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \ tab q w e r t y u i o p [ ] \
@caps @a @s @d @f @g @h @j @k @l @; ' ret @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) @h lctl lalt lmet spc rmet ralt)
;; The other layer is our `symbols' which allows me to hold down the ;; The other layer is our `symbols' which allows me to hold down the