Skip to main content

Simple text file based interface to LLMs

Project description

textllm

This is a SIMPLE text-based interface to LLMs. It is not intended to be a general purpose or overly featureful tool. It is just an easy way to call an LLM and save results in a simple format (text/markdown). It can also read images referenced in the Markdown.

textllm uses any-llm to interact with many AI models.

Setup

Install from PyPI:

$ pip install textllm

any-llm handles provider integrations. In most cases, install textllm and set the provider API key in the environment.

Usage

Simply call textllm. If no file is specified, it will create New Conversation.md with an incremented filename as needed. If the file does not exist, a template will be written.

$ textllm
$ textllm mytitle.md

That will look something like:

# !!AUTO TITLE!!

```toml
# Optional Settings
temperature = 1.0
model = 'openai/gpt-5.5'
```

Created with textllm-0.7.0 at 2026-05-24T12:00:00-06:00

--- System ---

You are an expert assistant. Provide concise, accurate answers.

--- User ---

Then modify the system prompt if needed and add your query under the user prompt. Then run:

$ textllm mytitle.md

textllm will update the title if needed, stream the response to stdout, append the response to the file, and add a new user block ready for the next prompt.

Streaming and Prompts

You can use --prompt to specify the new prompt and/or --edit to open a terminal text editor before running. textllm always streams the response to stdout while also writing response chunks to the conversation file as they arrive.

Titles and Names

As noted in "Format Description", the title is the first line. If !!AUTO TITLE!! is in the first line, textllm will generate a title for the document using the document settings, including the same model. This can be disabled or the title can be manually set. To regenerate a title, reset the title to !!AUTO TITLE!!.

If --rename is set, the document will also be renamed from the title. Numbers will be added to avoid conflicts if needed. --rename is the default for new files. This means you can do something like:

$ textllm --prompt "What is the meaning of life, the universe, and everything"

And it will respond and rename New Conversation.md to something like Meaning of Life Inquiry.md.

Environment Variables

Most behavior is governed by command-line flags but there are a few exceptions.

Variable Description
$TEXTLLM_ENV_PATH Path to an environment file for API keys. They can also just be set directly.
$TEXTLLM_EDITOR Set the editor for the --edit flag. Will fall back to $EDITOR and then vi.
$TEXTLLM_DEFAULT_MODEL Sets the default model if one is not specified and writes it into templates for new chats.
$TEXTLLM_DEFAULT_TEMPERATURE Sets the default temperature if one is not specified and writes it into templates for new chats.
$TEXTLLM_TEMPLATE_FILE Sets a file to read for the template. This is used for new chats but not for defaults.

These can be set before calling textllm or via an environment file, either .env or with the --env flag. The file can also be specified with $TEXTLLM_ENV_PATH except for itself of course.

For custom templates that should follow environment defaults for different models, either omit model and temperature from the template settings or use placeholders such as {model} and {temperature}. See Template Defaults and Environment Variables for examples.

API Environment Variables and Loading

any-llm usually reads provider API keys from environment variables. For example, OpenAI uses $OPENAI_API_KEY, Anthropic uses $ANTHROPIC_API_KEY, and Google uses $GEMINI_API_KEY or provider-specific any-llm settings.

These can be specified outside of textllm, but you can also store them in a file. You can tell textllm where to find that file in any or all of three ways:

  1. Set environment variable $TEXTLLM_ENV_PATH
  2. Create a .env file for python-dotenv to find
  3. Use the --env command-line argument

Models and Settings

Any model understood by any-llm's completion API can be used. Prefer provider/model in textllm files. textllm also accepts provider:model for compatibility with any-llm examples and older LangChain-era files, and passes the provider and remaining model id to any-llm.

model = "openai/gpt-5.5"
model = "openai:gpt-5.5"
model = "openai/gpt-4o-mini"
model = "anthropic/claude-sonnet-4-5"
model = "gemini/gemini-2.5-pro"
model = "ollama/llama3.1"
model = "openrouter/openai/gpt-4o-mini"

All TOML settings except model are passed through to any-llm. Unsupported settings will fail at the any-llm or provider layer.

Format Description

The format is designed to be very simple. An input is broken up into three main parts:

  1. Title (optional)
  2. Settings (optional)
  3. Conversation

(1) Title:

The first line of the document. If and only if it contains !!AUTO TITLE!!, it will be replaced with an appropriate title based on the document using the LLM.

Generally, this is only set once, but if !!AUTO TITLE!! is added back to the first line, it will get refreshed.

(2) Settings

Specify settings in TOML format inside a Markdown fenced code block. All settings are directly passed to any-llm, except for model, which textllm uses to select the provider and model. The template settings are the default and conversation settings update them.

Note that providers require API keys. Keys can be passed through settings when any-llm supports that, but environment variables or an environment file are usually better.

(3) Conversation

The conversation is written with simple Markdown role blocks. System, Developer, User, and Assistant are supported and are sent as OpenAI-style roles.

--- System ---

Enter your system prompt. These are like super user blocks.

--- User ---

The last "User" block is usually the question.

--- Assistant ---

The response.

Generally, you want the final block to be the new User question, but it does not have to be if --no-require-user-prompt is used. A new --- User --- heading will be added after the last response.

Role markers such as --- User --- and --- Assistant --- are reserved syntax when they appear at the start of a line. In normal assistant responses this is unlikely to matter, but if a response literally includes one of these markers, textllm may interpret it as a new conversation block on the next run. Prefix the marker with a backslash, for example \--- User ---, when you want it treated as ordinary text.

Tips and Tricks

Images

You can include images in the Markdown in normal format. Standalone image lines in user messages are converted into OpenAI-style multimodal input blocks.

Open Vim at Bottom

If using --edit to edit the file before submitting, it can be useful to open at the bottom of the file. textllm will correctly handle flags in $TEXTLLM_EDITOR so you can do something like:

export TEXTLLM_EDITOR="vim +"

More Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

textllm-0.8.0.tar.gz (15.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

textllm-0.8.0-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file textllm-0.8.0.tar.gz.

File metadata

  • Download URL: textllm-0.8.0.tar.gz
  • Upload date:
  • Size: 15.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for textllm-0.8.0.tar.gz
Algorithm Hash digest
SHA256 69086cba9a3a979e0c406ee9aa55f38126c5a08f441b71f20d5ff7c3d59d22da
MD5 125d9c7105fd0c81aebd088e00c41f91
BLAKE2b-256 69de6d5359829ea69ae3ad3893ef21c84d7782de659dde6e823d69251d941812

See more details on using hashes here.

File details

Details for the file textllm-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: textllm-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 15.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for textllm-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f0098e2ebdcb990a6fb4c466f4ed6c196c55a9ee0c45bb87628b06e7deb5e0e9
MD5 7d1ea9b6a3dc26159a070f462da89d18
BLAKE2b-256 f5911facfc135904238a0dcb35220e66503242f7f3ae1ce98310ff63948a575b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page