Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a45a08b
Add agent config symlinks for multi-IDE support
timvisher-dd Mar 20, 2026
f3eab31
Add CI workflow and local test runner
timvisher-dd Mar 20, 2026
d51d87e
Fix keymap quoting, test buffer-local bindings, and byte-compiler war…
timvisher-dd Mar 20, 2026
9d4ef02
Add runtime buffer invariants library
timvisher-dd Mar 20, 2026
331bb41
Add ACP meta helpers for toolResponse and terminal_output extraction
timvisher-dd Mar 20, 2026
4e5481f
Add streaming tool output handler with dedup
timvisher-dd Mar 20, 2026
1c5cea9
Integrate streaming dedup, insert-cursor, and process-mark preservation
timvisher-dd Mar 20, 2026
cb357ac
Update documentation for streaming dedup and live-validate workflow
timvisher-dd Mar 20, 2026
8635cb9
Update Claude Code icon
xenodium Mar 19, 2026
e4d65f4
Fixing auth-source-pass-get usage in README #434
xenodium Mar 19, 2026
4e1bc96
Try to include file name in permission title if missing #415
xenodium Mar 19, 2026
314b2b4
Adds agent-shell-mock-agent.el (needs mock-acp binary installed)
xenodium Mar 19, 2026
a0044ec
Adding experimental incoming session/pushPrompt
xenodium Mar 19, 2026
0710b49
Disable image pasting when running in tui #435
xenodium Mar 19, 2026
4e6ddad
Renaming experimental session/pushPrompt to session/push
xenodium Mar 20, 2026
a24ebb9
Adding more to CONTRIBUTING.org
xenodium Mar 20, 2026
4892364
Reject session/push requests when busy
xenodium Mar 20, 2026
3954508
Show activity indicator while receiving push and ignore out of bound …
xenodium Mar 21, 2026
1500196
Adding https://github.com/zackattackz/agent-shell-notifications to RE…
xenodium Mar 21, 2026
6f3ed77
Adds agent-shell-new-downloads-shell and agent-shell-new-temp-shell
xenodium Mar 22, 2026
307dce6
Add related project `agent-circus` to README.org
rpoisel Mar 22, 2026
28f1fb7
Make id more evident for available models and modes #452
xenodium Mar 24, 2026
0d639cc
Ensure that viewport compiles
martenlienen Mar 24, 2026
184b4c7
Use project-name instead of default-directory in header
bcc32 Mar 23, 2026
07db3a2
Prefer cache directory over tmp for caching
martenlienen Mar 25, 2026
a334503
Fix for structured input from toolCall.rawInput.plan
timfel Mar 20, 2026
7c40d53
Make agent-shell--format-plan more forgiving #438
xenodium Mar 25, 2026
12023b9
Enable expanding region/context text for editing #459
xenodium Mar 25, 2026
2fbe9f7
Fixes #455: unhandled method returns an error, unblocking client
0x6362 Mar 25, 2026
0093e35
Text header/modeline improvements #448
xenodium Mar 25, 2026
25a6178
Fixing checkdoc warning
xenodium Mar 25, 2026
313c0bb
Ensure button border does not leak into subsequently inserted text
xenodium Mar 25, 2026
b94cd0c
Add wl-paste as a Wayland image handler
martenlienen Mar 25, 2026
ea45407
Fix restart using wrong default-directory
zackattackz Mar 24, 2026
b13a9e8
Add documentation about the AOuth Anthropic authentication
chemtov Feb 26, 2026
2a78524
Fix header text invisible when font-get :size returns 0
Mar 25, 2026
8fa5b08
Replacing or + when-let* with if-let* #463
xenodium Mar 25, 2026
77e747b
Fixes refocus after diff regression #466
xenodium Mar 26, 2026
a8dca5d
Do not create a file if no image in Wayland clipboard
martenlienen Mar 26, 2026
6256877
Adding README entry for slash commands
xenodium Mar 26, 2026
3250af0
Shortening some agent names
xenodium Mar 27, 2026
f6150b6
Display key bindings in menu tooltips #448
xenodium Mar 27, 2026
f600ce8
Adding agent-shell-bookmark to related packages section
xenodium Mar 27, 2026
ed5d26a
Caching project files completions for improved performance
Gleek Mar 27, 2026
2f51417
Handle non-text content in user_message_chunk during session load
Gleek Mar 29, 2026
1af38c5
Fall back to "unknown" when type is not known #477
xenodium Mar 29, 2026
bcf36bb
Fix restart test to work in batch mode
timvisher-dd Mar 31, 2026
95c8c17
Fix extra closing paren in permission-title execute test
timvisher-dd Mar 31, 2026
370dca7
Add table rendering regression test
timvisher-dd Apr 2, 2026
773099b
Strengthen table tests with overlay structure and mid-stream assertions
timvisher-dd Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .agents/commands/live-validate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Live validation of agent-shell rendering

