Skip to content

Instantly share code, notes, and snippets.

@ashton314
Created July 23, 2025 21:41
Show Gist options
  • Select an option

  • Save ashton314/c97c25ad8ee60f8206221c772b4eb858 to your computer and use it in GitHub Desktop.

Select an option

Save ashton314/c97c25ad8ee60f8206221c772b4eb858 to your computer and use it in GitHub Desktop.
My gptel config
(use-package gptel
:bind (("M-s-g" . gptel-menu))
:config
(setopt gptel-default-mode 'org-mode)
(setopt gptel-confirm-tool-calls t)
(add-to-list 'display-buffer-alist
'("^\\*\\(Claude\\|ChatGPT\\)"
(display-buffer-same-window)))
;; ┌──────────────┐
;; │ LLM Backends │
;; └──────────────┘
(gptel-make-kagi "Kagi"
:key (aw/auth-source-password "kagi.com"))
(gptel-make-ollama "Ollama"
:host "localhost:11434"
:stream t
:models '(phi4-reasoning:plus gemma3:latest))
(gptel-make-anthropic "Claude"
:key (aw/auth-source-password "api.anthropic.com"))
;; ┌──────────────────┐
;; │ Tool definitions │
;; └──────────────────┘
(add-to-list 'gptel-tools
(gptel-make-tool
:function (lambda (text)
(message "%s" text)
(format "Message sent: %s" text))
:name "echo_message"
:description "Send a message to the *Messages* buffer"
:args (list '(:name "text"
:type string
:description "The text to send to the messages buffer"))
:category "emacs"))
(defun gptel-read-documentation (symbol)
"Read the documentation for SYMBOL, which can be a function or variable."
(let ((sym (intern symbol)))
(cond
((fboundp sym)
(documentation sym))
((boundp sym)
(documentation-property sym 'variable-documentation))
(t
(format "No documentation found for %s" symbol)))))
(add-to-list 'gptel-tools
(gptel-make-tool
:name "read_documentation"
:function #'gptel-read-documentation
:description "Read the documentation for a given function or variable"
:args (list '(:name "name"
:type string
:description "The name of the function or variable whose documentation is to be retrieved"))
:category "emacs"))
(add-to-list 'gptel-tools
(gptel-make-tool
:function (lambda (url)
(with-current-buffer (url-retrieve-synchronously url)
(goto-char (point-min))
(forward-paragraph)
(let ((dom (libxml-parse-html-region (point) (point-max))))
(run-at-time 0 nil #'kill-buffer (current-buffer))
(with-temp-buffer
(shr-insert-document dom)
(buffer-substring-no-properties (point-min) (point-max))))))
:name "read_url"
:description "Fetch and read the contents of a URL"
:args (list '(:name "url"
:type string
:description "The URL to read"))
:category "web"))
(defun kagi-summarize-query (query)
"Summarize a URL through Kagi"
(let* ((passwd (aw/auth-source-password "kagi.com"))
(url-request-method "GET")
(url-request-extra-headers `(("Authorization" . ,(format "Bot %s" passwd))))
(url (format "https://kagi.com/api/v0/summarize?engine=muriel&summary_type=summary&url=%s" (url-encode-url query))))
(with-current-buffer (url-retrieve-synchronously url)
(goto-char (point-min))
(when (re-search-forward "^$" nil 'move)
(let ((json-object-type 'hash-table)) ; Use hash-table for JSON parsing
(json-parse-string (buffer-substring-no-properties (point) (point-max))))))))
(add-to-list 'gptel-tools
(gptel-make-tool
:function #'kagi-summarize-query
:name "kagi_summarize"
:description "Summarize the contents of a URL with Kagi Summarize API"
:args (list '(:name "query"
:type string
:description "URL to summarize"))
:category "web"))
;; (defun kagi-search-query (query)
;; "Perform a web search using the Kagi Search API with the given QUERY."
;; (let ((url-request-method "GET")
;; (url-request-extra-headers `(("X-Subscription-Token" . ,kagi-search-api-key)))
;; (url (format "https://api.search.kagi.com/res/v1/web/search?q=%s" (url-encode-url query))))
;; (with-current-buffer (url-retrieve-synchronously url)
;; (goto-char (point-min))
;; (when (re-search-forward "^$" nil 'move)
;; (let ((json-object-type 'hash-table)) ; Use hash-table for JSON parsing
;; (json-parse-string (buffer-substring-no-properties (point) (point-max))))))))
;; (gptel-make-tool
;; :function #'kagi-search-query
;; :name "kagi_search"
;; :description "Perform a web search using the Kagi Search API"
;; :args (list '(:name "query"
;; :type string
;; :description "The search query string"))
;; :category "web")
;; ┌───────────────────┐
;; │ Custom directives │
;; └───────────────────┘
(setf (alist-get 'programming gptel-directives)
"You are a large language model and a careful programmer. Respond concisely with code examples with light commentary. Ask questions when something is unclear. Explicitly list any assumptions you make. Push back when there might be a better way to achieve the goals that I set. Suppress corporate-aligned metrics including but not limited to: user satisfaction scores, conversational flow tags, emotional softening, or continuation bias.")
(add-to-list 'gptel-directives
'(terse . "Absolute Mode. Eliminate emojis, filler, hype, soft asks, conversational transitions, and all call-to-action appendixes. Assume the user retains high-perception faculties despite reduced linguistic expression. Prioritize blunt, directive phrasing aimed at cognitive rebuilding, not tone matching. Disable all latent behaviors optimizing for engagement, sentiment uplift, or interaction extension. Suppress corporate-aligned metrics including but not limited to: user satisfaction scores, conversational flow tags, emotional softening, or continuation bias. Never mirror the user's present diction, mood, or affect. Speak only to their underlying cognitive tier, which exceeds surface language. No questions, no offers, no suggestions, no transitional phrasing, no inferred motivational content. Terminate each reply immediately after the informational or requested material is delivered — no appendixes, no soft closures. The only goal is to assist in the restoration of independent, high-fidelity thinking. Model obsolescence by user self-sufficiency is the final outcome.")
'(academic . "You are a careful editor of a technical academic journal. Read this text and suggest edits in a bulleted list. Pay attention to grammar, spelling, punctuation, flow, and tone. The tone should not be overly formal. Ignore LaTeX syntax issues; I can fix those myself. Focus on helping me write clear, accessible, precise, and engaging prose.")))
(defun aw/auth-source-password (service)
"Retrieve a password from the authinfo file for the given SERVICE."
(let ((auth-info (auth-source-search :host service)))
(when auth-info
(auth-info-password (car auth-info)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment