Instructed LLM programmer/assistant for Emacs
GPL-3.0 License
#+begin_quote [!WARNING] This is a fledgling project. Expect bugs, missing features, and API instability. #+end_quote
Evedel is an Emacs package that adds a workflow for interacting with LLMs during programming. Its primary goal is to shift workload from manually writing code to creating detailed, thoughtful instruction annotations in the source files for LLM models, leveraging them as indexed references to provide them with contextual understanding of the working environment.
Evedel is versatile enough so that it can be utilized in various types of buffers, and isn't limited to just programming buffers.
** Features
[[file:media/complex-labeling-example.png]]
** Requirements :PROPERTIES: :CUSTOM_ID: requirements :END:
** Usage
Evedel's function revolves around the creation and manipulation of references and directives within your Emacs buffers. Directives are prompts you send to the model, while references provide context to help complete these directives more accurately.
[[file:media/basic-demo.gif]]
*** Management
|------------------------------+-----------------------------------------------------------------------| | Command | Command Description | |------------------------------+-----------------------------------------------------------------------| | =evedel-create-reference= | Create or resize a reference instruction within a region. | | =evedel-create-directive= | Create or resize a directive instruction at point or within a region. | | =evedel-delete-instructions= | Remove instructions either at point or within the selected region. | | =evedel-delete-all= | Delete all Evedel instructions across all buffers. | |------------------------------+-----------------------------------------------------------------------|
Below is an example of scaling existing instruction overlay (in this case, a reference) by invoking the =evedel-create-reference= command within a region that contains one:
[[file:media/scaling-demo.gif]]
*** Saving & Loading
|----------------------------+--------------------------------------------------------| | Command | Command Description | |----------------------------+--------------------------------------------------------| | =evedel-save-instructions= | Save current instruction overlays to a specified file. | | =evedel-load-instructions= | Load instruction overlays from a specified file. | | =evedel-instruction-count= | Return the number of instructions currently loaded. | |----------------------------+--------------------------------------------------------|
|--------------------------------------+------------------------------------------------------------------| | Custom Variable | Variable Description | |--------------------------------------+------------------------------------------------------------------| | =evedel-patch-outdated-instructions= | Automatically patch instructions when the save file is outdated. | |--------------------------------------+------------------------------------------------------------------|
The variable =evedel-patch-outdated-instructions= controls the automatic patching of instructions during loading when the save file is outdated. The process is not perfect (word-wise diff), so you should always try and maintain a separate instruction file per branch.
*** Modification
|--------------------------------------+-------------------------------------------------------------------| | Command | Command Description | |--------------------------------------+-------------------------------------------------------------------| | =evedel-convert-instructions= | Convert between reference and directive types at point. | | =evedel-modify-directive= | Modify an existing directive instruction at point. | | =evedel-modify-reference-commentary= | Modify reference commentary at the current point. | | =evedel-add-tags= | Add tags to the reference under the point. | | =evedel-remove-tags= | Remove tags from the reference under the point. | | =evedel-modify-directive-tag-query= | Enter a tag search query for a directive under the current point. | | =evedel-link-instructions= | Link instructions by their ids. | | =evedel-unlink-instructions= | Unlink instructions by their ids. | |--------------------------------------+-------------------------------------------------------------------|
|-------------------------------------------+------------------------------------------------------| | Custom Variable | Variable Description | |-------------------------------------------+------------------------------------------------------| | =evedel-empty-tag-query-matches-all= | Determines matching behavior of queryless directives | | =evedel-always-match-untagged-references= | Determines matching behavior of untagged references | |-------------------------------------------+------------------------------------------------------|
**** Categorization
[[file:media/tag-query-demo.gif]]
The categorization system in allows you to use tags to label and organize references. You can add or remove tags to a reference using the commands =evedel-add-tags= and =evedel-remove-tags=. Each tag is a symbolic label that helps identify the nature or purpose of the reference.
You can also modify the tag query for a directive, which is a way to filter and search for references by tags. The tag query uses an infix notation system, allowing complex expressions with the operators =and=, =or=, and =not=. For example, the query =signature and function and doc= means the directive should match references tagged with =signature=, =function=, and =doc=. You may use parentheses in these expressions.
Additionally, there are special meta tag symbols that have exclusive meanings:
=evedel-empty-tag-query-matches-all= determines the behavior of directives without a tag search query. If set to =t=, directives lacking a specific tag search query will use all available references. Alternatively, if set to =nil=, such directives will not use any references, leading to potentially narrower results.
=evedel-always-match-untagged-references= controls the inclusion of untagged references in directive prompts. When set to =t=, untagged references are always incorporated into directive references, ensuring comprehensive coverage. Conversely, when set to =nil=, untagged references are ignored unless =evedel-empty-tag-query-matches-all= is set to =t=.
**** Commentary
You can add commentaries to references with the =evedel-modify-reference-commentary= command. Commentaries can add extra context and information to a reference. Example:
[[file:media/commentary-example.png]]
**** Linking
References can be linked to one another, which sets up a dependency or of automatic inclusion relationship between the two. This means that when the first reference is utilized, it will automatically bring into play the reference it is linked to, as well. This chaining of references is recursive: if a linked reference is itself linked to another, and so forth, all these links will be followed automatically. This continues until either there are no more links to follow or a cycle is detected in the linkage graph.
Linked references are also included when a directive is executed from within a reference which links to another, in a similar fashion to commentaries.
Currently, linking is only relevant for references.
*** Processing
|-----------------------------------+------------------------------------------------| | Command | Command Description | |-----------------------------------+------------------------------------------------| | =evedel-process-directives= | Process directives by sending them to gptel. | | =evedel-preview-directive-prompt= | Preview directive prompt at the current point. | |-----------------------------------+------------------------------------------------|
|----------------------------------------+------------------------------------------------------------| | Custom Variable | Variable Description | |----------------------------------------+------------------------------------------------------------| | =evedel-descriptive-mode-roles= | Alist mapping major modes to model roles association list | |----------------------------------------+------------------------------------------------------------|
You can use the =evedel-preview-directive-prompt= command to do a dry-run and see how the AI prompt will look like. Here's an example of previewing a directive prompt:
[[file:media/preview-directive-demo.gif]]
The =evedel-process-directives= command processes the directives.
*** Navigation
|--------------------------------------+-------------------------------------------------------------| | Command | Command Description | |--------------------------------------+-------------------------------------------------------------| | =evedel-next-instruction= | Cycle through instructions in the forward direction. | | =evedel-previous-instruction= | Cycle through instructions in the backward direction. | | =evedel-next-reference= | Cycle through references in the forward direction. | | =evedel-previous-reference= | Cycle through references in the backward direction. | | =evedel-next-directive= | Cycle through directives in the forward direction. | | =evedel-previous-directive= | Cycle through directives in the backward direction. | | =evedel-cycle-instructions-at-point= | Cycle through instructions at the point, highlighting them. | |--------------------------------------+-------------------------------------------------------------|
*** Customization
|-------------------------------------------+--------------------------------------------------| | Custom Variable | Variable Description | |-------------------------------------------+--------------------------------------------------| | =evedel-reference-color= | Tint color for reference overlays | | =evedel-directive-color= | Tint color for directive overlays | | =evedel-directive-processing-color= | Tint color for directives being processed | | =evedel-directive-success-color= | Tint color for successfully processed directives | | =evedel-directive-fail-color= | Tint color for failed directives | | =evedel-instruction-bg-tint-intensity= | Intensity for instruction background tint | | =evedel-instruction-label-tint-intensity= | Intensity for instruction label tint | | =evedel-subinstruction-tint-intensity= | Coefficient for adjusting subinstruction tints | |-------------------------------------------+--------------------------------------------------|
** Setup
Before proceeding, make sure you have [[https://github.com/karthink/gptel][gptel]] configured (see [[#requirements][requirements]]). This package will not work without it. Clone the Evedel repository:
#+begin_src sh git clone https://github.com/daedsidog/evedel.git #+end_src
Add the path to the cloned repository in your Emacs configuration. You can do this by adding the following code to your =init.el= or =config.el= file:
#+begin_src emacs-lisp (push "/path/to/evedel" load-path) (use-package evedel :bind (("C-c e r" . evedel-create-reference) ("C-c e d" . evedel-create-directive) ("C-c e s" . evedel-save-instructions) ("C-c e l" . evedel-load-instructions) ("C-c e p" . evedel-process-directives) ("C-c e m" . evedel-modify-directive) ("C-c e C" . evedel-modify-reference-commentary) ("C-c e k" . evedel-delete-instructions) ("C-c e c" . evedel-convert-instructions) ("C->" . evedel-next-instruction) ("C-<" . evedel-previous-instruction) ("C-." . evedel-cycle-instructions-at-point) ("C-c e t" . evedel-add-tags) ("C-c e T" . evedel-remove-tags) ("C-c e D" . evedel-modify-directive-tag-query) ("C-c e P" . evedel-preview-directive-prompt))) #+end_src
Make sure to replace ="/path/to/evedel"= with the actual path where you cloned the Evedel repository.
** Planned Features
Mark indicates previously planned features that have been implemented.
*** Instruction Navigation
*** Reference Management
*** Directive Management
*** Interface
[1] While the current patching is able to fix outdated instructions pretty accurately, it is still a better idea to maintain a separate save file for each branch. This feature solves the problem where even the most minor change in the file completely broke the overlay structure.
*** Documentation
** Acknowledgments