大模型
全球精选 ·
@dTal
El Yayster:让本地LLM驻留Emacs的代理框架
El Yayster是一个单文件Emacs包,通过OpenAI兼容接口(如Ollama)让LLM代理感知并操作Emacs环境,所有修改操作需用户批准。它支持本地模型,提供工具调用、上下文感知和流式输出,但尚未经过广泛验证。
AI推荐理由 该项目提出了一种新颖的Emacs与LLM集成方式,强调本地优先和用户控制,但作为GitHub项目,缺乏实际使用反馈和验证,且描述带有营销色彩。
70
评论 6
社区积分 34
正文
El Yayster
Emacs。Lisp。一个狂野的小小肯定:给本地LLM钥匙。
大多数“Emacs中的LLM”包让Emacs成为与模型对话的嘴:你输入,它回复到缓冲区。El Yayster反转了这一点。它让Emacs成为模型栖居的身体——代理感知你的实时环境,并通过受控的Emacs Lisp对其采取行动。决定→调用工具→读取结果→重复,针对任何兼容OpenAI的端点。本地Ollama是快乐路径。无需云。
名字既是玩笑也是论点。El是定冠词——Yayster——同时也是el,即Emacs Lisp。其余部分是挑战:一种无忧无虑、热爱玩乐的心态,那种看着eval和M-x说“是”的心态,把模型也安置在那里。代理起草;你仍然提交。
一个自包含文件:yayster.el。无需ELPA包——cl-lib、json、subr-x、curl二进制文件,以及一个可访问的模型。
为何不同
情境化。每一轮,代理都会被告知你打开了哪些缓冲区、当前模式和工作目录。它知道自己在Emacs中,并从内部说话。
它行动,受控。像eval_elisp、write_buffer和run_command这样的能力让代理操作编辑器——但每个修改操作都先征求你的许可。代理起草;你提交。
自我发现。apropos和describe让它探索Emacs自身的自我文档。它的工具集从编辑器本身成长。
本地优先且模型可移植。任何兼容OpenAI的/chat/completions端点。已在本地模型(Qwen、GLM)上测试,无需更改代码。
非阻塞。请求在curl子进程中运行;Emacs保持响应。进度流入*yayster*缓冲区。
可观察。*yayster*标题行显示实时模型、上下文窗口占用率(从Ollama的/api/show自动检测)以及每轮/会话令牌计数。
安装
将yayster.el放在磁盘某处。
添加到你的init中:
(add-to-list 'load-path "/path/to/yayster.el") ; 目录
(require 'yayster)
(yayster-awaken)
;; 可选:快捷键
(global-set-key (kbd "C-c y") #'yayster-step)
(global-set-key (kbd "C-c Y") #'yayster-use-host)
将其指向你的模型(默认为http://localhost:11434/v1/chat/completions):
(setq yayster-endpoint "http://localhost:11434/v1/chat/completions"
yayster-model "qwen3:8b")
要求
Emacs 28.1+
curl在你的PATH中(macOS内置;Linux上apt install curl)
一个兼容OpenAI的聊天端点。最简单的是Ollama:
ollama pull qwen3:8b然后它在localhost:11434上服务。
使用
M-x yayster-step(或C-c y)——用简单英语提问。
观察*yayster*;答案也会在迷你缓冲区中回显。
工具在你发出该轮时当前所在的缓冲区和目录中运行。
M-x yayster-use-host(或C-c Y)——在yayster-hosts中的端点之间切换。
M-x yayster-abort——终止挂起的轮次,取消临时文件链接,清除忙碌标志。
可选:模式行指示器
yayster-mode-line.el显示当前主机、模型,并在轮次进行中显示脉冲:
⌬ local qwen3:8b (空闲)
⌬ local qwen3:8b ◐ (轮次正在运行)
(require 'yayster-mode-line) ;; 安装自身到mode-line-format
它通过轮次开始/结束、主机切换、中止和安全重新武装的建议刷新——无轮询。使用M-x yayster-mode-uninstall移除它。
尝试:
“我打开了哪些缓冲区?” → 只读,即时
“统计匹配org-agenda的函数。” → 代理发现并调用apropos
“给我我的主目录的目录列表,最近5个。” → run_command
(你会被要求批准)
能力
能力
修改?
作用
read_buffer
否
读取缓冲区文本
list_buffers
否
列出缓冲区及主模式
apropos
否
查找匹配模式的函数(自我发现)
describe
否
读取函数的文档字符串
eval_elisp
是
求值Emacs Lisp表达式
write_buffer
是
替换缓冲区内容
run_command
是
运行shell命令
只读能力自动批准(yayster-auto-approve-readonly,默认开启)。
修改能力总是通过yayster-confirm-function提示。提示包括能力名称和完整参数负载——将运行的命令或elisp,不截断——因此重新绑定到y-or-n-p并非盲目。相同文本显示在*yayster-permission*中。在图形框架上:允许、YOLO(停止询问本会话剩余部分;使用M-x yayster-safety-on重新武装)、拒绝。在终端上:[y]/[n]/[!]。C-g /取消即拒绝。
run_command在yayster-command-timeout秒后超时(默认30),并将输出限制在yayster-command-max-bytes。
ReAct协议:ACTION: / ARGS: 必须各自开始一行;FINAL: 行结束轮次且永不执行,即使ACTION对也被引用。格式错误的JSON ARGS不是工具调用。
⚠️ 安全
修改工具(eval_elisp、write_buffer、run_command)总是提示(允许/拒绝)。提示显示完整命令或elisp——不截断。默认安装即该门——在允许之前阅读负载。
YOLO是选择加入且会话范围的,直到M-x yayster-safety-on。它不是默认。演示包时提示开启。
只读工具(read_buffer、list_buffers)自动批准,仍可将任何打开的缓冲区(包括秘密)发送给模型。这是重点,也是隐患。门只在你阅读你批准的内容时保护你。
如果你为托管API设置yayster-api-key,承载令牌写入模式0600的临时文件,并通过-H @FILE传递给curl。它永远不会出现在ps中。
工作原理
五个小部分,都在一个文件中:
能力——受控Elisp函数的注册表(代理的手)。
权限门——只读与修改;修改总是询问。
情境提示——实时环境+工具清单。
代理循环——ReAct(ACTION: / ARGS: / FINAL:)针对你的端点。
awaken——启动时安置El Yayster。
这是v0,故意很小——易于通读,易于扩展。
测试
emacs -Q --batch -L . -l yayster.el -l test/yayster-tests
el \
-f ert-run-tests-batch-and-exit
路线图
原生工具/函数调用(JSON-Schema工具)作为ReAct文本协议的替代
令牌级流式传输到*yayster*
自动主机故障转移
org-roam支持的记忆(记住/回忆作为知识图谱)
许可证
MIT——见LICENSE。
查看原文(中文正文为 AI 翻译)
El Yayster
The Emacs. The Lisp. A wild little yes: give a local LLM the keys.
Most "LLM in Emacs" packages make Emacs a mouth that talks to a model: you type,
it replies into a buffer. El Yayster inverts that. It makes Emacs a body the
model inhabits — the agent perceives your live environment, and acts on it
through gated Emacs Lisp. Decide → call a tool → read the result → repeat, against
any OpenAI-compatible endpoint. Local Ollama is the happy path. No cloud required.
The name is the joke and the thesis. El is the definite article — the Yayster —
and it is also el, as in Emacs Lisp. The rest is the dare: a carefree, fun-loving
mindset, the kind that looks at eval and M-x and says yes, seat the model
there too. The agent drafts; you still commit.
One self-contained file: yayster.el. No ELPA packages — cl-lib, json,
subr-x, the curl binary, and a reachable model.
Why it's different
Situated. Every turn, the agent is told what buffers you have open, your current
mode, and your working directory. It knows it's in Emacs and speaks from inside it.
It acts, gated. Capabilities like eval_elisp, write_buffer, and run_command
let the agent operate the editor — but every mutating action asks your permission
first. The agent drafts; you commit.
Self-discovering. apropos and describe let it explore Emacs's own
self-documentation. Its toolset grows from the editor itself.
Local-first & model-portable. Any OpenAI-compatible /chat/completions
endpoint. Tested across local models (Qwen, GLM) with no code changes.
Non-blocking. Requests run in a curl subprocess; Emacs stays responsive.
Progress streams into a *yayster* buffer.
Observable. The *yayster* header line shows the live model, context-window
occupancy (auto-detected from Ollama's /api/show), and per-turn / session token
counts.
Install
Drop yayster.el somewhere on disk.
Add to your init:
(add-to-list 'load-path "/path/to/yayster.el") ; the directory
(require 'yayster)
(yayster-awaken)
;; Optional: quick keys
(global-set-key (kbd "C-c y") #'yayster-step)
(global-set-key (kbd "C-c Y") #'yayster-use-host)
Point it at your model (defaults to http://localhost:11434/v1/chat/completions):
(setq yayster-endpoint "http://localhost:11434/v1/chat/completions"
yayster-model "qwen3:8b")
Requirements
Emacs 28.1+
curl on your PATH (built into macOS; apt install curl on Linux)
An OpenAI-compatible chat endpoint. Easiest is Ollama:
ollama pull qwen3:8b then it serves on localhost:11434.
Use
M-x yayster-step (or C-c y) — ask in plain English.
Watch *yayster*; the answer also echoes in the minibuffer.
Tools run in the buffer and directory that were current when you issued the turn.
M-x yayster-use-host (or C-c Y) — switch between endpoints in yayster-hosts.
M-x yayster-abort — kill a hung turn, unlink temp files, clear the busy flag.
Optional: mode-line indicator
yayster-mode-line.el shows the current host, model, and a pulse while a turn
is in flight:
⌬ local qwen3:8b (idle)
⌬ local qwen3:8b ◐ (a turn is running)
(require 'yayster-mode-line) ;; installs itself into mode-line-format
It refreshes via advice on turn start/finish, host switch, abort, and safety
re-arm — no polling. Remove it with M-x yayster-mode-uninstall.
Try:
"What buffers do I have open?" → read-only, instant
"Count the functions matching org-agenda." → the agent discovers + calls apropos
"Give me a directory listing of my home dir, 5 most recent." → run_command
(you'll be asked to approve it)
Capabilities
Capability
Mutating?
What it does
read_buffer
no
Read a buffer's text
list_buffers
no
List buffers + major modes
apropos
no
Find functions matching a pattern (self-discovery)
describe
no
Read a function's docstring
eval_elisp
yes
Evaluate an Emacs Lisp expression
write_buffer
yes
Replace a buffer's contents
run_command
yes
Run a shell command
Read-only capabilities auto-approve (yayster-auto-approve-readonly, default on).
Mutating capabilities always prompt via yayster-confirm-function. The
prompt includes the capability name and the full argument payload — the
command or elisp that will run, no truncation — so a rebind to y-or-n-p is
not blind. The same text is shown in *yayster-permission*. On a graphical
frame: Allow, YOLO (stop asking for the rest of the session; re-arm with
M-x yayster-safety-on), and Deny. On a terminal: [y]/[n]/[!]. C-g /
cancel is deny.
run_command times out after yayster-command-timeout seconds (default 30) and
caps output at yayster-command-max-bytes.
The ReAct protocol: ACTION: / ARGS: must start their own lines; a FINAL: line
ends the turn and is never executed, even if an ACTION pair is also quoted. Malformed
JSON ARGS is not a tool call.
⚠️ Safety
Mutating tools (eval_elisp, write_buffer, run_command) always prompt
(Allow / Deny). The prompt shows the full command or elisp — no truncation.
Default install is that gate — read the payload before you Allow.
YOLO is opt-in and session-scoped until M-x yayster-safety-on. It is not
the default. Demo the package with prompts on.
Read-only tools (read_buffer, list_buffers) auto-approve and can still send
any open buffer (including secrets) to the model. That is the point, and also
the footgun. The gate only protects you if you read what you approve.
If you set yayster-api-key for a hosted API, the bearer token is written to
a mode-0600 temp file and passed to curl as -H @FILE. It never appears on ps.
How it works
Five small pieces, all in one file:
Capabilities — a registry of gated Elisp functions (the agent's hands).
Permission gate — read-only vs. mutating; mutating always asks.
Situating prompt — live environment + a tool manifest.
Agent loop — ReAct (ACTION: / ARGS: / FINAL:) against your endpoint.
awaken — seats El Yayster at startup.
It's a v0 and deliberately small — easy to read end to end, easy to extend.
Tests
emacs -Q --batch -L . -l yayster.el -l test/yayster-tests.el \
-f ert-run-tests-batch-and-exit
Roadmap
Native tool/function-calling (JSON-Schema tools) as an alternative to the ReAct text protocol
Token-level streaming into *yayster*
Automatic host failover
org-roam–backed memory (remember / recall as a knowledge graph)
License
MIT — see LICENSE.