Run a live agent-shell session in batch mode and verify the buffer output.
This exercises the full rendering pipeline with real ACP traffic — the only
way to catch ordering, marker, and streaming bugs that unit tests miss.

## Prerequisites

- `ANTHROPIC_API_KEY` must be available (via `op run` / 1Password)
- `timvisher_emacs_agent_shell` must be on PATH
- Dependencies (acp.el-plus, shell-maker) in sibling worktrees or
overridden via env vars

## How to run

```bash
cd "$(git rev-parse --show-toplevel)"
timvisher_agent_shell_checkout=. \
timvisher_emacs_agent_shell claude --batch \
1>/tmp/agent-shell-live-stdout.log \
2>/tmp/agent-shell-live-stderr.log
```

Stderr shows heartbeat lines every 30 seconds. Stdout contains the
full buffer dump once the agent turn completes.

## What to check in the output

1. **Fragment ordering**: tool call drawers should appear in
chronological order (the order the agent invoked them), not
reversed. Look for `▶` lines — their sequence should match the
logical execution order.

2. **No duplicate content**: each tool call output should appear
exactly once. Watch for repeated blocks of identical text.

3. **Prompt position**: the prompt line (`agent-shell>`) should
appear at the very end of the buffer, after all fragments.

4. **Notices placement**: `[hook-trace]` and other notice lines
should appear in a `Notices` section, not interleaved with tool
call fragments.

## Enabling invariant checking

To run with runtime invariant assertions (catches corruption as it
happens rather than after the fact):

```elisp
;; Add to your init or eval before the session starts:
(setq agent-shell-invariants-enabled t)
```

When an invariant fires, a `*agent-shell invariant*` buffer pops up
with a debug bundle and recommended analysis prompt.

## Quick validation one-liner

```bash
cd "$(git rev-parse --show-toplevel)" && \
timvisher_agent_shell_checkout=. \
timvisher_emacs_agent_shell claude --batch \
1>/tmp/agent-shell-live.log 2>&1 && \
grep -n '▶' /tmp/agent-shell-live.log | head -20
```

If the `▶` lines are in logical order and the exit code is 0, the
rendering pipeline is healthy.
1 change: 1 addition & 0 deletions .claude
1 change: 1 addition & 0 deletions .codex
1 change: 1 addition & 0 deletions .gemini
95 changes: 95 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,101 @@ jobs:
fi
fi

agent-symlinks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Verify agent config symlinks
run: |
ok=true
for dir in .claude .codex .gemini; do
target=$(readlink "${dir}" 2>/dev/null)
if [[ "${target}" != ".agents" ]]; then
echo "::error::${dir} should symlink to .agents but points to '${target:-<missing>}'"
ok=false
fi
done
for md in CLAUDE.md CODEX.md GEMINI.md; do
target=$(readlink "${md}" 2>/dev/null)
if [[ "${target}" != "AGENTS.md" ]]; then
echo "::error::${md} should symlink to AGENTS.md but points to '${target:-<missing>}'"
ok=false
fi
done
if ! [[ -d .agents/commands ]]; then
echo "::error::.agents/commands/ directory missing"
ok=false
fi
if [[ "${ok}" != "true" ]]; then
exit 1
fi
echo "All agent config symlinks verified."

dependency-dag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Verify require graph is a DAG (no cycles)
run: |
# Build the set of project-internal modules from *.el filenames.
declare -A project_modules
for f in *.el; do
mod="${f%.el}"
project_modules["${mod}"]=1
done

# Parse (require 'foo) from each file and build an adjacency list.
# Only track edges where both ends are project-internal.
declare -A edges # edges["a"]="b c" means a requires b and c
for f in *.el; do
mod="${f%.el}"
deps=""
while IFS= read -r dep; do
if [[ -n "${project_modules[$dep]+x}" ]]; then
deps="${deps} ${dep}"
fi
done < <(sed -n "s/^.*(require '\\([a-zA-Z0-9_-]*\\)).*/\\1/p" "$f")
edges["${mod}"]="${deps}"
done

# DFS cycle detection.
declare -A color # white=unvisited, gray=in-stack, black=done
found_cycle=""
cycle_path=""

