branch: externals/ellama
commit f0f4589c72fa2ff01e6bde3bf3c93408a3af9d3f
Merge: c6cdb86950 4868cf4333
Author: Sergey Kostyaev <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #372 from s-kostyaev/implement-skills
    
    Add skills system to Ellama
---
 NEWS.org                  |   4 ++
 README.org                |  56 +++++++++++++++++
 ellama-skills.el          | 123 ++++++++++++++++++++++++++++++++++++
 ellama.el                 |  14 ++++-
 ellama.info               | 156 +++++++++++++++++++++++++++++++++++-----------
 skills/changelog/SKILL.md |  35 +++++++++++
 6 files changed, 349 insertions(+), 39 deletions(-)

diff --git a/NEWS.org b/NEWS.org
index 710e9bd0ff..0b7cadbbb6 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -1,3 +1,7 @@
+* Version 1.11.0
+- Add skills system to Ellama.
+- Add Agent Skills to the documentation.
+- Add changelog generation skill to the project.
 * Version 1.10.12
 - Added prepend_file tool that allows prepending content to files. This expands
   the set of file manipulation utilities available through the ellama tools.
diff --git a/README.org b/README.org
index 1c46bc2672..e3f7ceb6d2 100644
--- a/README.org
+++ b/README.org
@@ -384,6 +384,10 @@ argument generated text string.
   blueprints.
 - ~ellama-blueprint-file-extensions~: File extensions recognized as blueprint
   files.
+- ~ellama-skills-global-path~: Path to the global directory containing Agent
+  Skills.
+- ~ellama-skills-local-path~: Project-relative path for local Agent Skills.
+  Default value is ~"skills"~.
 
 * Context Management
 
@@ -711,6 +715,58 @@ to ~ellama~ you can add duckduckgo mcp server
               tools)))))
 #+end_src
 
