Model or dataset
karthink/gptel avatar
karthink/gptel

gptel: an LLM client that lives inside your Emacs buffers

A simple, extensible LLM client for Emacs

3,528 stars431 forksEmacs LispGPL-3.0

At a glance

What is it?
gptel is a GPL-3.0 Emacs Lisp package that puts a multi-backend LLM client in any buffer, chat or minibuffer. It is worth adopting if you already live in Emacs and want requests to be inspectable and editable before they leave; it is the wrong tool if you want a standalone chat application or a managed agent runtime.
Who is it for?
Adopt gptel if your work already happens in Emacs buffers and you want prompts, context and responses to stay as editable text you can inspect before sending. Do not adopt it if you need a browser UI, a hosted agent platform, or a client that manages conversation state outside your files.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem gptel solves is buffer locality, not model access

Most LLM clients are applications. You leave your editor, open a window, paste text in, copy text out. gptel inverts that. The README describes it as working "in the spirit of Emacs, available at any time and uniformly in any buffer." That sentence is the whole design brief. The unit of interaction is the buffer you are already in, not a chat window you navigate to.

This matters for a specific kind of user: someone editing source, an Org file, a shell buffer or the minibuffer, who wants a model call to operate on what is already in front of them. gptel supports in-place usage, so a region can be rewritten or filled in without a round trip through a separate application. It also supports a dedicated chat buffer for longer conversations, and the README lists both modes side by side rather than treating one as the real interface.

The audience is therefore narrow and self-selecting. If you do not already use Emacs as your primary environment, gptel offers you very little, because its main advantage is that it does not ask you to leave. If you do, the advantage is that the model becomes another command among the ones you already have.

How a request actually moves through gptel

The README states that gptel uses Curl if available and falls back to the built-in url-retrieve when it is not. That is the transport layer, and it is the only part of the data flow the material describes in concrete terms. The consequence is that gptel has no hard external dependency: on a machine without curl, requests still go out through Emacs's own networking primitive.

Above the transport, the README describes a request as something you can see before it is sent. It lists introspection as a feature, with the claim that you can see exactly what will be sent, and inspect and modify queries before sending them. It also says multi-stage requests can be paused at an intermediate stage and resumed later. Taken together, these suggest a pipeline where the assembled prompt is materialized as data you can edit, rather than being constructed and dispatched in one opaque step. The README does not document the internal function names or the structure of that intermediate representation, so treat the exact shape as something to confirm in the source.

Conversation state is file-based rather than server-based. The README says chats can be saved as regular Markdown, Org or Text files and resumed later, and that you can edit your previous prompts or LLM responses when continuing a conversation, with those edits fed back to the model. That is a meaningful architectural choice: the transcript is a document you own, in a format you already have tooling for, and editing it is a supported operation rather than a hack.

Backends, keys and the setup surface

gptel is not tied to one provider. The README's table of contents lists OpenAI, Azure, GPT4All, Ollama, Open WebUI, Gemini, Llama.cpp or Llamafile, Kagi, together.ai, Anyscale, Perplexity, Anthropic, Groq, Mistral Le Chat, OpenRouter, PrivateGPT, DeepSeek, Sambanova, Cerebras, Novita AI, xAI, AI/ML API, GitHub CopilotChat, AWS Bedrock and Moonshot. The list is long enough that the practical question is not whether your provider is covered but which of the covered providers you want to point at.

Installation is handled through the usual Emacs package channels. The README documents Straight, manual installation, Doom Emacs and Spacemacs, and the badges at the top of the file point at the NonGNU ELPA stable and devel archives plus stable.melpa.org and melpa.org. If you use package.el, the NonGNU ELPA entries are the ones to prefer for a released version.

For credentials, the README offers two optional routes. One is securing API keys with authinfo, the other is reading API keys from environment variables. Neither is mandatory in the sense that gptel refuses to run without it, but both are preferable to pasting a key into your init file, which is the default failure mode people fall into. The README also has a separate entry for using an OpenAI ChatGPT plus/pro subscription rather than an API key, which is a different authentication path and worth reading if that is your situation.

Configuration is exposed through a transient menu, and the FAQ addresses its behaviour directly: how to set options for only the current buffer, how to save transient menu options so they persist, and what to do when the menu leaves extra windows behind. The FAQ also covers changing the transient menu key bindings, and notes that under Doom Emacs sending a query from the gptel menu can fail because of a key conflict. That last item is the most useful thing in the FAQ for a new user, because it is a failure you will hit immediately rather than eventually.

Tool use and MCP, and where the abstraction gets thin

gptel supports tool use, which the README frames as equipping LLMs with agentic capabilities. There is a section on defining gptel tools, one on selecting tools, and one on LLM tool collections. Model Context Protocol integration is supported through a separate package, mcp.el, which gptel does not bundle.

That separation is the right call and also the main caveat. Tool definitions are written in Emacs Lisp, so a tool is a function with a schema attached, and the model's ability to call it depends on the backend supporting tool calls at all. The README lists tool use as a feature without qualifying it per backend, so if you are on one of the smaller or local backends, verify tool support before designing around it. The same applies to multi-modal input: the README says images and documents can be included, and the backend list is long, but capability parity across that list is not something the README claims.

