Fork 0
Kagi FastGPT and Universal Summarizer inside Emacs.
Go to file
Bram Schoenmakers 4e2a15a23d
Cache results by default
2024-04-12 23:37:10 +02:00
img Add screencast that demonstrates (define-kagi-fastgpt-prompt) 2024-04-10 21:09:09 +02:00
.gitignore Add some infrastructure for testing 2024-02-11 12:12:27 +01:00
Cask Enable lisp-data mode for Cask 2024-02-12 07:58:14 +01:00
LICENSE.txt Update copyright 2024-01-10 21:46:55 +01:00
README.org Add sentence 2024-04-12 23:21:51 +02:00
justfile Add testv recipe for more verbose logging 2024-04-10 07:20:20 +02:00
kagi-test.el Merge branch 'main' into prompts 2024-04-10 12:08:55 +02:00
kagi.el Add history variable to kagi-fastgpt-prompt 2024-04-12 21:25:37 +02:00
ob-kagi-fastgpt.el Cache results by default 2024-04-12 23:37:10 +02:00


kagi.el README



This Emacs package provides the following functionalities from the Kagi search engine:

Kagi's LLM offering, as a shell inspired by xenodium's chatgpt-shell.
Universal Summarizer
Summarizes texts, webpages, videos and more.

Both functions are accessed through Kagi's APIs. Before a call can be made, some setup should be done on the Kagi website (see below).


Commands and functions


Opens a shell buffer in a new window where prompts can be typed. This Kagi FastGPT typically returns output based on actual search results. When point is on one of the listed URLs, press C-c RET to open it.
Enter a prompt in the minibuffer and show the result in a separate buffer. With a universal prefix (C-u), the result is inserted at point. This function can also be used from Lisp code.

kagi.el has some functions that use FastGPT to perform certain operations on text:

Translates strings or complete buffers to another language (including programming languages).
Proofread a string or buffer.
Returns the definition of a word.

Org Babel support

kagi-fastgpt-prompt can also be used from Org mode with source blocks. Make sure to initialize the package:

  (require 'ob-kagi-fastgpt)

Then create a source block with 'language' kagi-fastgpt:

  #+begin_src kagi-fastgpt
    Can Kagi FastGPT be used in Org mode?

Then, press C-c C-c (org-babel-execute-src-block) to obtain the result below the prompt.

Universal Summarizer

Summarizes the content of a buffer.
Similarly, the text inside the region is summarized.
Prompts for a URL of which a summary is composed and displayed.
Function to retrieve a summary from a text or URL, to be used from Lisp code.

The summarize commands accept a single universal prefix, which allows you to:

  • insert the summary at point;
  • choose a (different) target language;
  • choose which summary engine to use;
  • choose which summary format to use (prose or bullet list);
  • opt-out from caching at Kagi for confidential content.

Note that texts submitted to Kagi are subject to their Privacy Policy.

Installation and configuration

kagi.el is available on MELPA and MELPA Stable.

To install from Git, clone with:

git clone https://codeberg.org/bram85/kagi.el.git /path/to/kagi.el

Note that kagi.el has a dependency on the shell-maker package, which is available on MELPA.

You may want to load and configure the package with use-package, for example put the following in your Emacs init file:

  (use-package kagi
    :ensure t
    (kagi-api-token "ABCDEF")
    ;; or use a function, e.g. with the password-store package:
    (kagi-api-token (lambda () (password-store-get "Kagi/API")))

    ;; Universal Summarizer settings
    (kagi-summarizer-engine "cecil")
    (kagi-summarizer-default-language "EN")
    (kagi-summarizer-cache t)
    ;; kagi-code defaults to fixed-pitch, but can be overridden as
    ;; follows:
    (kagi-code ((t (:inherit org-verbatim))))

    ;; likewise for kagi-bold:
    (kagi-bold ((t (:inherit modus-themes-bold)))))

The token can be supplied directly as a string, but you could write a lambda to retrieve the token from a more secure location (e.g. with the combination of pass(1) and the password-store package that comes with it).

Kagi API setup

  1. Create a Kagi account if you haven't done so already. An account is free, and comes with 100 trial searches.
  2. In your account settings, put a balance for the API part (note that this is a separate balance than the subscription). The recommendation is to start with a one-time charge of $5. Check the pricing for the FastGPT API and the Summarizer API for for the actual costs.
  3. In the API portal, create an API token. Put the result in kagi-api-token (or write a function to access it securely).

Configuration settings

Custom variable Description
kagi-api-token The Kagi API token.
kagi-fastgpt-api-url The Kagi FastGPT API entry point.
kagi-fastgpt-prompts Prompts to choose for a buffer, text or region.
kagi-summarizer-api-url The Kagi Summarizer API entry point.
kagi-summarizer-cache Determines whether the Summarizer should cache results.
kagi-summarizer-default-language Default target language of the summary.
kagi-summarizer-default-summary-format The summary format that should be returned.
kagi-summarizer-engine Which summary engine to use.

Defining your own prompts

kagi.el comes with a macro to define your own prompts easily: define-kagi-fastgpt-prompt. When the prompt contains the placeholder %s, it will be replaced with the region or an interactively used word.

An example usage of this macro comes by default with this package:

  (define-kagi-fastgpt-prompt kagi-fastgpt-prompt-definition
                              "Define the following word: %s"

The first argument is the name of the command that will be defined. The second argument the prompt that will be sent. The third argument is optional and gives your prompt a user visible name. It will be shown when calling kagi-fastgpt-prompt interactively.

The defined prompt becomes a typical Emacs command that takes one argument to fill the placeholder. You could bind the prompt command to a key, use it to integrate with Embark (see below) or to list all your prompts with a Hydra.

The prompt string may also be a function that returns the prompt string. The function may take one argument: whether the command was called interactively or not. This can be used to alter the prompt based on how the command was called. E.g. a non-interactive version could contain an instruction to say either Yes or No. See kagi-proofread for an example:

  (define-kagi-fastgpt-prompt kagi-proofread
                              (lambda (interactive-p)
                                (format "Proofread the following text. %s

  %%s" (if interactive-p "" "Say OK if there are no issues.")))

Note the %%s notation, format turns it into %s which becomes the prompt placeholder.

Embark integration

The kagi.el package can be integrated with Embark. Use it to easily summarize, translate or proofread a buffer, region or a URL. It can also be used to call your custom prompts with define-kagi-fastgpt-prompt.

In order to be consistent with all keymaps, and to avoid clashes, the functionality is behind the K prefix key. For example, press K s to invoke the summarize functionality.

  (defmacro embark-kagi-map (name &rest keys)
    "Macro for defining a keymap for accessing Kagi functionality through Embark."
    `(defvar-keymap ,name
       :doc "Keymap for accessing Kagi functionality with Embark."
       :parent nil

  (embark-kagi-map embark-kagi-buffer-map
                   "p" #'kagi-proofread
                   "s" #'kagi-summarize-buffer
                   "t" #'kagi-translate)
  (keymap-set embark-buffer-map "K" embark-kagi-buffer-map)

  (embark-kagi-map embark-kagi-region-map
                   "d" #'kagi-fastgpt-prompt-definition
                   "p" #'kagi-proofread
                   "s" #'kagi-summarize-region
                   "t" #'kagi-translate)
  (keymap-set embark-region-map "K" embark-kagi-region-map)

  (embark-kagi-map embark-kagi-url-map
                   "s" #'kagi-summarize-url)
  (keymap-set embark-url-map "K" embark-kagi-url-map)

FastGPT shell key bindings

Since the FastGPT shell inherits from comint-mode indirectly, many key bindings are also inherited. Enter the help command in the shell to get more info, or run describe-keymap on fastgpt-shell-mode-map.

One of those bindings is C-c C-o, which flushes the last output. However, this binding is used in org-mode to open a URL an point. Typical FastGPT results include URLs so one may be tempted to type C-c C-o to browse the URL, only to have the output erased (which you can undo, actually).

If you recognize this confusion, you may want to add the following line to your configuration file to shadow the comint-mode binding with something more appropriate:

  (add-hook 'fastgpt-shell-mode-hook
            (lambda ()
              (keymap-set fastgpt-shell-mode-map "C-c C-o" #'browse-url-at-point)))

Because the fastgpt-shell-mode-map only becomes available when kagi-fastgpt-shell has been invoked, the keybinding is done in a mode hook.


kagi.el comes with some unit tests, written with buttercup and can be executed in a controlled Cask environment:

  1. git clone https://github.com/cask/cask/
  2. make -C cask install
  3. Run cask in the kagi.el directory to setup the environment.
  4. Run the tests with cask exec buttercup -L .

There's also a justfile which allows you to execute just test to compile the Emacs Lisp source and run the unit tests afterwards in one go.

Needless to say, the tests won't make actual API calls. Otherwise it wouldn't be unit tests.



Breaking changes

  • Removed function kagi-fastgpt as announced in the 0.4 changelog.


  • The define-kagi-fastgpt-prompt macro allows you to define your own prompts, that may contain a placeholder to fill in relevant text.
  • The macro is used to (re)define commands:

    • kagi-fastgpt-prompt-definition: Define the a word.
    • kagi-proofread is now defined with the macro.
  • Org Babel support was added.
  • kagi-summarize has a no-cache parameter to opt out from caching at Kagi's side.
  • kagi-summarize-buffer and kagi-summarize-region also have a no-cache parameter which can be toggled interactively when called with the universal prefix.
  • Add support for traditional Chinese as possible summary language.


  • Fixed language code for Czech summaries.
  • Handle error responses when calling the FastGPT API.


Breaking changes

  • Obsoleted function kagi-fastgpt in favor of kagi-fastgpt-prompt. To be removed in a next release.


  • Introduce variable kagi-summarizer-default-summary-format, to produce a paragraph summary (default) or a take-away in bullet-list format.
  • kagi-proofread asks FastGPT to proofread the region, a buffer or a text input.
  • kagi-summarize-buffer returns the summary when called non-interactively.
  • Unit tests added.


  • Change the prompt for kagi-translate to return translations only, without preamble.
  • Added autoload markers where they were missing.
  • Language selection menu for summaries was not formatted properly.