+* Agent Skills
+
+Ellama supports *Agent Skills*, a lightweight format for extending AI
+capabilities. Skills are loaded into context only when needed (Progressive
+Disclosure).
+
+** Directory Structure
+
+Ellama looks for skills in two locations:
+1.  *Global*: =~/.emacs.d/ellama/skills/= (Customizable via
+~ellama-skills-global-path~)
+2.  *Project-Local*: ~skills/~ inside your project root (Customizable via
+~ellama-skills-local-path~)
+
+A skill is a directory containing a ~SKILL.md~ file. This file includes 
metadata
+(~name~ and ~description~, at minimum) and instructions that tell an agent how
+to perform a specific task. Skills can also bundle scripts, templates, and
+reference materials.
+
+#+begin_src
+my-project/
+└──skills/
+   └── pdf-processing/
+       ├── SKILL.md          # Required: instructions + metadata
+       ├── scripts/          # Optional: executable code
+       ├── references/       # Optional: documentation
+       └── assets/           # Optional: templates, resources
+#+end_src
+
+** Creating a Skill
+
+SKILL.md must contain YAML frontmatter:
+
+#+begin_src markdown
+---
+name: pdf-processing
+description: Extract text from PDFs and summarize them.
+---
+
+# PDF Processing Instructions
+To extract text from a PDF...
+#+end_src
+
+** How it works
+
+*Auto-Discovery*: Ellama scans skill directories automatically whenever a chat
+ starts.
+*Context*: Skill metadata (name, description, location) is injected into the
+ system prompt.
+*Activation*: The LLM uses the read_file tool to load the SKILL.md content when
+ needed.
+
 * Acknowledgments
 
 Thanks [[https://github.com/jmorganca][Jeffrey Morgan]] for excellent project 
[[https://github.com/jmorganca/ollama][ollama]]. This project
diff --git a/ellama-skills.el b/ellama-skills.el
new file mode 100644
index 0000000000..a58c2c3f63
--- /dev/null
+++ b/ellama-skills.el
@@ -0,0 +1,123 @@
+;;; ellama-skills.el --- Working with skills -*- lexical-binding: t; 
package-lint-main-file: "ellama.el"; -*-
+
+;; Copyright (C) 2023-2026  Free Software Foundation, Inc.
+
+;; Author: Sergey Kostyaev <[email protected]>
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Ellama is a tool for interacting with large language models from Emacs.
+;; It allows you to ask questions and receive responses from the
+;; LLMs.  Ellama can perform various tasks such as translation, code
+;; review, summarization, enhancing grammar/spelling or wording and
+;; more through the Emacs interface.  Ellama natively supports streaming
+;; output, making it effortless to use with your preferred text editor.
+;;
+
+;;; Code:
+(require 'cl-lib)
+(require 'ellama-tools)
+(require 'yaml)
+
+(defcustom ellama-skills-global-path
+  (expand-file-name "ellama/skills" user-emacs-directory)
+  "Path to the global directory containing Agent Skills."
+  :type 'directory
+  :group 'ellama)
+
+(defcustom ellama-skills-local-path "skills"
+  "Project-relative path for local Agent Skills."
+  :type 'string
+  :group 'ellama)
+
+(cl-defstruct ellama-skill
+  id          ; The folder name
+  name        ; From frontmatter
+  description ; From frontmatter
+  path        ; Absolute path to the skill directory
+  file-path)  ; Absolute path to SKILL.md
+
+(defun ellama-skills--parse-frontmatter (file)
+  "Parse YAML frontmatter from FILE using yaml.el."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (goto-char (point-min))
+    (if (and (looking-at "^---[ \t]*$")
+             (search-forward-regexp "^---[ \t]*$" nil t 2))
+        (let* ((end (match-beginning 0))
+               (start (save-excursion (goto-char (point-min)) (forward-line) 
(point)))
+               (yaml-string (buffer-substring-no-properties start end)))
+          (condition-case nil
+              (yaml-parse-string yaml-string
+                                 :object-type 'alist
+                                 :object-key-type 'symbol)
+            (error nil)))
+      nil)))
+
+(defun ellama-skills--scan-directory (root-dir)
+  "Return list of `ellama-skill` structs found in ROOT-DIR."
+  (let (skills)
+    (when (and root-dir (file-exists-p root-dir))
+      (dolist (skill-dir (directory-files root-dir t "^[^.]"))
+        (when (file-directory-p skill-dir)
+          (let ((skill-file (expand-file-name "SKILL.md" skill-dir)))
+            (when (file-exists-p skill-file)
+              (let* ((meta (ellama-skills--parse-frontmatter skill-file))
+                     (name (alist-get 'name meta))
+                     (desc (alist-get 'description meta)))
+                (when (and name desc)
+                  (push (make-ellama-skill
+                         :id (file-name-nondirectory skill-dir)
+                         :name name
+                         :description desc
+                         :path skill-dir
+                         :file-path skill-file)
+                        skills))))))))
+    skills))
+
+(defun ellama-skills-get-project-dir ()
+  "Get the absolute path to the project local skills directory."
+  (let ((root (ellama-tools-project-root-tool)))
+    (when root
+      (expand-file-name ellama-skills-local-path root))))
+
+(defun ellama-get-skills ()
+  "Scan and return all available skills (global and local)."
+  (append (ellama-skills--scan-directory ellama-skills-global-path)
+          (ellama-skills--scan-directory (ellama-skills-get-project-dir))))
+
+;;;###autoload
+(defun ellama-skills-generate-prompt ()
+  "Generate the <available_skills> XML block for the system prompt."
+  (let ((skills (ellama-get-skills)))
+    (if skills
+        (concat
+         "\n<available_skills>\n"
+         (mapconcat
+          (lambda (skill)
+            (format "  <skill>\n    <name>%s</name>\n    
<description>%s</description>\n    <location>%s</location>\n  </skill>"
+                    (ellama-skill-name skill)
+                    (ellama-skill-description skill)
+                    (ellama-skill-file-path skill)))
+          skills
+          "\n")
+         "\n</available_skills>\n"
+         "You have access to the skills listed above. To use a skill, use the 
`read_file` tool on the file path specified in <location> to load its 
instructions.")
+      "")))
+
+(provide 'ellama-skills)
+;;; ellama-skills.el ends here
diff --git a/ellama.el b/ellama.el
index 23f41ece93..df6b8f1e16 100644
--- a/ellama.el
+++ b/ellama.el
@@ -5,8 +5,8 @@
 ;; Author: Sergey Kostyaev <[email protected]>
 ;; URL: http://github.com/s-kostyaev/ellama
 ;; Keywords: help local tools
-;; Package-Requires: ((emacs "28.1") (llm "0.24.0") (plz "0.8") (transient 
"0.7") (compat "29.1"))
-;; Version: 1.10.12
+;; Package-Requires: ((emacs "28.1") (llm "0.24.0") (plz "0.8") (transient 
"0.7") (compat "29.1") (yaml "1.2.3"))
+;; Version: 1.11.0
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;; Created: 8th Oct 2023
 
@@ -41,6 +41,7 @@
 (require 'compat)
 (eval-when-compile (require 'rx))
 (require 'ellama-tools)
+(require 'ellama-skills)
 
 (defgroup ellama nil
   "Tool for interacting with LLMs."
@@ -1212,6 +1213,13 @@ Otherwire return current active session."
 
 (defvar ellama-global-system nil)
 
+(defun ellama-get-system-message ()
+  "Return the effective system message, including dynamically scanned skills."
+  (let ((msg (concat (or ellama-global-system "")
+                    (ellama-skills-generate-prompt))))
+    (when (not (string= msg ""))
+      msg)))
+
 (defvar-local ellama--stop-scroll nil)
 
 ;;;###autoload
@@ -1510,7 +1518,7 @@ failure (with BUFFER current).
         (donecb (or (plist-get args :on-done) #'ignore))
         (prompt-with-ctx (ellama-context-prompt-with-context prompt))
         (system (or (plist-get args :system)
-                    ellama-global-system))
+                    (ellama-get-system-message)))
         (llm-prompt (if session
                         (if (llm-chat-prompt-p (ellama-session-prompt session))
                             (progn
diff --git a/ellama.info b/ellama.info
index ec605322b7..17a2e7a7a0 100644
--- a/ellama.info
+++ b/ellama.info
@@ -66,6 +66,7 @@ Assistant".  Previous sentence was written by Ellama itself.
 * Minor modes::
 * Using Blueprints::
 * MCP Integration::
+* Agent Skills::
 * Acknowledgments::
 * Contributions::
 * GNU Free Documentation License::
@@ -107,6 +108,12 @@ Using Blueprints
 * Transient Menus::
 * Running Blueprints programmatically::
 
+Agent Skills
+
+* Directory Structure::
+* Creating a Skill::
+* How it works::
+
 
 
 File: ellama.info,  Node: Installation,  Next: Commands,  Prev: Top,  Up: Top
@@ -510,6 +517,10 @@ argument generated text string.
      project-specific blueprints.
    • ‘ellama-blueprint-file-extensions’: File extensions recognized as
      blueprint files.
+   • ‘ellama-skills-global-path’: Path to the global directory
+     containing Agent Skills.
+   • ‘ellama-skills-local-path’: Project-relative path for local Agent
+     Skills.  Default value is ‘"skills"’.
 
 
 File: ellama.info,  Node: Context Management,  Next: Minor modes,  Prev: 
Configuration,  Up: Top
@@ -944,7 +955,7 @@ arguments.
      (global-set-key (kbd "C-c e M") #'my-chat-with-morpheus)
 
 
-File: ellama.info,  Node: MCP Integration,  Next: Acknowledgments,  Prev: 
Using Blueprints,  Up: Top
+File: ellama.info,  Node: MCP Integration,  Next: Agent Skills,  Prev: Using 
Blueprints,  Up: Top
 
 8 MCP Integration
 *****************
@@ -974,10 +985,79 @@ capability to ‘ellama’ you can add duckduckgo mcp server
                     tools)))))
 
 
-File: ellama.info,  Node: Acknowledgments,  Next: Contributions,  Prev: MCP 
Integration,  Up: Top
+File: ellama.info,  Node: Agent Skills,  Next: Acknowledgments,  Prev: MCP 
Integration,  Up: Top
 
-9 Acknowledgments
-*****************
+9 Agent Skills
+**************
+
+Ellama supports *Agent Skills*, a lightweight format for extending AI
+capabilities.  Skills are loaded into context only when needed
+(Progressive Disclosure).
+
+* Menu:
+
+* Directory Structure::
+* Creating a Skill::
+* How it works::
+
+
+File: ellama.info,  Node: Directory Structure,  Next: Creating a Skill,  Up: 
Agent Skills
+
+9.1 Directory Structure
+=======================
+
+Ellama looks for skills in two locations:
+  1. *Global*: ‘~/.emacs.d/ellama/skills/’ (Customizable via
+‘ellama-skills-global-path’)
+  1. *Project-Local*: ‘skills/’ inside your project root (Customizable
+     via
+‘ellama-skills-local-path’)
+
+A skill is a directory containing a ‘SKILL.md’ file.  This file includes
+metadata (‘name’ and ‘description’, at minimum) and instructions that
+tell an agent how to perform a specific task.  Skills can also bundle
+scripts, templates, and reference materials.
+
+     my-project/
+     └──skills/
+        └── pdf-processing/
+            ├── SKILL.md          # Required: instructions + metadata
+            ├── scripts/          # Optional: executable code
+            ├── references/       # Optional: documentation
+            └── assets/           # Optional: templates, resources
+
+
+File: ellama.info,  Node: Creating a Skill,  Next: How it works,  Prev: 
Directory Structure,  Up: Agent Skills
+
+9.2 Creating a Skill
+====================
+
+SKILL.md must contain YAML frontmatter:
+
+     ---
+     name: pdf-processing
+     description: Extract text from PDFs and summarize them.
+     ---
+
+     # PDF Processing Instructions
+     To extract text from a PDF...
+
+
+File: ellama.info,  Node: How it works,  Prev: Creating a Skill,  Up: Agent 
Skills
+
+9.3 How it works
+================
+
+*Auto-Discovery*: Ellama scans skill directories automatically whenever
+a chat starts.  *Context*: Skill metadata (name, description, location)
+is injected into the system prompt.  *Activation*: The LLM uses the
+read_file tool to load the SKILL.md content when needed.
+
+
+File: ellama.info,  Node: Acknowledgments,  Next: Contributions,  Prev: Agent 
Skills,  Up: Top
+
+10 Acknowledgments
+******************
 
 Thanks Jeffrey Morgan (https://github.com/jmorganca) for excellent
 project ollama (https://github.com/jmorganca/ollama).  This project
@@ -996,7 +1076,7 @@ Without it only ‘ollama’ would be supported.
 
 File: ellama.info,  Node: Contributions,  Next: GNU Free Documentation 
License,  Prev: Acknowledgments,  Up: Top
 
-10 Contributions
+11 Contributions
 ****************
 
 To contribute, submit a pull request or report a bug.  This library is
@@ -1490,37 +1570,41 @@ their use in free software.
 
 Tag Table:
 Node: Top1379
-Node: Installation3654
-Node: Commands8662
-Node: Keymap16101
-Node: Configuration18934
-Node: Context Management25234
-Node: Transient Menus for Context Management26142
-Node: Managing the Context27756
-Node: Considerations28531
-Node: Minor modes29124
-Node: ellama-context-header-line-mode31112
-Node: ellama-context-header-line-global-mode31937
-Node: ellama-context-mode-line-mode32657
-Node: ellama-context-mode-line-global-mode33505
-Node: Ellama Session Header Line Mode34209
-Node: Enabling and Disabling34778
-Node: Customization35225
-Node: Ellama Session Mode Line Mode35513
-Node: Enabling and Disabling (1)36098
-Node: Customization (1)36545
-Node: Using Blueprints36839
-Node: Key Components of Ellama Blueprints37479
-Node: Creating and Managing Blueprints38086
-Node: Blueprints files39064
-Node: Variable Management39485
-Node: Keymap and Mode39938
-Node: Transient Menus40874
-Node: Running Blueprints programmatically41420
-Node: MCP Integration42007
-Node: Acknowledgments43032
-Node: Contributions43744
-Node: GNU Free Documentation License44130
+Node: Installation3748
+Node: Commands8756
+Node: Keymap16195
+Node: Configuration19028
+Node: Context Management25551
+Node: Transient Menus for Context Management26459
+Node: Managing the Context28073
+Node: Considerations28848
+Node: Minor modes29441
+Node: ellama-context-header-line-mode31429
+Node: ellama-context-header-line-global-mode32254
+Node: ellama-context-mode-line-mode32974
+Node: ellama-context-mode-line-global-mode33822
+Node: Ellama Session Header Line Mode34526
+Node: Enabling and Disabling35095
+Node: Customization35542
+Node: Ellama Session Mode Line Mode35830
+Node: Enabling and Disabling (1)36415
+Node: Customization (1)36862
+Node: Using Blueprints37156
+Node: Key Components of Ellama Blueprints37796
+Node: Creating and Managing Blueprints38403
+Node: Blueprints files39381
+Node: Variable Management39802
+Node: Keymap and Mode40255
+Node: Transient Menus41191
+Node: Running Blueprints programmatically41737
+Node: MCP Integration42324
+Node: Agent Skills43346
+Node: Directory Structure43709
+Node: Creating a Skill44736
+Node: How it works45111
+Node: Acknowledgments45502
+Node: Contributions46213
+Node: GNU Free Documentation License46599
 
 End Tag Table
 
diff --git a/skills/changelog/SKILL.md b/skills/changelog/SKILL.md
new file mode 100644
index 0000000000..96d4fd3528
--- /dev/null
+++ b/skills/changelog/SKILL.md
@@ -0,0 +1,35 @@
+---
+name: changelog
+description: Use this skill to generate changelog.
+---
+
+# Generating changelog
+
+Call shell_command tool with "git log --reverse main..HEAD" argument. Based on
+the output write short changelog in org-mode list format. Use "~tildas~" 
quoting
+instead of "`backticks`" quoting. Do not add any anknowledgements. Every
+changelog element should be ended with full stop. Changelog shouldn't be too
+short or too long, use detailed description for major changes and concise
+description for minor changes.
+
+Call shell_command tools with "git tag -l --points-at=main" argument to see
+previously released version. Based on this information and minority/majority of
+the changes you can fill version variable. If you are not sure, ask the user
+using ask_user tool with your variants of the version.
+
+Write it to ./NEWS.org using prepend_file tool
+with header:
+
+* Version {version}
+
+After header should be changelog content. Content should ends with single
+newline.
+Example:
+ ```text
+* Version {version}
+- Some change description. Some additional information.
+- Major change detailed description. This change improves ~ellama-something~.
+  Some additional information.
+- Third change description.
+- Some fix in ~ellama-example-command~ description.
+```

Reply via email to