Reasoning content is handled as a distinct category. The README lists support for reasoning content in LLM responses and a section on handling it, which implies it is surfaced separately rather than concatenated into the answer text. For models that emit a thinking trace, that distinction is the difference between a usable transcript and a noisy one.

The README also notes that if you do not like gptel's workflow, you can build your own for any supported model or backend using a simple API, pointing at a wiki page on defining custom gptel commands. That is the escape hatch, and its existence is a fair signal about the intended audience: people who are willing to write Lisp when the built-in flow does not fit.

The case against gptel

The clearest limitation is that gptel is an Emacs package. Every feature it has is gated behind being in Emacs, and the onboarding cost is Emacs configuration: package installation through one of four documented methods, backend selection, key storage through authinfo or environment variables, and then a transient menu whose key bindings may conflict with what you already have. None of that is unusual for Emacs, and all of it is friction for anyone who is not already past it.

The second limitation is that state lives in files you manage. The README presents saving chats as Markdown, Org or Text and resuming them as a feature, and it is one, but it also means there is no index of your conversations, no search across them beyond whatever your existing file tools provide, and no synchronisation story. If you want a client that remembers everything for you and lets you scroll back through a sidebar, this is the wrong shape.

The third is subtler. gptel is described as a client, and the README's feature list stops at the client boundary. There is no mention of a server component, a shared team workspace, usage accounting, or rate-limit handling beyond whatever the backend enforces. A team that wants centrally managed keys and per-user spend reporting will not find it here. That is not a defect in a package that describes itself as simple, but it is a real boundary and it is better to notice it before adoption than after.

Finally, the README itself is the primary documentation, supplemented by two YouTube demos (18 and 28 minutes) and a third-party 2-minute demo. Video is a poor format for checking whether a specific config key exists. Expect to read the source for anything the README does not spell out, including the exact structure of the introspection data and the precise contract of gptel-request.

What it is not: a comparison with a standalone chat client

The natural alternative is a dedicated desktop or browser chat application that talks to the same backends. The difference is not model access, since both reach the same APIs. The difference is where the text lives and who controls the request.

In a standalone client, you compose a message in a text box owned by that application. The conversation is stored in the application's database, and the request that goes to the provider is assembled by code you cannot see. In gptel, the conversation is a Markdown or Org file on disk, and the README states that you can inspect and modify queries before sending them, and that you can edit previous prompts or responses and have those edits fed back to the model. That is a different relationship with the tool: the transcript is a document, and the request is a value you can look at.

The cost of that relationship is that gptel gives you no UI beyond Emacs. No rendered markdown pane, no image thumbnails, no drag-and-drop file attachment. The README notes that responses arrive in Markdown or Org markup, which means you are reading them as text in a buffer, with whatever Org or Markdown rendering your Emacs setup provides. For someone who already reads and writes in Org, that is not a downgrade. For someone who does not, it is a substantial one.

A second alternative worth naming is writing your own thin HTTP client in Emacs Lisp. gptel's own README points at the custom commands API as the path for people who dislike its workflow, which is an implicit acknowledgment that the built-in workflow will not suit everyone. The difference is that gptel has already solved multi-backend dispatch, streaming insertion, file-based sessions and tool plumbing, and a hand-rolled client has not. Whether that saved work is worth the constraint depends on how far your desired workflow diverges from gptel's.

Maintenance, releases and licence

The repository is not archived, and the release history shows a steady cadence: v0.9.9.4 in February 2026, v0.9.9.5 in May 2026, v0.9.9.6 in September 2026, with the last push to master on the same day as the most recent release. The version numbers sit at 0.9.9.x, which is a pre-1.0 series. That has a practical consequence for anyone building on top of gptel: the README documents a custom commands API and the transient menu has configurable bindings, but a pre-1.0 package offers no compatibility guarantee, so pin a version if you depend on internals rather than on the documented commands.

Upgrade cost is mostly Emacs-shaped. If you install from NonGNU ELPA or MELPA, upgrades arrive through your normal package workflow, and the main thing that can break is configuration that touches internals or key bindings. The FAQ entry about Doom Emacs key conflicts is a reminder that binding-level breakage is a real category here, not a hypothetical one.

The licence is GPL-3.0. For most users this is unremarkable: you can install and use it freely. It matters if you intend to redistribute a modified gptel or incorporate its code into another package, because GPL-3.0 carries copyleft obligations that permissive licences do not. If you are embedding gptel in something you ship, read the licence text and, where the answer affects your product, get proper advice rather than relying on a summary. This article is not legal advice.

One maintenance note that is easy to miss: gptel's MCP support depends on mcp.el, a separate project. That is a second dependency with its own release schedule, and a break there is a break in your tool integration even if gptel itself is unchanged.

Editorial conclusion

Adopt gptel if your work already happens in Emacs buffers and you want prompts, context and responses to stay as editable text you can inspect before sending. Do not adopt it if you need a browser UI, a hosted agent platform, or a client that manages conversation state outside your files. Before committing, verify three things on your own machine: that your chosen backend is listed in the README's backend section and that its key resolves through authinfo or an environment variable, that the gptel transient menu does not collide with your existing key bindings, and that gptel-request's callback shape fits whatever you intend to build on top of it.

Official sources

  1. Issues
  2. karthink/gptel on GitHub
  3. License: GPL-3.0
  4. README
  5. Releases
Community notes

Community notes