dfs() {
local node="$1"
local path="$2"
color["${node}"]="gray"
for neighbor in ${edges["${node}"]}; do
if [[ "${color[$neighbor]:-white}" == "gray" ]]; then
found_cycle=1
cycle_path="${path} -> ${neighbor}"
return
fi
if [[ "${color[$neighbor]:-white}" == "white" ]]; then
dfs "${neighbor}" "${path} -> ${neighbor}"
if [[ -n "${found_cycle}" ]]; then
return
fi
fi
done
color["${node}"]="black"
}

for mod in "${!project_modules[@]}"; do
if [[ "${color[$mod]:-white}" == "white" ]]; then
dfs "${mod}" "${mod}"
if [[ -n "${found_cycle}" ]]; then
echo "::error::Dependency cycle detected: ${cycle_path}"
exit 1
fi
fi
done
echo "Dependency graph is a DAG — no cycles found."

test:
runs-on: ubuntu-latest
steps:
Expand Down
11 changes: 10 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,18 @@ When adding or changing features:

1. **Run `bin/test`.** Set `acp_root` and `shell_maker_root` if the
deps aren't in sibling worktrees. This runs byte-compilation, ERT
tests, and checks that `README.org` was updated when code changed.
tests, dependency DAG check, and checks that `README.org` was
updated when code changed.
2. **Keep the README features list current.** The "Features on top of
agent-shell" section in `README.org` must be updated whenever code
changes land. Both `bin/test` and CI enforce this — changes to `.el`
or `tests/` files without a corresponding `README.org` update will
fail.
3. **Live-validate rendering changes.** For changes to the rendering
pipeline (fragment insertion, streaming, markers, UI), run a live
batch session to verify fragment ordering and buffer integrity.
See `.agents/commands/live-validate.md` for details. The key command:
```bash
timvisher_agent_shell_checkout=. timvisher_emacs_agent_shell claude --batch \
1>/tmp/agent-shell-live.log 2>&1
```
1 change: 1 addition & 0 deletions CODEX.md
31 changes: 31 additions & 0 deletions CONTRIBUTING.org
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,20 @@ Overall, try to flatten things. Look out for unnecessarily nested blocks and fla
buffer)
#+end_src

Similarly, flatten =when-let= + nested =when= by using boolean guard clauses as bindings in =when-let=.

#+begin_src emacs-lisp :lexical no
;; Avoid
(when-let ((filename (file-name-nondirectory filepath)))
(when (not (string-empty-p filename))
(do-something filename)))

;; Prefer (use boolean binding as guard clause)
(when-let ((filename (file-name-nondirectory filepath))
((not (string-empty-p filename))))
(do-something filename))
#+end_src

** Prefer =let= and =when-let= over =let*= and =when-let*=

Only use the =*= variants when bindings depend on each other. LLMs tend to default to =let*= and =when-let*= even when there are no dependencies between bindings.
Expand Down Expand Up @@ -231,3 +245,20 @@ Tests live under the tests directory:
Opening any file under the =tests= directory will load the =agent-shell-run-all-tests= command.

Run tests with =M-x agent-shell-run-all-tests=.

*** From the command line

=bin/test= runs the full ERT suite in batch mode. By default it
expects =acp.el= and =shell-maker= to be checked out as sibling
worktrees (e.g. =…/acp.el/main= and =…/shell-maker/main= next to
=…/agent-shell/main=). Override the paths with environment variables
if your layout differs:

#+begin_src bash
acp_root=~/path/to/acp.el \
shell_maker_root=~/path/to/shell-maker \
bin/test
#+end_src

