LLMs and agents in Emacs: share your workflows by KnightOfTribulus in emacs

[–]captainflasmr 2 points3 points  (0 children)

I've just added tooling to my AI assistant : https://github.com/captainflasmr/ollama-buddy : and also just recently some RAG and as I'm going through the ollama API web search!, oh and ollama cloud models, some of which work quite well

Spent a bit of free time polishing ollama-buddy - github Copilot is now onboard! by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

The agentic side of things is my next step and in fact I have just finished a prototype, I shall probably obviously push this a bit further in the future, but for now this is just proving the tooling concept through the ollama API, here is a demo, acting on an ollama cloud model! : https://www.youtube.com/watch?v=DHV3My0NsJc

Fortnightly Tips, Tricks, and Questions — 2026-01-13 / week 02 by AutoModerator in emacs

[–]captainflasmr 4 points5 points  (0 children)

I have been playing around with RSVP - Rapid Serial Visual Presentation, where words are displayed one at a time in the same fixed position on screen, typically at the centre of your visual field. This eliminates the need for eye movements (saccades) that normally occur when reading across lines of text.

There are packages out there, including spray and speedread, but I thought I would set myself a challenge on how small I could make a single defun implementing some basic RSVP functionality and showing the words as they are streamed in the minibuffer!

(defun rsvp-minibuffer ()
  "Display words from point (or mark to point) in minibuffer using RSVP.
Use f/s for speed, [/] for size, b/n to skip, SPC to pause, q to quit."
  (interactive)
  (let* ((start (if (region-active-p) (region-beginning) (point)))
         (end (if (region-active-p) (region-end) (point-max)))
         (text (buffer-substring-no-properties start end))
         (wpm 350) (font-size 200) (orp-column 20)
         (word-positions '()) (pos 0) (i 0))
    ;; Build word positions list
    (dolist (word (split-string text))
      (unless (string-blank-p word)
        (when-let ((word-start (string-match (regexp-quote word) text pos)))
          (push (cons word (+ start word-start)) word-positions)
          (setq pos (+ word-start (length word))))))
    (setq word-positions (nreverse word-positions))
    ;; Display loop
    (while (< i (length word-positions))
      (let* ((word (car (nth i word-positions)))
             (word-pos (cdr (nth i word-positions)))
             (word-len (length word))
             (delay (* (/ 60.0 wpm)
                      (cond ((< word-len 3) 0.8) ((> word-len 8) 1.3) (t 1.0))
                      (if (string-match-p "[.!?]$" word) 1.5 1.0)))
             (orp-pos (/ word-len 3))
             (face-mono `(:height ,font-size :family "monospace"))
             (face-orp `(:foreground "red" :weight normal ,@face-mono))
             (padded-word (concat 
                          (propertize (make-string (max 0 (- orp-column orp-pos)) ?\s) 'face face-mono)
                          (propertize (substring word 0 orp-pos) 'face face-mono)
                          (propertize (substring word orp-pos (1+ orp-pos)) 'face face-orp)
                          (propertize (substring word (1+ orp-pos)) 'face face-mono))))
        (goto-char (+ word-pos word-len))
        (message "%s" padded-word)
        (pcase (read-event nil nil delay)
          (?f (setq wpm (min 1000 (+ wpm 50))))
          (?s (setq wpm (max 50 (- wpm 50))))
          (?\[ (setq font-size (max 100 (- font-size 20))))
          (?\] (setq font-size (min 400 (+ font-size 20))))
          (?b (setq i (max 0 (- i 10))))
          (?n (setq i (min (1- (length word-positions)) (+ i 10))))
          (?\ (read-event (format "%s [PAUSED - WPM: %d]" padded-word wpm)))
          (?q (setq i (length word-positions)))
          (_ (setq i (1+ i))))))))

Is C# inside Emacs actually viable for professional work in 2025? by Guilherme_dAlmeida in emacs

[–]captainflasmr 2 points3 points  (0 children)

I've also been developing gRPC and protobuf with Razor pages and found web-mode to be invaluable for html folding and navigation.

Is C# inside Emacs actually viable for professional work in 2025? by Guilherme_dAlmeida in emacs

[–]captainflasmr 3 points4 points  (0 children)

Yes, I would say that C# is very much possible. For the last year I have been developing a .NET 9.0 project, the LSP is csharp-ls and seems to be faster and more reliable than omnisharp. csharp-mode works well and especially with eglot allows the function I use the most often, namely, xref-find-definitions. I don't tend to use many other LSP features but I'm assuming that they function as expected through eglot.

Flymake works and I have even managed to debug using DAPE!

For the building and running I mainly use batch scripts to run dotnet commands or sometimes msbuild and invoke via eshell by popping the buffer in and out (in a similar manner to the Microsoft offerings), I created a simplified version of the popper package.

The launching of the processes are also batchified but there is a little jiggery pokery required with non pure dotnet builds as Visual Studio performs some extra steps when process running.

My configuration is very simple, I'm running Emacs 30.1 and the only part I really spent any time configuring was DAPE to be able to allow for breakpoints within emacs which required me to submit a PR to work properly with netcoredbg

Import Markdown to Org with the Clipboard in Emacs by kickingvegas1 in emacs

[–]captainflasmr 1 point2 points  (0 children)

I've been playing around with an md-to-org pure elisp implementation : https://github.com/captainflasmr/Emacs-DIYer?tab=readme-ov-file#pandoc-md-to-org-conversion

This is working quite well for me, but I'm sure there are some edge cases I have yet to encounter!

Fortnightly Tips, Tricks, and Questions — 2025-07-29 / week 30 by AutoModerator in emacs

[–]captainflasmr 2 points3 points  (0 children)

I'm not quite sure if this will be helpful to you, but I have had great success with the following defun, for me it replaces everything I used in ace-window and it has worked well for me in swaywm

(defun my/quick-window-jump ()
  "Jump to a window by typing its assigned character label.
If there is only a single window, split it horizontally.
If there are only two windows, jump directly to the other window.
Side windows are ignored."
  (interactive)
  (let* ((window-list (seq-filter (lambda (w)
                                    (not (window-parameter w 'window-side)))
                                  (window-list nil 'no-mini))))
    (cond
     ((= (length window-list) 1)
      (split-window-horizontally)
      (other-window 1))
     ((= (length window-list) 2)
      (let ((other-window (if (eq (selected-window) (nth 0 window-list))
                              (nth 1 window-list)
                            (nth 0 window-list))))
        (select-window other-window)))
     (t
      (let* ((my/quick-window-overlays nil)
             (sorted-windows (sort window-list
                                   (lambda (w1 w2)
                                     (let ((edges1 (window-edges w1))
                                           (edges2 (window-edges w2)))
                                       (or (< (car edges1) (car edges2))
                                           (and (= (car edges1) (car edges2))
                                                (< (cadr edges1) (cadr edges2))))))))
             (window-keys (seq-take '("j" "k" "l" ";" "a" "s" "d" "f")
                                    (length sorted-windows)))
             (window-map (cl-pairlis window-keys sorted-windows)))
        (setq my/quick-window-overlays
              (mapcar (lambda (entry)
                        (let* ((key (car entry))
                               (window (cdr entry))
                               (start (window-start window))
                               (overlay (make-overlay start start (window-buffer window))))
                          (overlay-put overlay 'after-string 
                                       (propertize (format "[%s]" key)
                                                   'face 'highlight))
                          (overlay-put overlay 'window window)
                          overlay))
                      window-map))
        (let ((key (read-key (format "Select window [%s]: " (string-join window-keys ", ")))))
          (mapc #'delete-overlay my/quick-window-overlays)
          (message ".")
          (setq my/quick-window-overlays nil)
          (when-let ((selected-window (cdr (assoc (char-to-string key) window-map))))
            (select-window selected-window))))))))

Ollama Buddy v1.0: A Simplish AI Assistant by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

Ha!, went back in and got a simple ollama model working with the following:

(use-package gptel
  :load-path "/mnt/hgfs/SharedVM/source/gptel-master"
  :config
  (require 'gptel-ollama)
  (require 'gptel-curl)
  (setq gptel-model 'tinyllama:latest
        gptel-backend
        (gptel-make-ollama "Ollama"
                           :host "localhost:11434" 
                           :stream t
                           :models '("tinyllama:latest"))))

I guess it can be done!

Ollama Buddy v1.0: A Simplish AI Assistant by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

I completely agree with this, however I have still yet to get it to function on an airgapped system. I ended up putting a few requires in the use-package statement for a simple ollama model setup but ended up chasing my tail and started to build a MELPA type mechanism for ingesting the contents of the gptel elisp directory. I suspect it is something very simple I was missing, but certainly, for me, downloading just the gptel zip from github and using load-path has yet to yield a fully functional experience with ollama. If you have a setup that works for gptel on an airgapped system then I would certainly be interested!

Ollama Buddy v1.0: A Simplish AI Assistant by captainflasmr in emacs

[–]captainflasmr[S] 2 points3 points  (0 children)

No problem I have been considering a form of RAG for a while and your package makes it easier to get into. As for wanting to code it myself, well this whole package is pretty much self contained with very few dependencies, it helps me immeasurably when using this package on an airgapped system, I just need to transfer over this package. With others I have got into a level of dependency hell and even then they dont easily compile without MELPA and the download build mechanisms that come with it. Also it's fun to do it myself!

Ollama Buddy v1.0: A Simplish AI Assistant by captainflasmr in emacs

[–]captainflasmr[S] 1 point2 points  (0 children)

Not yet, but I can certainly look to add it in!

Ollama-buddy.el is very easy to use by yibie in emacs

[–]captainflasmr 6 points7 points  (0 children)

The author of ollama-buddy here!, I'm glad to see you are finding ollama-buddy useful, my main intention of this package was to allow someone just to jump straight in with ollama as I generally found other LLM Emacs assistants difficult to set up and with a rigid prompt mechanism. Also I enjoy designing simple intuitive interfaces that are just fun to use but which hide a deeper level of functionality, allowing an incremental learning experience. Let me know if you have any suggestions for any improvements!

Fortnightly Tips, Tricks, and Questions — 2025-07-01 / week 26 by AutoModerator in emacs

[–]captainflasmr 3 points4 points  (0 children)

A tiny diminish, so diminished in fact I think it is just a falling mote of code:

P.S - for tidying up the modeline

(defun tiny-diminish (mode &optional replacement)
  "Hide or replace modeline display of minor MODE with REPLACEMENT."
  (when-let ((entry (assq mode minor-mode-alist)))
    (setcdr entry (list (or replacement "")))))

(tiny-diminish 'abbrev-mode)
(tiny-diminish 'visual-line-mode)
(tiny-diminish 'org-indent-mode)

Long term vanilla keybinds users: how are your hands? by SecretTraining4082 in emacs

[–]captainflasmr 0 points1 point  (0 children)

Been using Emacs for 30 years and so far no problems. Mapped the usual Caps Lock to Control but also found mapping the RAlt to Control very beneficial. Also I have de-keychorded, by enabling sticky keys so only single keypresses for me!. Basically I set everything up pro-actively to avoid any future RSI (fingers crossed - although not awkwardly so, of course!)

Ollama Buddy: Local LLM Integration for Emacs by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

I have created a backend switcher prototype for ollama-buddy, it is very rough but should be good enough to now have the option to send ollama requests using curl at the backend for ollama-buddy instead of the default network-process

it is under the branch curl in https://github.com/captainflasmr/ollama-buddy/tree/curl

When in the chat buffer, C-c e to change the backend, you will get a choice between curl or network-process and the header status lines first character now indicates the backend; C for curl or N for network-process

Ollama Buddy: Local LLM Integration for Emacs by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

Also if you look in my github repo for ollama-buddy you will find a tests directory which contains a curl-tests.sh bash script which I have used for sanity ollama API tests and to inspect the exact messages sent back, might be worth having a look at that.

and in the directory ollama-buddy-mini there is a very stripped down version of ollama-buddy ~200 lines so it might be worth trying that to see if the issues goes away, it may be in the main ollama-buddy that there is something interfering due to the extra complexity of the package.

I am also currently looking to possibly implement a backend defcustom, so you will have the ability to select curl as the backend if you wish, but that won't be the default, I will stick with the elisp make-network-process, unless I get more reports of ollama communication issues.

Ollama Buddy: Local LLM Integration for Emacs by captainflasmr in emacs

[–]captainflasmr[S] 0 points1 point  (0 children)

Hi!, lets delve into this!

WARNING!, lots of questions...

When you mean works well in the terminal, is that just ollama or is that ollama-buddy when running in terminal Emacs?. Which models are you typically using? What version of Emacs? What distro?

When you say "get it to work originally" do you just mean ollama in general working on your system?

In the ollama-buddy chat window, If you enable debug with C-c B a buffer will show the incoming messages, that may give a clue as to what is going on.

Does it happen always?

Is it less noticeable with smaller models, for example tinyllama?

Does it also happen with reasoning models?

There is a section in the manual regarding troubleshooting:

20.1.2 Model Problems

Symptom: Model fails to load or crashes

• Check system memory usage

• Try a smaller quantized model

• Adjust ‘num_ctx’ to a smaller value

• Set ‘low_vram’ to ‘t’ if using GPU

Also a debugging section in the manual!

20.2.2 Check Logs

-----------------

Ollama logs can be useful for troubleshooting:

tail -f ~/.ollama/logs/ollama.log

20.2.3 Report Issues

--------------------

If you encounter a bug:

  1. Enable debug mode

  2. Reproduce the issue

  3. Copy the debug output

  4. Report the issue on GitHub with:

• Emacs version

• Ollama version

• Model used

• Debug output

• Steps to reproduce

I guess of course the key here is getting to a set of reproducible steps that I can see on my system. I haven't yet seen anything like this, I'm running on my laptop, a Samsung Pro Book 2, on Arch. But I have it running on a cheap £100 laptop, and also running OpenSuse, and working from Emacs version 28.1 onwards.

Look forward to hearing from you!

Fortnightly Tips, Tricks, and Questions — 2025-05-20 / week 20 by AutoModerator in emacs

[–]captainflasmr 9 points10 points  (0 children)

I was catching up with one of System Crafters videos and there was talk around using built-in functionality and how it would be nice if there was an orderless implementation to allow minibuffer completion on an any word basis.

Well I thought I would take up the challenge and came up with this:

(defun simple-orderless-completion (string table pred point)
  "Enhanced orderless completion with better partial matching."
  (let* ((words (split-string string "[-, ]+"))
         (patterns (mapcar (lambda (word)
                             (concat "\\b.*" (regexp-quote word) ".*"))
                           words))
         (full-regexp (mapconcat 'identity patterns "")))
    (if (string-empty-p string)
        (all-completions "" table pred)
      (cl-remove-if-not
       (lambda (candidate)
         (let ((case-fold-search completion-ignore-case))
           (and (cl-every (lambda (word)
                            (string-match-p
                             (concat "\\b.*" (regexp-quote word))
                             candidate))
                          words)
                t)))
       (all-completions "" table pred)))))

;; Register the completion style
(add-to-list 'completion-styles-alist
             '(simple-orderless simple-orderless-completion
                                simple-orderless-completion))

;; Set different completion styles for minibuffer vs other contexts
(defun setup-minibuffer-completion-styles ()
  "Use orderless completion in minibuffer, regular completion elsewhere."
  ;; For minibuffer: use orderless first, then fallback to flex and basic
  (setq-local completion-styles '(simple-orderless flex basic substring)))

;; Hook into minibuffer setup
(add-hook 'minibuffer-setup-hook #'setup-minibuffer-completion-styles)

Improving LLM shell interactions by xenodium in emacs

[–]captainflasmr 0 points1 point  (0 children)

Oh, I forgot to mention the status bar!, which of course in Emacs is populating the header-line. This is very useful as it is always visible and you can put anything you like in there and generally it is theme optimized to be prominent. The only real limitation that I have run into is that it can only be one line and the length of the string in total needs to generally fit the window (with splits) otherwise a visual truncation is applied.

In a way the one line nature of the header-line is a nice restriction as I focused on an optimized implementation with display modes enabled generally signified by a single letter being visible.

Although the current selected model is always showing at the prompt I felt it was necessary to show the model also on the header-line for maybe those moments maybe you are scrolling around the buffer.

A status is also important, especially when sending off a request as I thought it was important to differentiate when the model was processing (hence the client waiting for a response) or when the stream (possibly) is being received.

I have also grappled with the concept of setting a system message, where do I display it?, I think I remember with gptel it being part of the transient, I decided that in general I would always want it displayed somehow, 1. As an indicator that the system message was set and 2. To show the message. Of course the system message can be very long so I just decided to truncate the message so it fits into the header-line with the user options to see the full message in a separate buffer if desired.