An Emacs Lisp AI coding agent with multi-agent architecture, permission-based
tool access, an Elisp-native slash-command extension API through
magent-command, and LLM integration via gptel.
homepage: https://jamie-cui.github.io/magent/
Magent now uses a durable child-agent lifecycle for collaborative agent work: spawn, message, wait, list, resume/inspect, and close. The lifecycle is implemented on top of the Magent-owned agent loop while provider integration stays with gptel-request.
See docs/UI_BACKENDS.org for the supported agent-shell frontend boundary.
magent-command and skills are complementary extension points, not two ways to
define the same thing:
magent-command | Skill | |
|---|---|---|
| Primary role | An explicit Emacs or slash-command action | Reusable instructions or a model-invokable operation |
| Definition | Trusted Elisp registered with magent-command-register | A SKILL.md file; a tool skill may also have a companion Elisp implementation |
| Activation | The user enters /name or runs M-x magent-agent-shell-run-command | The user enters /$name, selects it for the next turn, or a capability activates it; a tool skill is called by the model |
| Owns | Arguments, requirements, session policy, Steps, and multi-step control | Model context and workflow guidance, or one named operation through skill_invoke |
| Project trust boundary | Command Workflows are trusted installed Elisp | Project instruction Markdown is data-only; companion Elisp runs only for explicitly trusted roots |
Use magent-command when you want a stable, user-triggered entry point in
Emacs. Use a skill when you want reusable expertise or an operation that the
agent can apply while handling requests. Use both when an explicit command
should activate reusable expertise: an agent Step can select skills with
:skills and declare its tool preflight with :required-tools.
ACP advertises every visible instruction skill as /$name in agent-shell,
without requiring default-prompt. An instruction skill with default-prompt
is additionally projected into the command registry as a legacy /name
compatibility adapter. Invoking either surface activates the original skill; it
does not turn Markdown into a Command Workflow or give it trusted Elisp
execution authority.
magent-command therefore makes slash commands first-class, explicit user
actions. Your init file or another trusted Elisp package can register a command
through the public magent-command-register API without changing the agent-shell
or ACP integration. Every command owns one generator-backed Elisp Workflow;
managed agent, process, and callback Steps provide asynchronous suspension,
cancellation, progress, and activity recording.
Registered commands are advertised to agent-shell and can be invoked as slash
input or selected with M-x magent-agent-shell-run-command. The complete
use-package example below registers /ask-name; see
docs/COMMANDS.org for the full command API and lifecycle.
- Emacs 29.1+
- gptel 0.9.8+
- compat 30.1+
- yaml 1.0+
- acp 0.13.1+
- agent-shell 0.62.1+
- ripgrep (for the
greptool)
Add the project to your Emacs load path:
(add-to-list 'load-path "/path/to/magent/lisp")
(require 'magent)
(magent-agent-shell-ensure-config)(use-package magent
:load-path "/path/to/magent/lisp"
:config
(magent-agent-shell-ensure-config))When your use-package supports the :vc keyword, it can install and load
Magent directly from Git:
(use-package magent
:vc (:url "https://github.com/Jamie-Cui/magent" :rev "master")
:ensure t
:after (agent-shell gptel)
:demand t
:custom
;; Uncomment to bypass Magent's tool permission checks and approval prompts.
;; (magent-bypass-permission t)
(magent-default-effort 'xhigh)
:config
;; Optional: append an additional personal skill directory. Later entries
;; have higher precedence and become the skill manager's install target.
(add-to-list 'magent-skill-directories
(expand-file-name "skills" user-emacs-directory)
t)
(magent-agent-shell-ensure-config)
;; Register /ask-name as an Elisp-native Magent command.
(magent-command-defworkflow my-magent-ask-name (invocation)
(let ((topic
(string-trim
(or (magent-command-invocation-argument invocation) ""))))
(magent-command-answer
"Ask selected agent"
(if (string-empty-p topic)
"What is your name?"
(format "What is your name? Also discuss: %s" topic)))))
(magent-command-register
"ask-name"
:description "Ask the selected Magent agent to introduce itself."
:session-policy 'current
:workflow #'my-magent-ask-name
:source-layer 'user
:requires 'subr-x)):requires accepts one Emacs feature or a list of features. Magent calls
require during invocation preflight; it does not install packages or require
a project workspace. Tool requirements belong to the agent Step that needs
them. Every registration requires one :workflow and an explicit
:session-policy. A user command can override an installed package or
builtin command with the same name. Registering the same name, layer, and
canonical scope again replaces that slot’s previous definition. The core
/compact and /skills names remain reserved.
Magent delegates all LLM communication to gptel. Configure your provider, model, and API key through gptel:
;; gptel handles provider/model/key configuration
(setq gptel-model 'claude-sonnet-4-20250514)
(setq gptel-api-key "sk-ant-...") ; or use ANTHROPIC_API_KEY env varSee gptel documentation for full provider setup (Anthropic, OpenAI, Ollama, etc.).
The only supported Magent frontend is agent-shell. Magent supplies its own agent-shell configuration and in-process ACP client, so no external ACP command is required. To start using Magent:
- Visit a file in the project you want Magent to work on.
- Run
M-x magent-start. Magent opens or reuses the project-local agent-shell buffer through its in-process ACP adapter. You can also runM-x agent-shelland select Magent after registering the configuration as shown in the installation examples above. - Type a prompt at the bottom of the agent-shell buffer and press
RETto submit it. Assistant responses, reasoning, tool calls, and permission requests are streamed into the same buffer. - Enter another prompt and press
RETto continue the project-scoped session. While a request is running, pressC-c C-cto interrupt it.
From a source buffer, M-x magent-agent-shell-prompt-region sends the active
region and M-x magent-agent-shell-ask-at-point asks about the symbol at point;
both commands submit their context through agent-shell.
Customize with M-x customize-group RET magent RET. Key settings:
| Option | Default | Description |
|---|---|---|
magent-system-prompt | (built-in) | Default system prompt for agents |
magent-enable-tools | default tool set | Globally enabled tool permission groups |
magent-project-root-function | nil | Custom project root finder |
magent-max-history | 100 | Max messages in history |
magent-request-timeout | 120 | Timeout in seconds for LLM requests |
magent-max-sampling-requests | 0 | Continuation budget; reaching it fails the turn directly, and 0 disables the guard |
magent-default-agent | "build" | Default agent for new sessions |
magent-default-effort | nil | Default reasoning effort; nil/auto uses provider default |
magent-skill-directories | user-emacs-directory/magent/skills/ | Ordered user skill roots; later entries override earlier entries |
magent-load-custom-agents | t | Load custom agents from .magent/agent/*.md |
magent-enable-audit-log | t | Persist compact audit logs for permission and sensitive actions |
magent-agent-directory | ".magent/agent" | Relative path to custom agent dir |
magent-session-directory | ~/.emacs.d/magent/sessions/ | Base directory for global sessions and per-project session subdirectories |
magent-audit-directory | nil | Override directory for audit JSONL files; defaults to magent-session-directory/audit/ |
magent-grep-program | "rg" | Path to ripgrep binary |
magent-grep-max-matches | 100 | Max matches from grep searches |
magent-bash-program | "bash" | Bash-compatible executable; commands use pipefail without implicit errexit |
magent-bash-timeout | 300 | Host-owned timeout in seconds for synchronous bash commands |
magent-child-agent-max-depth | 1 | Max recursive child-agent depth; direct children are allowed by default |
magent-emacs-eval-timeout | 10 | Timeout in seconds for emacs_eval |
magent-enable-capabilities | t | Enable contextual capability resolution by default |
magent-project-instruction-file-names | ("AGENTS.md") | Scoped project instruction filenames discovered from root toward request resources |
magent-project-instructions-max-bytes | 65536 | Aggregate per-request byte limit for project instructions; nil disables discovery |
magent-audit-preview-length | 120 | Max width for persisted normalized audit path markers |
magent-include-reasoning | t | Display (t), hide but retain (ignore), or discard (nil) reasoning; never final-answer fallback |
magent-trusted-project-skill-companion-roots | nil | Project roots explicitly trusted to execute tool-skill companion Elisp |
Core, built-in agent, slash-command, and internal runtime prompts live as
editable Org files under prompts/. Files containing placeholders such as
{{project-root}} or {{instruction}} should keep those placeholders where
the dynamic value is needed; ordinary percent signs need no escaping. Skill
prompts remain self-contained in skills/*/SKILL.md. Every bundled Org prompt
must appear exactly once in prompts/manifest.txt.
| Command | Description |
|---|---|
magent-start | Open or reuse the project-local Magent agent-shell buffer |
magent-agent-shell-start | Start a fresh Magent agent-shell buffer |
magent-agent-shell-prompt-region | Send the selected region through agent-shell |
magent-agent-shell-ask-at-point | Ask about the symbol at point through agent-shell |
magent-agent-shell-interrupt | Interrupt the active Magent agent-shell request |
magent-agent-shell-run-command | Select and run a registered slash command |
magent-agent-shell-toggle-skill-for-next-request | Toggle a one-shot instruction skill |
magent-toggle-bypass-permission | Toggle permission bypass for tool filtering and approval prompts |
Prompt text is entered directly in the agent-shell buffer, and Magent streams assistant responses, tool activity, permission prompts, and session updates back through agent-shell.
Use agent-shell session options for per-session request settings. Reasoning
effort is exposed as agent-shell’s thought level session option; use
agent-shell-set-session-thought-level to choose auto, minimal, low,
medium, high, or xhigh for future turns in the current session. The
Automatic capabilities session option enables or disables contextual skill
activation without affecting explicitly selected instruction skills.
Agent-shell file mentions use ACP structured resource blocks. Magent persists those blocks with the turn and reconstructs their bodies as user-role context; local file resources also select applicable project instructions from the project root toward the attached file.
The same bypass state is also exposed as the customize option
magent-bypass-permission under M-x customize-group RET magent RET.
Magent runtime state is scoped by project, and the supported agent-shell workflow associates sessions with the current project:
- In a recognized project, prompts, agent selection, clear, and resume operate on that project’s current session.
- Saved project sessions live under
magent-session-directory/projects/<sha1(project-root)>/. - Outside any project, Magent falls back to the global session behavior and saves directly under
magent-session-directory. - Compact audit logs for permission decisions and sensitive tools are written as daily JSONL files under
magent-session-directory/audit/unlessmagent-audit-directoryis set.
Instruction skills can be selected as one-shot context for the next request.
In agent-shell, use M-x magent-agent-shell-toggle-skill-for-next-request to
toggle a skill and M-x magent-agent-shell-clear-skills-for-next-request to
clear selected skills. Selected skills are scoped to the active Magent session
and are consumed by the next prompt.
Elisp-native slash commands are registered through the public
magent-command-register API and can be selected with
M-x magent-agent-shell-run-command. Agent-shell advertises twelve bundled
commands: /explain, /fix, /init, /review, /summarize, /test,
/compact, /skills, /doctor, /memory-init, /memory-refresh, and
/memory-clear. The six prompt commands own package Org resources and
do not activate same-name skills. /summarize writes one canonical Org note
for the current Git project and accepts an optional path or semantic scope.
Every instruction skill in the exact session scope is advertised as /$name.
/skills lists those descriptors locally. Skills with default-prompt retain
the additional legacy /name adapter; use
M-x magent-agent-shell-run-skill-command to select one directly. Project and
user skill adapters may override package commands, while the core /compact
and /skills controls are reserved. See
docs/COMMANDS.org for command behavior, the
third-party Elisp API, and compatibility details. Project adapters and skill
descriptors are retained by canonical project scope, and agent-shell uses the
exact session scope for both menus and dispatch.
Project-local instruction skills are data-only and load normally. A
tool-type project skill may also contain executable companion Elisp; Magent
does not execute that file by default. Add the normalized project root to
magent-trusted-project-skill-companion-roots only after reviewing the code.
Built-in and user-level tool skills retain their normal loading behavior.
Use M-x magent-find-skill to search skills.sh. The finder shows the ten
most-installed matches; RET previews a candidate, i installs it directly,
and g starts another search. M-x magent-install-skill also accepts a local
skill directory, owner/repo@skill, or a public GitHub URL.
Managed skills are copied into ~~/.emacs.d/magent/skills/<name>/~ by default.
Magent previews the source, size, file count, and any scripts or code before a
single y/n confirmation. It installs instruction skills only, does not
execute copied scripts, and records provenance in .magent-install.json.
M-x magent-delete-skill permanently deletes a selected user-level skill after
one y/n confirmation. These commands never manage project-local
.magent/skills/ or ~~/.agents/skills/~.
magent-skill-directories is ordered: later directories take precedence when
skill names collide, and its final entry is the installation target used by the
skill manager. Append a custom directory to retain the default roots while
making the custom directory the highest-priority source and installation
target:
(add-to-list 'magent-skill-directories "/path/to/skills" t)Magent uses a multi-agent architecture where different agents have different capabilities and permissions.
| Agent | Mode | Description |
|---|---|---|
build | primary | Default agent for general coding tasks with full tool access |
plan | primary | Planning agent with restricted file edits (only .magent/plan/*.md) |
explore | subagent | Fast codebase exploration (read/grep/glob/bash only) |
general | subagent | General-purpose subagent for child-agent tasks |
compaction | primary (hidden) | Session summarization / conversation compaction |
title | primary (hidden) | Conversation title generation |
summary | primary (hidden) | Pull-request style summary generation |
- primary: User-facing agents that can be selected for sessions
- subagent: Internal agents called by primary agents for subtasks
- all: Can act as either primary or subagent
Primary agents can coordinate child agents through durable jobs. A root turn can call spawn_agent to start work under a subagent profile, use list_agents and wait_agent to monitor results, send follow-up input with send_agent_message, and close work explicitly with close_agent.
Child jobs are stored in the parent session under agent-jobs with status,
prompt, metadata, result/error, and transcript state. Agent-shell shows compact
lifecycle updates. See docs/AGENT_JOBS.org for the implementation model and
boundaries.
Each agent has permission rules controlling tool access:
;; Example permission rules in an agent definition
'((read . allow)
(write . (("*.env.example" . allow)
("*.env" . deny)
("*.key" . deny)
(* . ask)))
(bash . ask)
(* . allow))Permission actions:
allow: Tool is alloweddeny: Tool is blockedask: Prompt the user for confirmation
Create custom agents by adding markdown files to .magent/agent/.
Example: ~.magent/agent/reviewer.md~
---
description: Code review specialist
mode: primary
hidden: false
temperature: 0.3
effort: high
permissions:
read: allow
write: deny
bash: deny
grep: allow
glob: allow
---
You are a code review specialist. Analyze code for:
- Bugs and potential issues
- Code style and best practices
- Performance optimizations
- Security vulnerabilities
Provide constructive feedback with specific examples.The YAML frontmatter supports:
description: Short description of the agentmode:primary,subagent, orallhidden: Hide from agent selection UItemperature: Override default temperatureeffort: Override reasoning effort:auto,minimal,low,medium,high, orxhighmodel: Override default modeloptions: Compatibility metadata retained as a mapping; it is not sent to the providersteps: Compatibility metadata retained from older agent definitionspermissions: Mapping of permission groups toallow,deny,ask, or nested file-pattern rules
The older YAML list form using entries such as (read_file . allow) remains
read-compatible, but new and saved definitions use the mapping above.
The AI agent has access to these tools (can be customized per agent):
| Tool | Side-effect | Description |
|---|---|---|
read_file | no | Read file contents from the filesystem |
write_file | yes | Write or create a file (auto-creates parent dirs) |
write_repo_summary | yes | Update the canonical single-file Org repository summary |
edit_file | yes | Replace exact text in a file (must match once) |
grep | no | Regex search via ripgrep; returns file:line:content |
glob | no | Find files matching a glob pattern |
bash | yes | Execute shell commands (default timeout 30s) |
emacs_eval | yes | Evaluate Emacs Lisp expressions (default timeout 10s) |
spawn_agent | yes | Start a durable child-agent job |
send_agent_message | yes | Send follow-up input to a live child job |
wait_agent | no | Wait for child jobs and return status/results |
list_agents | no | List child-agent jobs for the current session |
close_agent | yes | Close or cancel a child-agent job |
skill_invoke | no | Invoke tool-type skills |
web_search | no | Search the web via DuckDuckGo |
Each tool follows the active agent’s allow, deny, or ask rule. The
default build profile asks for shell, Emacs evaluation, and general file
writes, while some other side-effecting operations are allowed. File-specific
deny rules still apply. Permission bypass disables these checks and should be
used only deliberately.
Tool availability is controlled by:
- Global
magent-enable-toolssetting - Per-agent permission rules
Magent-owned maintenance workflows share one command spec between agent-shell slash input and their M-x wrappers:
/memory-initorM-x magent-command-run-memory-initinitializes Emacs profile memory./memory-refreshorM-x magent-command-run-memory-refreshrefreshes the managed profile while keeping user notes./memory-clearorM-x magent-command-run-memory-cleardeactivates and clears the managed profile while retaining user notes and a snapshot./doctororM-x magent-command-run-doctorcollects bounded local diagnostics and sends one sanitized, tool-free analysis request. Use/doctor selectorC-uon the M-x command for manual probe selection.M-x magent-command-list-sessionsopens the progressive command-session viewer;M-x magent-command-cancelcancels active work.
Doctor never gives the model emacs_eval, shell, or file tools. Its probes
are trusted read-only Elisp extensions, and only path-normalized, recursively
redacted data is persisted or sent. See docs/DOCTOR.org for the
trust boundary and probe API, and docs/COMMANDS.org for the
complete user-facing workflow command reference.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.