The script validates that both dependencies are readable and exits
with a descriptive error if either is missing.
61 changes: 49 additions & 12 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ A soft fork of [[https://github.com/xenodium/agent-shell][agent-shell]] with ext
* Features on top of agent-shell

- CI workflow and local test runner ([[https://github.com/timvisher-dd/agent-shell-plus/pull/1][#1]], [[https://github.com/timvisher-dd/agent-shell-plus/pull/6][#6]], [[https://github.com/timvisher-dd/agent-shell-plus/pull/8][#8]])
- Byte-compilation of all =.el= files ([[https://github.com/timvisher-dd/agent-shell-plus/pull/1][#1]])
- ERT test suite ([[https://github.com/timvisher-dd/agent-shell-plus/pull/1][#1]])
- README update check when code changes ([[https://github.com/timvisher-dd/agent-shell-plus/pull/4][#4]])
- Dependency DAG check (=require= graph must be acyclic) ([[https://github.com/timvisher-dd/agent-shell-plus/pull/7][#7]])
- Desktop notifications when the prompt is idle and waiting for input ([[https://github.com/timvisher-dd/agent-shell-plus/pull/2][#2]], [[https://github.com/timvisher-dd/agent-shell-plus/pull/8][#8]])
- Per-shell debug logging infrastructure ([[https://github.com/timvisher-dd/agent-shell-plus/pull/2][#2]])
- Regression tests for shell buffer selection ordering ([[https://github.com/timvisher-dd/agent-shell-plus/pull/3][#3]])
- CI check that README.org is updated when code changes ([[https://github.com/timvisher-dd/agent-shell-plus/pull/4][#4]])
- Usage tests and defense against ACP =used > size= bug ([[https://github.com/timvisher-dd/agent-shell-plus/pull/5][#5]])
- Streaming tool output with dedup: advertise =_meta.terminal_output= capability, handle incremental chunks from codex-acp and batch results from claude-agent-acp, strip =<persisted-output>= tags, fix O(n²) rendering, and partial-overlap thought dedup ([[https://github.com/timvisher-dd/agent-shell-plus/pull/7][#7]])
- DWIM context insertion: inserted context lands at the prompt and fragment updates no longer drag process-mark past it ([[https://github.com/timvisher-dd/agent-shell-plus/pull/7][#7]])
- Runtime buffer invariant checking with event tracing and violation debug bundles ([[https://github.com/timvisher-dd/agent-shell-plus/pull/7][#7]])

-----

Expand Down Expand Up @@ -53,15 +60,18 @@ Watch on [[https://www.youtube.com/watch?v=R2Ucr3amgGg][YouTube]]

We now have a handful of additional packages to extend the =agent-shell= experience:

- [[https://github.com/nineluj/agent-review][agent-review]]: Code review interface for =agent-shell=.
- [[https://github.com/ultronozm/agent-shell-attention.el][agent-shell-attention.el]]: Mode-line attention tracker for =agent-shell=.
- [[https://github.com/jethrokuan/agent-shell-manager][agent-shell-manager]]: Tabulated view and management of =agent-shell= buffers.
- [[https://github.com/xenodium/emacs-skills][emacs-skills]]: Claude Agent skills for Emacs.
- [[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.
- [[https://github.com/Embedded-Focus/agent-circus][agent-circus]]: Run AI coding agents in sandboxed Docker containers.
- [[https://github.com/cmacrae/agent-shell-sidebar][agent-shell-sidebar]]: A sidebar add-on for =agent-shell=.
- [[https://github.com/dcluna/agent-shell-bookmark][agent-shell-bookmark]]: Bookmark support for agent-shell sessions.
- [[https://github.com/gveres/agent-shell-workspace][agent-shell-workspace]]: Dedicated tab-bar workspace for managing multiple =agent-shell= sessions.
- [[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.
- [[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.
- [[https://github.com/jethrokuan/agent-shell-manager][agent-shell-manager]]: Tabulated view and management of =agent-shell= buffers.
- [[https://github.com/nineluj/agent-review][agent-review]]: Code review interface for =agent-shell=.
- [[https://github.com/ultronozm/agent-shell-attention.el][agent-shell-attention.el]]: Mode-line attention tracker for =agent-shell=.
- [[https://github.com/xenodium/agent-shell-knockknock][agent-shell-knockknock]]: Notifications for =agent-shell= via [[https://github.com/konrad1977/knockknock][knockknock.el]].
- [[https://github.com/xenodium/emacs-skills][emacs-skills]]: Claude Agent skills for Emacs.
- [[https://github.com/zackattackz/agent-shell-notifications][agent-shell-notifications]]: Desktop notifications for =agent-shell= events.
- [[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.

* Icons

Expand Down Expand Up @@ -212,7 +222,7 @@ Pass environment variables to the spawned agent process by customizing the `agen
#+begin_src emacs-lisp
(setq agent-shell-anthropic-claude-environment
(agent-shell-make-environment-variables
"ANTHROPIC_API_KEY" (auth-source-pass-get "secret" "anthropic-api-key")
"ANTHROPIC_API_KEY" (auth-source-pass-get 'secret "anthropic-api-key")
"HTTPS_PROXY" "http://proxy.example.com:8080"))
#+end_src

Expand All @@ -221,7 +231,7 @@ Pass environment variables to the spawned agent process by customizing the `agen
By default, the agent process starts with a minimal environment. To inherit environment variables from the parent Emacs process, use the `:inherit-env t` parameter in `agent-shell-make-environment-variables`:

#+begin_src emacs-lisp
(setenv "ANTHROPIC_API_KEY" (auth-source-pass-get "secret" "anthropic-api-key"))
(setenv "ANTHROPIC_API_KEY" (auth-source-pass-get 'secret "anthropic-api-key"))

(setq agent-shell-anthropic-claude-environment
(agent-shell-make-environment-variables :inherit-env t))
Expand Down Expand Up @@ -268,7 +278,20 @@ For API key authentication:
;; With function
(setq agent-shell-anthropic-authentication
(agent-shell-anthropic-make-authentication
:api-key (lambda () (auth-source-pass-get "secret" "anthropic-api-key"))))
:api-key (lambda () (auth-source-pass-get 'secret "anthropic-api-key"))))
#+end_src

For OAuth token authentication (the =CLAUDE_CODE_OAUTH_TOKEN= we get from =claude setup-token=):

#+begin_src emacs-lisp
;; With string
(setq agent-shell-anthropic-authentication
(agent-shell-anthropic-make-authentication :oauth "your-oauth-token-here"))

;; With function
(setq agent-shell-anthropic-authentication
(agent-shell-anthropic-make-authentication
:oauth (lambda () (auth-source-pass-get "secret" "anthropic-oauth-token"))))
#+end_src

For alternative Anthropic-compatible API endpoints, configure via environment variables:
Expand Down Expand Up @@ -300,7 +323,7 @@ For API key authentication:
;; With function
(setq agent-shell-google-authentication
(agent-shell-google-make-authentication
:api-key (lambda () (auth-source-pass-get "secret" "google-api-key"))))
:api-key (lambda () (auth-source-pass-get 'secret "google-api-key"))))
#+end_src

For Vertex AI authentication:
Expand Down Expand Up @@ -329,7 +352,7 @@ For API key authentication:
;; With function
(setq agent-shell-openai-authentication
(agent-shell-openai-make-authentication
:api-key (lambda () (auth-source-pass-get "secret" "openai-api-key"))))
:api-key (lambda () (auth-source-pass-get 'secret "openai-api-key"))))
#+end_src

*** Goose
Expand All @@ -344,7 +367,7 @@ For OpenAI API key authentication:
;; With function
(setq agent-shell-goose-authentication
(agent-shell-make-goose-authentication
:openai-api-key (lambda () (auth-source-pass-get "secret" "openai-api-key"))))
:openai-api-key (lambda () (auth-source-pass-get 'secret "openai-api-key"))))
#+end_src

*** Qwen Code
Expand Down Expand Up @@ -513,6 +536,13 @@ For example, to store data under =user-emacs-directory= instead of the project t

This stores data at a path like =~/.emacs.d/agent-shell/home-user-src-myproject/screenshots/=.

*** Screenshots from clipboard

You can send a screenshot from your clipboard to your shell with =agent-shell-send-clipboard-image=. Call with =C-u= to =agent-shell-send-clipboard-image-to= to select from your shells. agent-shell relies on external programs to write an image from clipboard to file as configured in =agent-shell-clipboard-image-handlers=. Preconfigured handlers are
- =wl-paste= for Wayland desktops,
- =xclip= for Xorg,
- =pngpaste= for MacOS.

*** Inhibiting minor modes during file writes

Some minor modes (for example, =aggressive-indent-mode=) can interfere with an agent's edits. Agent Shell can temporarily disable selected per-buffer minor modes while applying edits.
Expand Down Expand Up @@ -805,6 +835,13 @@ Please read through this section before filing issues or feature requests. I won
- *Your agent-shell config*: Share any relevant =agent-shell= variable settings from your Emacs config.
- *Profiling data* (for performance issues): Use =M-x profiler-start=, reproduce the issue, then =M-x profiler-report= (and =M-x profiler-stop=). Share the report.

** Why doesn't =agent-shell= offer all slash commands available in CLI agent?

=agent-shell= can only offer the slash commands advertised by the agent via [[https://agentclientprotocol.com][Agent Client Protocol]]. To view what's exposed by your agent, expand the "Available /commands" section. Is the command you're after missing? Please consider filing a feature-request with the respective agent (ie. Gemini CLI) or their ACP layer (claude-code-acp).

[[file:slash-commands.png]]


** Can you add support for another agent?

Does the agent support ACP ([[https://agentclientprotocol.com][Agent Client Protocol]])? If so, =agent-shell= can likely support this agent. Some agents have ACP support built-in (like [[https://github.com/google-gemini/gemini-cli][gemini-cli]]). Others require a separate ACP package (like [[https://github.com/zed-industries/claude-code-acp][claude-code-acp]] for [[https://github.com/anthropics/claude-code][claude-code]]). When filing a feature request to add a new agent, please include a link to the project supporting [[https://agentclientprotocol.com][Agent Client Protocol]] (built-in or otherwise).
Expand Down
Loading
Loading