Compare commits
No commits in common. "c0a1d5c2d7480d43b9d266f703e1c67efe970cf8" and "590bc6f567aa164b763005e4487fb13b12e89cc4" have entirely different histories.
c0a1d5c2d7
...
590bc6f567
3 changed files with 70 additions and 254 deletions
|
|
@ -29,22 +29,16 @@ Can we call the following /applications/? I guess.
|
|||
* Agentic Interface
|
||||
Ethic issues aside, I’m [[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 can’t compete with my creation here.
|
||||
** Agent Shell
|
||||
Installing Xenodium’s [[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 Xenodium’s [[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 Xenodium’s [[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 can’t 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 Workday’s 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 let’s 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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
@ -32,8 +32,12 @@ To create special key bindings, I can:
|
|||
hs.application.launchOrFocus("Slack")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
|
||||
hs.application.launchOrFocus("Spotify")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function()
|
||||
hs.application.launchOrFocus("Safari")
|
||||
hs.application.launchOrFocus("Firefox")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function()
|
||||
|
|
@ -49,12 +53,12 @@ To create special key bindings, I can:
|
|||
hs.application.launchOrFocus("zoom.us")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function()
|
||||
hs.application.launchOrFocus("KeepassXC")
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "A", function()
|
||||
hs.application.launchOrFocus("Cursor")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "W", function()
|
||||
hs.application.launchOrFocus("VLC")
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "Q", function()
|
||||
hs.application.launchOrFocus("KeepassXC")
|
||||
end)
|
||||
|
||||
hs.hotkey.bind({"alt", "ctrl", "shift"}, "E", function()
|
||||
|
|
@ -210,32 +214,23 @@ My company gave me a nice monitor … maybe a little too nice, as I don’t care
|
|||
|
||||
function centerWindow()
|
||||
local win = hs.window.focusedWindow()
|
||||
if not win then return end -- Safety check in case no window is focused
|
||||
|
||||
local app = win:application()
|
||||
local screen = hs.screen.find("DELL P3424WE")
|
||||
local maxBounds = screen:frame() -- This gets the absolute coordinates of that specific monitor
|
||||
local f = win:frame()
|
||||
|
||||
-- 2. Define your desired size
|
||||
local desiredW = 2200
|
||||
local desiredH = 1470
|
||||
-- Magic numbers figured out by trial and error:
|
||||
f.x = 600
|
||||
f.y = 30
|
||||
f.w = 2200
|
||||
f.h = 1470
|
||||
|
||||
if app then
|
||||
local name = app:name()
|
||||
-- If the application is Slack, adjust the height
|
||||
if name == "Slack" or name == "iTerm2" then
|
||||
desiredH = 1200
|
||||
f.h = 1200
|
||||
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")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue