Skip to content

Commit 83a1ce8

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents ebdba1d + 520cad3 commit 83a1ce8

12 files changed

Lines changed: 815 additions & 177 deletions

.github/ISSUE_TEMPLATE/issue.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ assignees: ''
1111
- [ ] *I agree to communicate with the author myself* (not AI-generated).
1212
- [ ] I've read the README's [Filing issues](https://github.com/xenodium/agent-shell?tab=readme-ov-file#filing-issues) section.
1313
- [ ] I'm running the latest versions (fill in below).
14-
- agent-shell:
15-
- acp.el:
16-
- ACP package (e.g. claude-code-acp):
17-
- Agent CLI (e.g. claude, gemini):
14+
- agent-shell version:
15+
- acp.el version:
16+
- ACP package (e.g. claude-agent-acp) version:
17+
- Agent CLI (e.g. claude, gemini) version:
1818
- [ ] For requesting new agent support, I'm including a link to the ACP-capable agent or related ACP package.
1919
- [ ] For issues, I'm including [ACP traffic](https://github.com/xenodium/agent-shell?tab=readme-ov-file#how-do-i-viewget-agent-client-protocol-traffic) (as per README).

CONTRIBUTING.org

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ Accessing and working with =alists=? Please prefer =map.el= unless we have a str
5454
(map-elt animal :species)
5555
#+end_src
5656

57+
** Prefer =map-nested-elt= over nested =map-elt=
58+
59+
When accessing nested alist values, use =map-nested-elt= instead of nesting =map-elt= calls.
60+
61+
#+begin_src emacs-lisp :lexical no
62+
;; Avoid
63+
(map-elt (map-elt response 'usage) 'totalTokens)
64+
65+
;; Prefer
66+
(map-nested-elt response '(usage totalTokens))
67+
#+end_src
68+
5769
** cl-lib (limited to =cl-defun=)
5870

5971
While I'm a fan of =cl-defun=, please limit =cl= usage to =cl-defun= if possible. Nothing against =cl-lib=. I'm just limiting the surface and number of idioms I need to keep in my head to maintain the codebase. Often, =seq.el= and =map.el= can do the job just fine.
@@ -146,7 +158,9 @@ When defining hook functions or callbacks, prefer a single alist/event parameter
146158

147159
Remove comments obviously by an LLM (e.g. referencing "previous code" or restating the obvious). Avoid emojis in code and output strings.
148160

149-
** Keep PRs focused
161+
** Keep PRs small and focused
162+
163+
Prefer smaller PRs whenever possible. They're easier to review and less likely to introduce issues. If a change can be split into independent steps, submit them as separate PRs.
150164

151165
Don't include unrelated changes (whitespace, indentation, formatting) in your PR. If you'd like to do a cleanup, please submit it as a separate PR.
152166

README.org

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Thank you!
3232

3333
A native Emacs shell to interact with LLM agents powered by ACP ([[https://agentclientprotocol.com][Agent Client Protocol]]).
3434

35-
With agent-shell, you can chat with the likes of Gemini CLI, Claude Code, Auggie, Mistral Vibe, or any other ACP-driven agent.
35+
With agent-shell, you can chat with the likes of Gemini CLI, Claude Agent, Auggie, Mistral Vibe, or any other ACP-driven agent.
3636

3737
Watch on [[https://www.youtube.com/watch?v=R2Ucr3amgGg][YouTube]]
3838

@@ -60,7 +60,8 @@ We now have a handful of additional packages to extend the =agent-shell= experie
6060
- [[https://github.com/gveres/agent-shell-workspace][agent-shell-workspace]]: Dedicated tab-bar workspace for managing multiple =agent-shell= sessions.
6161
- [[https://github.com/ElleNajt/agent-shell-to-go][agent-shell-to-go]]: Interact with =agent-shell= sessions from your mobile or any other device via Slack.
6262
- [[https://github.com/ElleNajt/meta-agent-shell][meta-agent-shell]]: Multi-agent coordination system for =agent-shell= with inter-agent communication, task tracking, and project-level dispatching.
63-
- [[https://github.com/xenodium/emacs-skills][emacs-skills]]: Claude Code skills for Emacs.
63+
- [[https://github.com/xenodium/agent-shell-knockknock][agent-shell-knockknock]]: Notifications for =agent-shell= via [[https://github.com/konrad1977/knockknock][knockknock.el]].
64+
- [[https://github.com/xenodium/emacs-skills][emacs-skills]]: Claude Agent skills for Emacs.
6465

6566
* Icons
6667

@@ -70,9 +71,9 @@ Thanks to [[https://github.com/lobehub/lobe-icons][Lobe Icons]] for the lovely i
7071

7172
** External dependencies
7273

73-
*** Claude Code
74+
*** Claude Agent SDK
7475

75-
For Anthropic's Claude Code, follow [[https://github.com/zed-industries/claude-agent-acp][Zed's claude-agent-acp instructions]], typically something like:
76+
For Anthropic's [[https://platform.claude.com/docs/en/agent-sdk/overview][Claude Agent SDK]] (formerly known as the Claude Code SDK), follow [[https://github.com/zed-industries/claude-agent-acp][Zed's claude-agent-acp instructions]], typically something like:
7677

7778
#+begin_src bash
7879
npm install -g @zed-industries/claude-agent-acp
@@ -390,7 +391,7 @@ For API key authentication:
390391

391392
*** Customizing Available Agents
392393

393-
By default, =agent-shell= includes configurations for all supported agents (Claude Code, Gemini CLI, Codex, Goose, Qwen Code, and Auggie). You can customize which agents are available through the =agent-shell-agent-configs= variable.
394+
By default, =agent-shell= includes configurations for all supported agents (Claude Agent, Gemini CLI, Codex, Goose, Qwen Code, and Auggie). You can customize which agents are available through the =agent-shell-agent-configs= variable.
394395

395396
** Usage
396397

@@ -404,7 +405,7 @@ You can select and start any of the known agent shells (see =agent-shell-agent-c
404405

405406
Start a specific agent shell session directly:
406407

407-
- =M-x agent-shell-anthropic-start-claude-code= - Start a Claude Code agent session
408+
- =M-x agent-shell-anthropic-start-claude-code= - Start a Claude Agent session
408409
- =M-x agent-shell-auggie-start-agent= - Start an Auggie agent session
409410
- =M-x agent-shell-openai-start-codex= - Start a Codex agent session
410411
- =M-x agent-shell-google-start-gemini= - Start a Gemini agent session
@@ -717,7 +718,7 @@ always go to Evil modes if you need to with ~C-z~).
717718
|-----------------+---------------------------------------------------------+-------------------------------------------------------------------------------|
718719
| | agent-shell | Start or reuse an existing agent shell. |
719720
| | agent-shell--display-buffer | Toggle agent SHELL-BUFFER display. |
720-
| | agent-shell-anthropic-start-claude-code | Start an interactive Claude Code agent shell. |
721+
| | agent-shell-anthropic-start-claude-code | Start an interactive Claude Agent shell. |
721722
| | agent-shell-auggie-start-agent | Start an interactive Auggie agent shell. |
722723
| | agent-shell-clear-buffer | Clear the current shell buffer. |
723724
| | agent-shell-completion-mode | Toggle agent shell completion with @ or / prefix. |
@@ -834,7 +835,7 @@ Sometimes including a traffic screenshot in an issue is enough. Other times incl
834835

835836
If you're able to determine the agent is missing a feature (or a bug is present) in their [[https://agentclientprotocol.com][Agent Client Protocol]] implementation, please file an issue directly with the agent folks. For example:
836837

837-
- [[https://github.com/zed-industries/claude-code-acp][claude-code-acp]]: For Claude Code.
838+
- [[https://github.com/zed-industries/claude-code-acp][claude-code-acp]]: For Claude Agent.
838839
- [[https://github.com/zed-industries/codex-acp][codex-acp]]: For Codex.
839840
- [[https://github.com/google-gemini/gemini-cli][Gemini CLI]].
840841
- [[https://block.github.io/goose/docs/getting-started/installation][Goose]].

agent-shell-anthropic.el

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ Example usage to set a custom Anthropic API base URL:
132132
:group 'agent-shell)
133133

134134
(defun agent-shell-anthropic-make-claude-code-config ()
135-
"Create a Claude Code agent configuration.
135+
"Create a Claude Agent configuration.
136136
137137
Returns an agent configuration alist using `agent-shell-make-agent-config'."
138138
(agent-shell-make-agent-config
@@ -152,7 +152,7 @@ Returns an agent configuration alist using `agent-shell-make-agent-config'."
152152
:install-instructions "See https://github.com/zed-industries/claude-agent-acp for installation."))
153153

154154
(defun agent-shell-anthropic-start-claude-code ()
155-
"Start an interactive Claude Code agent shell."
155+
"Start an interactive Claude Agent shell."
156156
(interactive)
157157
(agent-shell--dwim :config (agent-shell-anthropic-make-claude-code-config)
158158
:new-shell t))

agent-shell-diff.el

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ via `agent-shell-diff-mode-map'."
6868
(set-keymap-parent agent-shell-diff-mode-map nil)
6969
(setq buffer-read-only t))
7070

71+
(defun agent-shell-diff-kill-buffer (buffer)
72+
"Kill diff BUFFER, suppressing any `agent-shell-on-exit' callback.
73+
If BUFFER is not live, do nothing."
74+
(when (buffer-live-p buffer)
75+
(with-current-buffer buffer
76+
(setq agent-shell-on-exit nil))
77+
(kill-buffer buffer)))
78+
7179
(defun agent-shell-diff-accept-all ()
7280
"Accept all changes in the current diff buffer."
7381
(interactive)
@@ -90,6 +98,8 @@ using `agent-shell-diff-mode'. The buffer is read-only.
9098
9199
When the buffer is killed, calls ON-EXIT with no arguments.
92100
101+
Returns the newly created diff buffer.
102+
93103
Arguments:
94104
:OLD - Original string content
95105
:NEW - Modified string content
@@ -154,18 +164,15 @@ Arguments:
154164
(setq agent-shell-on-exit on-exit)
155165
(add-hook 'kill-buffer-hook
156166
(lambda ()
157-
(with-current-buffer diff-buffer
158-
(when agent-shell-on-exit
159-
(with-current-buffer calling-buffer
160-
(funcall on-exit))))
161-
(with-current-buffer calling-buffer
162-
;; Make sure give focus back to calling buffer on exit.
163-
(if (window-live-p calling-window)
164-
(if (eq (window-buffer calling-window) calling-buffer)
165-
;; Calling buffer still on calling window, just select it.
166-
(select-window calling-window)
167-
;; Calling buffer not on calling window, restore it.
168-
(progn
167+
(when (and agent-shell-on-exit
168+
(buffer-live-p calling-buffer))
169+
(with-current-buffer calling-buffer
170+
(funcall on-exit))
171+
;; Give focus back to calling buffer.
172+
(ignore-errors
173+
(if (window-live-p calling-window)
174+
(if (eq (window-buffer calling-window) calling-buffer)
175+
(select-window calling-window)
169176
(set-window-buffer calling-window calling-buffer)
170177
(select-window calling-window))))))
171178
nil t))
@@ -185,7 +192,8 @@ Arguments:
185192
"\\[agent-shell-diff-accept-all] accept "
186193
"\\[agent-shell-diff-reject-all] reject "
187194
"\\[agent-shell-diff-open-file] open "
188-
"\\[kill-current-buffer] quit")))))
195+
"\\[kill-current-buffer] quit"))))
196+
diff-buffer)
189197
(pop-to-buffer diff-buffer '((display-buffer-use-some-window
190198
display-buffer-same-window))))))
191199

agent-shell-heartbeat.el

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ Returns the heartbeat alist with the timer started."
8484
(map-put! heartbeat :heartbeat-timer
8585
(run-at-time 0 (/ 1.0 (map-elt heartbeat :beats-per-second))
8686
(lambda ()
87-
(map-put! heartbeat :status 'busy)
88-
(map-put! heartbeat :value
89-
(1+ (map-elt heartbeat :value)))
90-
(funcall (map-elt heartbeat :on-heartbeat)
91-
(map-elt heartbeat :value)
92-
(map-elt heartbeat :status))))))
87+
(when-let ((value (map-elt heartbeat :value)))
88+
(map-put! heartbeat :status 'busy)
89+
(map-put! heartbeat :value (1+ value))
90+
(funcall (map-elt heartbeat :on-heartbeat)
91+
(map-elt heartbeat :value)
92+
(map-elt heartbeat :status)))))))
9393
heartbeat))
9494

9595
(cl-defun agent-shell-heartbeat-stop (&key heartbeat)

agent-shell-ui.el

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ NAMESPACE-ID, BLOCK-ID, LABEL-LEFT, LABEL-RIGHT, and BODY are the keys."
5050
(cons :label-right (agent-shell-ui--string-or-nil label-right))
5151
(cons :body (agent-shell-ui--string-or-nil body))))
5252

53+
(defun agent-shell-ui--insert-read-only (text)
54+
"Insert TEXT as read-only output."
55+
(add-text-properties 0 (length text)
56+
'(read-only t front-sticky (read-only))
57+
text)
58+
(insert text))
59+
5360
(cl-defun agent-shell-ui-update-fragment (model &key append create-new on-post-process navigation expanded no-undo)
5461
"Update or add a fragment using MODEL.
5562
@@ -121,10 +128,10 @@ For existing blocks, the current expansion state is preserved unless overridden.
121128
;; Not found or create-new - insert new block
122129
(goto-char (point-max))
123130
(setq padding-start (point))
124-
(insert (agent-shell-ui--required-newlines 2))
131+
(agent-shell-ui--insert-read-only (agent-shell-ui--required-newlines 2))
125132
(setq block-start (point))
126133
(agent-shell-ui--insert-fragment model qualified-id expanded navigation)
127-
(insert "\n\n")
134+
(agent-shell-ui--insert-read-only "\n\n")
128135
(setq padding-end (point))))
129136
(when on-post-process
130137
(funcall on-post-process))
@@ -444,7 +451,7 @@ When NO-UNDO is non-nil, disable undo recording."
444451
(t
445452
(goto-char (point-max))
446453
(let ((padding-start (point)))
447-
(insert (agent-shell-ui--required-newlines 2))
454+
(agent-shell-ui--insert-read-only (agent-shell-ui--required-newlines 2))
448455
(let ((block-start (point)))
449456
(insert (apply #'propertize text props))
450457
(list (cons :block (list (cons :start block-start)

agent-shell-usage.el

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,18 @@ context window usage, and cost information after each agent response."
4646
:type 'boolean
4747
:group 'agent-shell)
4848

49-
(defcustom agent-shell-show-context-usage-indicator t
50-
"Non-nil to show the context usage indicator in the header and mode line.
49+
(defcustom agent-shell-show-context-usage-indicator 'detailed
50+
"Whether and how to show the context usage indicator.
5151
52-
The indicator displays context window usage as a vertical bar character,
53-
color-coded from green (low) to yellow (high) to red (critical).
52+
When set to t, displays a vertical bar character indicating
53+
fill level. When set to `detailed', displays a numeric format
54+
like \"➤ 29k/200k (29%%)\". When nil, no indicator is shown.
55+
56+
Color-coded: green (low), yellow (high), red (critical).
5457
Only appears when the ACP server provides usage information."
55-
:type 'boolean
58+
:type '(choice (const :tag "Hidden" nil)
59+
(const :tag "Bar" t)
60+
(const :tag "Detailed" detailed))
5661
:group 'agent-shell)
5762

5863
(cl-defun agent-shell--save-usage (&key state acp-usage)
@@ -192,9 +197,49 @@ When MULTILINE is non-nil, format as right-aligned labeled rows."
192197
'font-lock-face 'font-lock-comment-face)
193198
cost))))
194199

200+
(defun agent-shell--context-usage-face (percentage)
201+
"Return the face for context usage at PERCENTAGE.
202+
Green for normal, yellow for warning, red for critical."
203+
(cond
204+
((>= percentage 85) 'error)
205+
((>= percentage 60) 'warning)
206+
(t 'success)))
207+
208+
(defun agent-shell--context-usage-indicator-bar (usage context-used context-size)
209+
"Return a bar indicator for context USAGE.
210+
CONTEXT-USED and CONTEXT-SIZE are token counts."
211+
(let* ((percentage (/ (* 100.0 context-used) context-size))
212+
(indicator (cond
213+
((>= percentage 100) "")
214+
((>= percentage 87.5) "")
215+
((>= percentage 75) "")
216+
((>= percentage 62.5) "")
217+
((>= percentage 50) "")
218+
((>= percentage 37.5) "")
219+
((>= percentage 25) "")
220+
((> percentage 0) "")
221+
(t nil))))
222+
(when indicator
223+
(propertize indicator
224+
'face (agent-shell--context-usage-face percentage)
225+
'help-echo (agent-shell--format-usage usage)))))
226+
227+
(defun agent-shell--context-usage-indicator-detailed (usage context-used context-size)
228+
"Return a detailed indicator for context USAGE.
229+
CONTEXT-USED and CONTEXT-SIZE are token counts.
230+
Format: \"29k/200k (29%)\"."
231+
(let ((percentage (/ (* 100.0 context-used) context-size)))
232+
(propertize (format "%s/%s (%.0f%%%%)"
233+
(agent-shell--format-number-compact context-used)
234+
(agent-shell--format-number-compact context-size)
235+
percentage)
236+
'face (agent-shell--context-usage-face percentage)
237+
'help-echo (agent-shell--format-usage usage))))
238+
195239
(defun agent-shell--context-usage-indicator ()
196-
"Return a single character indicating context usage percentage.
197-
Uses Unicode vertical block characters to show fill level.
240+
"Return a string indicating context usage percentage.
241+
Dispatches to bar or detailed indicator based on
242+
`agent-shell-show-context-usage-indicator'.
198243
Only returns an indicator if enabled and usage data is available."
199244
(when-let* ((agent-shell-show-context-usage-indicator)
200245
((agent-shell--usage-has-data-p (map-elt (agent-shell--state) :usage)))
@@ -206,26 +251,11 @@ Only returns an indicator if enabled and usage data is available."
206251
(propertize "?"
207252
'face 'warning
208253
'help-echo (agent-shell--format-usage usage))
209-
(let* ((percentage (/ (* 100.0 context-used) context-size))
210-
;; Unicode vertical block characters from empty to full
211-
(indicator (cond
212-
((>= percentage 100) "") ; Full
213-
((>= percentage 87.5) "")
214-
((>= percentage 75) "")
215-
((>= percentage 62.5) "")
216-
((>= percentage 50) "")
217-
((>= percentage 37.5) "")
218-
((>= percentage 25) "")
219-
((> percentage 0) "")
220-
(t nil))) ; Return nil for no usage
221-
(face (cond
222-
((>= percentage 85) 'error) ; Red for critical
223-
((>= percentage 60) 'warning) ; Yellow/orange for warning
224-
(t 'success)))) ; Green for normal
225-
(when indicator
226-
(propertize indicator
227-
'face face
228-
'help-echo (agent-shell--format-usage usage)))))))
254+
(pcase agent-shell-show-context-usage-indicator
255+
('detailed
256+
(agent-shell--context-usage-indicator-detailed usage context-used context-size))
257+
(_
258+
(agent-shell--context-usage-indicator-bar usage context-used context-size))))))
229259

230260
(provide 'agent-shell-usage)
231261
;;; agent-shell-usage.el ends here

0 commit comments

Comments
 (0)