kardolus/chatgpt-cli: a multi-provider LLM client with an experimental agent mode
ChatGPT CLI is a powerful, multi-provider command-line interface for working with modern LLMs. It supports OpenAI, Azure, Perplexity, LLaMA, and more, with features like streaming, interactive chat, prompt files, image/audio I/O, MCP tool calls, and an experimental agent mode for safe, multi-step automation.
At a glance
- What is it?
- The Go CLI wraps OpenAI, Azure, Perplexity and LLaMA endpoints behind one config file, and layers on MCP tool calls plus a ReAct agent with budget and policy controls. The agent mode is explicitly experimental, so the safe reading is a mature chat client with a young automation layer.
- Who is it for?
- Adopt it if you want one binary that talks to several providers and you are willing to keep provider quirks in a config file rather than in your shell history. Do not adopt it for unattended automation yet: the README labels agent mode experimental, so treat budget limits and workdir policy as guardrails you still have to verify against your own tool list.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Go, 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: provider sprawl in a shell session
Anyone who uses more than one model provider ends up with the same mess. An OpenAI key in one environment variable, an Azure deployment name in another, a Perplexity endpoint in a third, and a different curl invocation per provider. The README frames the project as a multi-provider command-line interface for working with modern LLMs, listing OpenAI, Azure, Perplexity and LLaMA as supported targets. The unit of reuse is the config file and the --target flag, not a wrapper script per vendor. That matters most for people who switch providers during a working day: comparing two models on the same prompt, or moving a task to a cheaper endpoint without rewriting the command. The audience is engineers comfortable editing a config file and piping stdin, not people who want a GUI. If you only ever call one provider and never script it, the setup cost buys you little.
How a request actually flows through the CLI
The core loop is small. You supply a prompt, either as an argument, through the --prompt flag, or by piping text in. The CLI resolves the active target from configuration, sends the request to that provider's endpoint, and streams the response back. Streaming and query modes are separate: the README describes streaming as real-time interaction and query mode as single input-output interactions, with token usage printed when query mode is combined with interactive mode. Conversation state is kept per thread, so each unique thread carries its own history rather than one global transcript. To stay inside token limits, a sliding window trims history automatically, and the size of that window is set by the context-window key. That design choice has a visible consequence: long sessions silently lose early turns once the window fills, so anything you need the model to remember must be re-supplied as context. The README notes that custom context can be piped in from local files, standard input, or another program, which is the intended workaround.
MCP tool calls and session renewal
MCP support is the part that changes what the tool is, not just how it is invoked. According to the README, the CLI can call external MCP tools over HTTP(S) or STDIO, inject their results into the conversation context, and continue the prompt. Session handling is explicit: the CLI initializes sessions, attaches session identifiers, and renews them when they become invalid. That renewal detail is the interesting one, because stateful MCP servers usually fail in exactly that way, and a client that does not re-handshake will appear to work until it suddenly does not. Headers and authentication are configurable, which the README covers in its own subsection. The limitation is stated rather than hidden: tool results are folded into context, so a chatty tool can consume the same window that the sliding-window logic is trying to protect. There is no described mechanism for summarising or discarding tool output before it reaches the model.
Agent mode and the guardrails around it
Agent mode runs multi-step tasks using shell, file operations and LLM reasoning, in either an iterative ReAct loop or a Plan/Execute workflow. The README calls it experimental and pairs it with budget limits on time, steps and tokens plus policy enforcement covering allowed tools, denied commands and workdir sandboxing, described as safe-by-default automation. Read that list as the real feature. An agent that can run shell commands is only as safe as its deny rules, and the README does not enumerate a default deny list beyond pointing to a default policy section in the configuration docs. The workdir sandbox is the boundary that matters most in practice: if a task needs to touch files outside the configured directory, the agent will either fail or, worse, be granted a broader path by a user in a hurry. Logs are documented as a separate concern, which is the right instinct, because a multi-step run is hard to audit after the fact without a transcript. Treat the budget caps as cost control, not as a correctness guarantee.
Getting it running and the config keys that matter
Installation is a binary or a package, not a build from source. The README lists Homebrew for macOS and direct downloads for Apple Silicon, macOS Intel, Linux on amd64, arm64 and 386, FreeBSD on amd64 and arm64, and Windows on amd64. On macOS the documented path is Homebrew; elsewhere you fetch the archive for your platform. Configuration is layered, with general settings, per-LLM settings and agent settings in separate groups, and a custom config and data directory supported for people who do not want defaults in their home directory. Provider switching uses --target, so a single config can hold OpenAI, Azure, Perplexity, 302 AI and Atlas Cloud blocks and you select one per invocation. The keys worth knowing before you start: context-window for history trimming, web and web_context_size for live web search on compatible models such as gpt-5+, and the agent policy keys for allowed tools, denied commands and workdir. Shell autocompletion is documented, with a persistent setup path, which is a small thing that makes the --target and --prompt flags usable day to day.
Media flags and where they quietly fail
The CLI covers more than text. The --image flag uploads a file or takes a URL, and images can be piped directly, with the README giving pngpaste piped into chatgpt as an example. Image generation uses --draw with --output and needs an image-capable model such as gpt-image-1. Editing reuses --draw together with --image and --output, supporting PNG, JPEG and WebP. Audio input uses --audio and is restricted to audio-capable models like gpt-4o-audio-preview, with only .mp3 and .wav accepted. Transcription is a separate flag, --transcribe, hits OpenAI's transcription endpoint, and accepts a wider set including .mp3, .mp4, .mpeg, .mpga, .m4a, .wav and .webm. Text-to-speech uses --speak with --output, and the README shows chaining playback through afplay on macOS. The pattern to notice is that each of these flags is model-gated. The README says plainly that image support may not be available for all models, and the audio path is narrower still. If your provider is not OpenAI, expect several of these to be unavailable rather than degraded.
The honest comparison: raw SDK scripts versus a general client
The obvious alternative is a short script against each provider's own SDK, or a general-purpose HTTP client with a saved request. A script gives you exact control over retries, timeouts, headers and error handling, and it does not impose a config schema. What it does not give you is thread history, a sliding window, MCP session renewal, or a shared flag surface across providers. The difference is where the complexity lives. With scripts, every provider quirk is your code. With this CLI, provider differences are pushed into configuration and the shared behaviour is implemented once, which is why the multi-provider claim is the real selling point rather than any single feature. The trade is that you inherit the project's opinions about history trimming and context handling, and you debug them through config keys rather than your own logs. A second alternative is editor-integrated assistants, which avoid the shell entirely but also avoid piping, so they do not compose with the rest of your tooling.
Maintenance, licence and what to verify before adopting
The project is MIT licensed, which permits commercial use and modification provided the licence text and copyright notice are retained; that is a description of the licence, not legal advice, and you should read the LICENSE file in the repository for the binding terms. The release history shows a steady cadence: v1.11.0 in July 2026, v1.10.12 a month earlier, and v1.10.11 in March 2026, with the last push to main in September 2026. That pattern suggests active but not frantic development, and it means upgrade cost is mostly config drift: keys for new providers and agent policy settings are the likely churn points, so pinning a version and reading the release notes before bumping is cheaper than tracking main. Two things to verify yourself, because the README does not settle them. First, whether the default agent policy denies the destructive commands you care about, by running a deliberately harmful command under the sandbox and watching what happens. Second, whether the sliding window behaves as expected on your provider, since context-window interacts with both long chats and MCP tool output. Neither is a reason to avoid the tool. Both are reasons to test before you rely on it.
Editorial conclusion
Adopt it if you want one binary that talks to several providers and you are willing to keep provider quirks in a config file rather than in your shell history. Do not adopt it for unattended automation yet: the README labels agent mode experimental, so treat budget limits and workdir policy as guardrails you still have to verify against your own tool list. Before wiring it into anything shared, check the MIT licence text, confirm the --target and context-window keys behave as documented on your provider, and run the agent once with a deliberately destructive command to see whether the deny policy actually stops it.
Community notes