Saturday, June 27, 2026

FreeCLI - LLM agnostic ncurses based CLI

Standard

FreeCLI — A Terminal Chat UI for All the LLMs, Written in C

I've been building a small open-source project over the past few weeks that scratched a personal itch: I wanted a fast, keyboard-driven terminal UI for chatting with large language models — one that wasn't locked to a single provider and didn't pull in a Python runtime or an Electron app just to show me a text box.

The result is FreeCLI, and it's now on GitHub under the GPL-3 license.

→ github.com/NikolajHansen/FreeCLI

What it is

 

FreeCLI is a three-pane ncurses application written in C. On the left you have a list of persistent chat sessions (auto-named by topic — so instead of "Chat 1" you get something like "#1 API Design"). In the middle is the scrollable conversation. On the right is a live view of background workers — because one of the more interesting features is that models can call other models mid-conversation.

It ships with four LLM providers out of the box:

  • xAI — Grok-3-fast, Grok-3, Grok-3-mini
  • Anthropic — Claude Opus, Sonnet, Haiku (3.5 and 4.5 families)
  • Google — Gemini 2.5 Flash/Pro, 2.0 Flash, 1.5 family
  • IBM watsonx — Granite 3, Llama 3.3/3.1 70B

You switch between them with /provider and /model — both pop up a small overlay right in the terminal.

The part I'm most proud of: LLM-to-LLM communication

The backend runs as a separate process and communicates with the TUI over a local TCP socket. When a model supports tools (currently xAI), it gets an ask_ai function injected into its context. It can then call that tool with a question and a target model name — say, asking Claude to review a piece of code while Grok is working through the broader problem.

Those sub-queries show up as indented entries in the workers pane with their own spinner, so you can watch the inter-AI conversation happen in real time. The sub-queries themselves have tools disabled to prevent infinite recursion.

Architecture

The split between the TUI binary (freecli) and the backend binary (freecli-backend) was a deliberate choice: the TUI has zero dependency on libcurl. It just renders, handles input, and talks IPC. The backend owns all the HTTP, JSON parsing, and provider logic. This keeps the ncurses side lean and means you could theoretically swap the backend for something else entirely.

The IPC wire format is simple: a 4-byte length prefix, a 4-byte message type, an 8-byte correlation ID, then the payload. Requests carry the session index, message history, model name, and provider ID. Replies come back as streamed tokens or structured events (worker start/end, session rename, etc.).

Session naming

After your first exchange in a new session, the backend silently fires off a one-shot call to a fast model with a prompt asking for a short topic label. The result comes back over IPC and replaces "Chat 1" with something descriptive. If the name is too long to fit in the sidebar, the selected entry scrolls like a marquee. Small detail, but it makes navigating a long list of sessions much more pleasant.

Building it

It uses autotools, which I know is not fashionable, but it handles the Linux/macOS/FreeBSD portability story well and adds zero runtime dependencies beyond what you already have on any Unix system.

 git clone https://github.com/NikolajHansen/FreeCLI
 cd FreeCLI
 ./bootstrap
 ./configure
 make -j4
 src/freecli
 

You'll need ncurses, libcurl, and a C compiler. On Debian/Ubuntu: apt install libncurses-dev libcurl4-openssl-dev. On FreeBSD: pkg install ncurses curl.

What's next

A few things on the list: streaming token output (so replies appear word by word rather than all at once), persisting the selected provider and model to a config file, a /delete command for sessions, and tool support for Anthropic (their tool format differs from OpenAI's so it needs its own implementation). Adding a new provider is fairly mechanical — one .c file and two registry entries — so if there's demand for OpenAI, Mistral, or Ollama support it shouldn't take long.

If you try it, open an issue or send a PR. Code is on GitHub, GPL-3.

https://github.com/NikolajHansen/FreeCLI

0 kommentarer: