term-llm

command module
v0.0.37 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2026 License: MIT Imports: 1 Imported by: 0

README

term-llm logo

term-llm

A Swiss Army knife for your terminal—AI-powered commands, answers, and images at your fingertips.

Release

Features

  • Command suggestions: Natural language → executable shell commands
  • Ask questions: Get answers with optional web search
  • Chat mode: Persistent sessions with tool and MCP support
  • File editing: Edit code with AI assistance (supports line ranges)
  • File context: Include files, clipboard, stdin, or line ranges as context (-f)
  • Image generation: Create and edit images (Gemini, OpenAI, xAI, Flux)
  • MCP servers: Extend with external tools via Model Context Protocol
  • Multiple providers: Anthropic, OpenAI, ChatGPT, xAI (Grok), OpenRouter, Gemini, Gemini CLI, Zen (free tier), Claude Code (claude-bin), Ollama, LM Studio
  • Local LLMs: Run with Ollama, LM Studio, or any OpenAI-compatible server
  • Free tier available: Try it out with Zen (no API key required)
$ term-llm exec "find all go files modified today"

> find . -name "*.go" -mtime 0   Uses find with name pattern
  fd -e go --changed-within 1d   Uses fd (faster alternative)
  find . -name "*.go" -newermt "today"   Alternative find syntax
  something else...

Installation

curl -fsSL https://raw.githubusercontent.com/samsaffron/term-llm/main/install.sh | sh

Or with options:

curl -fsSL https://raw.githubusercontent.com/samsaffron/term-llm/main/install.sh | sh -s -- --version v0.1.0 --install-dir ~/bin
Go install
go install github.com/samsaffron/term-llm@latest
Build from source
git clone https://github.com/samsaffron/term-llm
cd term-llm
go build

Setup

On first run, term-llm will prompt you to choose a provider (Anthropic, OpenAI, ChatGPT, xAI, OpenRouter, Gemini, Gemini CLI, Zen, Claude Code (claude-bin), Ollama, or LM Studio).

Option 1: Try it free with Zen

OpenCode Zen provides free access to GLM 4.7 and other models. No API key required:

term-llm exec --provider zen "list files"
term-llm ask --provider zen "explain git rebase"

Or configure as default:

# In ~/.config/term-llm/config.yaml
default_provider: zen
Option 2: Use API key

Set your API key as an environment variable:

# For Anthropic
export ANTHROPIC_API_KEY=your-key

# For OpenAI
export OPENAI_API_KEY=your-key

# For xAI (Grok)
export XAI_API_KEY=your-key

# For OpenRouter
export OPENROUTER_API_KEY=your-key

# For Gemini
export GEMINI_API_KEY=your-key
Option 3: Use ChatGPT (Plus/Pro subscription)

If you have a ChatGPT Plus or Pro subscription, you can use the chatgpt provider with native OAuth authentication:

term-llm ask --provider chatgpt "explain this code"
term-llm ask --provider chatgpt:gpt-5.2-codex "code question"

On first use, you'll be prompted to authenticate via browser. Credentials are stored locally and refreshed automatically.

# In ~/.config/term-llm/config.yaml
default_provider: chatgpt

providers:
  chatgpt:
    model: gpt-5.2-codex
Option 4: Use xAI (Grok)

xAI provides access to Grok models with native web search and X (Twitter) search capabilities.

# In ~/.config/term-llm/config.yaml
default_provider: xai

providers:
  xai:
    model: grok-4-1-fast  # default model

Available models:

Model Context Description
grok-4-1-fast 2M Latest, best for tool calling (default)
grok-4-1-fast-reasoning 2M With chain-of-thought reasoning
grok-4-1-fast-non-reasoning 2M Faster, no reasoning overhead
grok-4 256K Base Grok 4 model
grok-3 / grok-3-fast 131K Previous generation
grok-3-mini / grok-3-mini-fast 131K Smaller, faster
grok-code-fast-1 256K Optimized for coding tasks

Or use the --provider flag:

term-llm ask --provider xai "explain quantum computing"
term-llm ask --provider xai -s "latest xAI news"  # uses native web + X search
term-llm ask --provider xai:grok-4-1-fast-reasoning "solve this step by step"
term-llm ask --provider xai:grok-code-fast-1 "review this code"
Option 5: Use OpenRouter

OpenRouter provides a unified OpenAI-compatible API across many models. term-llm sends attribution headers by default.

# In ~/.config/term-llm/config.yaml
default_provider: openrouter

providers:
  openrouter:
    model: x-ai/grok-code-fast-1
    app_url: https://github.com/samsaffron/term-llm
    app_title: term-llm
Model Discovery

List available models from any supported provider:

term-llm models --provider anthropic  # List Anthropic models
term-llm models --provider openrouter # List OpenRouter models
term-llm models --provider ollama     # List local Ollama models
term-llm models --provider lmstudio   # List local LM Studio models
term-llm models --json                # Output as JSON
Provider Discovery

List all available LLM providers and their configuration status:

term-llm providers                 # List all providers
term-llm providers --configured    # Only show configured providers
term-llm providers --builtin       # Only show built-in providers
term-llm providers anthropic       # Show details for specific provider
term-llm providers --json          # JSON output
Option 6: Use local LLMs (Ollama, LM Studio)

Run models locally with Ollama or LM Studio:

# List available models from your local server
term-llm models --provider ollama
term-llm models --provider lmstudio

# Configure in ~/.config/term-llm/config.yaml
default_provider: ollama

providers:
  ollama:
    type: openai_compatible
    base_url: http://localhost:11434/v1
    model: llama3.2:latest

  lmstudio:
    type: openai_compatible
    base_url: http://localhost:1234/v1
    model: deepseek-coder-v2

For other OpenAI-compatible servers (vLLM, text-generation-inference, etc.):

providers:
  my-server:
    type: openai_compatible
    base_url: http://your-server:8080/v1
    model: mixtral-8x7b
    models:  # optional: list models for shell autocomplete
      - mixtral-8x7b
      - llama-3-70b

The models list enables tab completion for --provider my-server:<TAB>. The configured model is always included in completions.

Option 7: Use Claude Code (claude-bin)

If you have Claude Code installed and logged in, you can use the claude-bin provider to run completions via the Claude Agent SDK. This requires no API key - it uses Claude Code's existing authentication.

# Use directly via --provider flag (no config needed)
term-llm ask --provider claude-bin "explain this code"
term-llm ask --provider claude-bin:haiku "quick question"  # use haiku model
term-llm exec --provider claude-bin "list files"           # command suggestions
term-llm ask --provider claude-bin -s "latest news"        # with web search

# Or configure as default
# In ~/.config/term-llm/config.yaml
default_provider: claude-bin

providers:
  claude-bin:
    model: sonnet  # opus, sonnet, or haiku

Features:

  • No API key required - uses Claude Code's OAuth authentication
  • Full tool support via MCP (exec, search, edit all work)
  • Model selection: opus, sonnet (default), haiku
  • Works immediately if Claude Code is installed and logged in
Option 8: Use existing CLI credentials (gemini-cli)

If you have gemini-cli installed and logged in, term-llm can use those credentials directly:

# Use gemini-cli credentials (no config needed)
term-llm ask --provider gemini-cli "explain this code"

Or configure as default:

# In ~/.config/term-llm/config.yaml
default_provider: gemini-cli  # uses ~/.gemini/oauth_creds.json

OpenAI-compatible providers support two URL options:

  • base_url: Base URL (e.g., https://api.cerebras.ai/v1) - /chat/completions is appended automatically
  • url: Full URL (e.g., https://api.cerebras.ai/v1/chat/completions) - used as-is without appending

Use url when your endpoint doesn't follow the standard /chat/completions path, or to paste URLs directly from API documentation.

Usage

term-llm exec "your request here"

Use arrow keys to select a command, Enter to execute, or press h for detailed help on the highlighted command. Select "something else..." to refine your request.

Use term-llm chat for a persistent session.

term-llm chat
Chat Keyboard Shortcuts
Key Action
Enter Send message
Shift+Enter Insert newline
Ctrl+C Quit
Ctrl+K Clear conversation
Ctrl+S Toggle web search
Ctrl+P Command palette
Ctrl+M Toggle MCP servers
Esc Cancel streaming
Chat Slash Commands
Command Description
/help Show help
/clear Clear conversation
/model Show current model
/search Toggle web search
/mcp Manage MCP servers
/quit Exit chat
Flags
Flag Short Description
--provider Override provider, optionally with model (e.g., openai:gpt-5.2)
--file -f File(s) to include as context (supports globs, line ranges, 'clipboard')
--auto-pick -a Auto-execute the best suggestion without prompting
--max N -n N Limit to N options in the selection UI
--search -s Enable web search (configurable: Exa, Brave, Google, DuckDuckGo) and page reading
--native-search Use provider's native search (override config)
--no-native-search Force external search tools instead of native
--print-only -p Print the command instead of executing it
--debug -d Show provider debug information
--debug-raw Emit raw debug logs with timestamps (tool calls/results, raw requests)
--system-message -m Custom system message/instructions
--stats Show session statistics (time, tokens, tool calls)
--max-turns Max agentic turns for tool execution (default: 20 for exec, 200 for chat)
Examples
term-llm exec "list files by size"              # interactive selection
term-llm exec "compress folder" --auto-pick     # auto-execute best
term-llm exec "find large files" -n 3           # show max 3 options
term-llm exec "install latest node" -s          # with web search
term-llm exec "disk usage" -p                   # print only
term-llm exec --provider zen "git status"       # use specific provider
term-llm exec --provider openai:gpt-5.2 "list"   # provider with specific model
term-llm exec --debug-raw "list files"          # raw debug logs with timestamps
term-llm exec --provider ollama:llama3.2 "list" # use local Ollama model
term-llm exec --provider lmstudio:deepseek "list"  # use LM Studio model
term-llm ask --provider openai:gpt-5.2-xhigh "complex question"  # max reasoning
term-llm exec --provider openai:gpt-5.2-low "quick task"         # faster/cheaper

# With file context
term-llm exec -f error.log "find the cause"     # analyze a file
term-llm exec -f "*.go" "run tests for these"   # glob pattern
git diff | term-llm exec "commit message"       # pipe stdin

# Ask a question
term-llm ask "What is the difference between TCP and UDP?"
term-llm ask "latest node.js version" -s        # with web search
term-llm ask --provider zen "explain docker"    # use specific provider
term-llm ask -f code.go "explain this code"     # with file context
term-llm ask -f code.go:50-100 "explain this function"  # specific lines
term-llm ask -f clipboard "what is this?"       # from clipboard
cat README.md | term-llm ask "summarize this"   # pipe stdin
term-llm ask --debug-raw "latest zig release"   # raw debug logs with timestamps

# Edit files
term-llm edit "add error handling" -f main.go
term-llm edit "refactor loop" -f utils.go:20-40  # only lines 20-40
term-llm edit "add tests" -f "*.go" --dry-run    # preview changes
term-llm edit "use the API" -f main.go -c api/client.go  # with context

# Generate images
term-llm image "a sunset over mountains"
term-llm image "logo design" --provider flux    # use specific provider
term-llm image "make it purple" -i photo.png    # edit existing image

Debugging

Use --debug to print provider-level diagnostics (requests, model info, etc.). Use --debug-raw for a timestamped, raw view of tool calls, tool results, and reconstructed requests. Raw debug is most useful for troubleshooting tool calling and search.

Image Generation

Generate and edit images using AI models from Gemini, OpenAI, or Flux (Black Forest Labs).

term-llm image "a robot cat on a rainbow"

By default, images are:

  • Saved to ~/Pictures/term-llm/ with timestamped filenames
  • Displayed in terminal via icat (if available)
  • Copied to clipboard (actual image data, pasteable in apps)
Image Flags
Flag Short Description
--input -i Input image to edit
--provider Override provider (gemini, openai, flux)
--output -o Custom output path
--no-display Skip terminal display
--no-clipboard Skip clipboard copy
--no-save Don't save to default location
--debug -d Show debug information
Image Examples
# Generate
term-llm image "cyberpunk cityscape at night"
term-llm image "minimalist logo" --provider flux
term-llm image "futuristic city" --provider xai  # uses Grok image model
term-llm image "watercolor painting" -o ./art.png

# Edit existing image (not supported by xAI)
term-llm image "add a hat" -i photo.png
term-llm image "make it look vintage" -i input.png --provider gemini
term-llm image "add sparkles" -i clipboard       # edit from clipboard

# Options
term-llm image "portrait" --no-clipboard        # don't copy to clipboard
term-llm image "landscape" --no-display         # don't show in terminal
Image Providers
Provider Model Environment Variable Config Key
Gemini (default) gemini-2.5-flash-image GEMINI_API_KEY image.gemini.api_key
OpenAI gpt-image-1 OPENAI_API_KEY image.openai.api_key
xAI grok-2-image-1212 XAI_API_KEY image.xai.api_key
Flux flux-2-pro / flux-kontext-pro BFL_API_KEY image.flux.api_key
OpenRouter various OPENROUTER_API_KEY image.openrouter.api_key

Image providers use their own credentials, separate from text providers. This allows using different API keys or accounts for text vs image generation.

Note: xAI image generation does not support image editing (-i flag).

File Editing

Edit files using natural language instructions:

term-llm edit "add error handling" --file main.go
term-llm edit "refactor to use interfaces" --file "*.go"
term-llm edit "fix the bug" --file utils.go:45-60     # only lines 45-60
term-llm edit "use the API" -f main.go -c api/client.go  # with context files
Edit Flags
Flag Short Description
--file -f File(s) to edit (required, supports globs)
--context -c Read-only reference file(s) (supports globs, 'clipboard')
--dry-run Preview changes without applying
--provider Override provider (e.g., openai:gpt-5.2-codex)
--per-edit Prompt for each edit separately
--debug -d Show debug information
Context Files

Use --context/-c to include reference files that inform the edit but won't be modified:

term-llm edit "refactor to use the client" -f handler.go -c api/client.go -c types.go

Context files are shown to the AI as read-only references. This is useful when your edit depends on types, interfaces, or patterns defined elsewhere.

You can also pipe stdin as context, which is handy for git diffs:

git diff | term-llm edit "apply these changes" -f main.go
git show HEAD~1 | term-llm edit "undo this change" -f handler.go
Line Range Syntax

Both edit and ask support line range syntax to focus on specific parts of a file:

# Edit specific lines
term-llm edit "fix this" --file main.go:11-22    # lines 11 to 22
term-llm edit "fix this" --file main.go:11-      # line 11 to end
term-llm edit "fix this" --file main.go:-22      # start to line 22

# Ask about specific lines
term-llm ask -f main.go:50-100 "explain this function"
Diff Format

term-llm supports two edit strategies:

Format Description Best For
replace Multiple parallel find/replace tool calls Most models (default)
udiff Single unified diff with elision support Codex models, large refactors

The udiff format uses unified diff syntax with -... elision to efficiently replace large code blocks without listing every line:

--- file.go
+++ file.go
@@ func BigFunction @@
-func BigFunction() error {
-...
-}
+func BigFunction() error {
+    return newImpl()
+}

Configure in ~/.config/term-llm/config.yaml:

edit:
  diff_format: auto  # auto, udiff, or replace
  • auto (default): Uses udiff for Codex models, replace for others
  • udiff: Always use unified diff format
  • replace: Always use multiple find/replace calls

Autonomous Loops

Run an agent in a loop until a completion condition is met. State persists in the filesystem—the agent reads/writes files to track progress, and each iteration starts with fresh context.

# Run until tests pass
term-llm loop --done "go test ./..." --tools all "fix the failing tests"

# Run until file contains marker
term-llm loop --done-file TODO.md:COMPLETE \
  "Implement features in {{TODO.md}}. Mark COMPLETE when done."
Loop Flags
Flag Description
--done "cmd" Exit when command returns 0
--done-file FILE:TEXT Exit when file contains TEXT
--max N Maximum iterations (0 = unlimited)
--history N Inject last N iteration summaries to avoid repeating mistakes
--yolo Auto-approve all tool operations (for unattended runs)

All standard flags work: --tools, --mcp, --agent, --provider, --search, etc.

File Expansion

Use {{file}} in your prompt to inline file contents. Files are re-read each iteration, so agents can update them for inter-iteration state:

term-llm loop --done "npm test" \
  "Implement the spec in {{SPEC.md}}. Track progress in {{TODO.md}}."
History

Use --history N to inject summaries of previous iterations. This helps the agent avoid repeating failed approaches:

term-llm loop --done "go test" --history 3 --tools all \
  "Fix the tests. Don't repeat failed approaches."

Each iteration summary includes tools used and a truncated output.

Examples
# Migration: run until no class components remain
term-llm loop --done "! grep -r 'React.Component' src/" --tools all \
  "Convert class components to hooks. One file at a time. Run tests after each."

# Research: run until conclusion written
term-llm loop --done-file RESEARCH.md:"## Conclusion" --tools read,write --search --max 20 \
  "Research WebGPU compute shaders. Current progress: {{RESEARCH.md}}. Write a Conclusion section when done."

# With an agent and iteration cap
term-llm loop @coder --done "make build" --max 20 --yolo \
  "Implement the feature described in {{SPEC.md}}"

MCP Servers

MCP (Model Context Protocol) lets you extend term-llm with external tools—browser automation, database access, API integrations, and more.

# Add from registry
term-llm mcp add playwright              # search and install
term-llm mcp add @anthropic/mcp-server-fetch

# Add from URL (HTTP transport)
term-llm mcp add https://developers.openai.com/mcp

# Use with any command
term-llm exec --mcp playwright "take a screenshot of google.com"
term-llm ask --mcp github "list my open PRs"
term-llm chat --mcp playwright,filesystem
MCP Commands
Command Description
mcp add <name-or-url> Add server from registry or URL
mcp list List configured servers
mcp test <name> Test server connection
mcp remove <name> Remove a server
mcp browse [query] Browse/search the MCP registry
mcp path Print config file path
Adding Servers

From the registry (stdio transport):

term-llm mcp add playwright           # search by name
term-llm mcp add @playwright/mcp      # exact package
term-llm mcp browse                   # interactive browser

From a URL (HTTP transport):

term-llm mcp add https://developers.openai.com/mcp
term-llm mcp add https://mcp.example.com/api
Using MCP Tools

The --mcp flag works with all commands (ask, exec, edit, chat):

# Single server
term-llm ask --mcp fetch "summarize https://example.com"
term-llm exec --mcp playwright "take a screenshot of google.com"
term-llm edit --mcp github -f main.go "update based on latest API"

# Multiple servers (comma-separated)
term-llm chat --mcp playwright,filesystem,github

# In chat, toggle servers with Ctrl+M
Configuration

MCP servers are stored in ~/.config/term-llm/mcp.json:

{
  "servers": {
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp"]
    },
    "openai-docs": {
      "type": "http",
      "url": "https://developers.openai.com/mcp"
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"
      }
    },
    "authenticated-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer your-token"
      }
    }
  }
}
Transport Types
Type Config Description
stdio command + args Runs as subprocess (npm/pypi packages)
http url Connects to remote HTTP endpoint

HTTP transport uses Streamable HTTP (MCP spec 2025-03-26).

Built-in Tools

term-llm includes built-in tools for file operations and shell access. Enable them with the --tools flag:

term-llm chat --tools read,shell,grep    # Enable specific tools
term-llm exec --tools read,write,edit,shell,grep,find,view  # Multiple tools
Available Tools
Tool Description
read Read file contents (with line ranges)
write Create/overwrite files
edit Edit existing files
shell Execute shell commands
grep Search file contents (uses ripgrep)
find Find files by glob pattern
view Display images in terminal
image Generate images via configured provider
ask_user Prompt user for input
Tool Permissions

Control which directories and commands tools can access:

# Allow read access to specific directories
term-llm chat --tools read,grep --read-dir /home/user/projects

# Allow write access to specific directories
term-llm chat --tools read,write,edit --read-dir . --write-dir ./src

# Allow specific shell commands (glob patterns)
term-llm chat --tools shell --shell-allow "git *" --shell-allow "npm test"

When a tool needs access outside approved directories, term-llm prompts for approval with options:

  • Proceed once: Allow this specific action
  • Proceed always: Allow for this session (memory only)
  • Proceed always + save: Allow permanently (saved to config)

Commands run by term-llm don't appear in your shell history. To fix this, add a shell function that uses --print-only mode.

Zsh

Add to ~/.zshrc:

tl() {
  local cmd=$(term-llm exec --print-only "$@")
  if [[ -n "$cmd" ]]; then
    print -s "$cmd"  # add to history
    eval "$cmd"
  fi
}
Bash

Add to ~/.bashrc:

tl() {
  local cmd=$(term-llm exec --print-only "$@")
  if [[ -n "$cmd" ]]; then
    history -s "$cmd"  # add to history
    eval "$cmd"
  fi
}

Then use tl instead of term-llm:

tl "find large files"
tl "install latest docker" -s      # with web search
tl "compress this folder" -a       # auto-pick best

Configuration

term-llm config        # Show current config
term-llm config edit   # Edit config file
term-llm config path   # Print config file path

Version & Updates

term-llm automatically checks for updates once per day and notifies you when a new version is available.

term-llm version       # Show version info
term-llm upgrade       # Upgrade to latest version
term-llm upgrade --version v0.2.0  # Install specific version

To disable update checks, set TERM_LLM_SKIP_UPDATE_CHECK=1.

Usage Tracking

View token usage and costs from local CLI tools:

term-llm usage                           # Show all usage
term-llm usage --provider claude-code    # Filter by provider
term-llm usage --provider term-llm       # term-llm usage only
term-llm usage --since 20250101          # From specific date
term-llm usage --breakdown               # Per-model breakdown
term-llm usage --json                    # JSON output

Supported sources: Claude Code, Gemini CLI, and term-llm's own usage logs.

Config is stored at ~/.config/term-llm/config.yaml:

default_provider: anthropic

providers:
  # Built-in providers - type is inferred from the key name
  anthropic:
    model: claude-sonnet-4-5

  openai:
    model: gpt-5.2
    credentials: codex  # or "api_key" (default)

  xai:
    model: grok-4-1-fast  # grok-4, grok-3, grok-code-fast-1

  openrouter:
    model: x-ai/grok-code-fast-1
    app_url: https://github.com/samsaffron/term-llm
    app_title: term-llm

  gemini:
    model: gemini-3-flash-preview  # uses GEMINI_API_KEY

  gemini-cli:
    model: gemini-3-flash-preview  # uses ~/.gemini/oauth_creds.json

  zen:
    model: glm-4.7-free
    # api_key is optional - leave empty for free tier

  # Local LLM providers (require explicit type)
  # Run 'term-llm models --provider ollama' to list available models
  # ollama:
  #   type: openai_compatible
  #   base_url: http://localhost:11434/v1
  #   model: llama3.2:latest

  # Custom OpenAI-compatible endpoints
  # cerebras:
  #   type: openai_compatible
  #   base_url: https://api.cerebras.ai/v1  # /chat/completions appended automatically
  #   # url: https://api.cerebras.ai/v1/chat/completions  # alternative: full URL, used as-is
  #   model: llama-4-scout-17b
  #   api_key: ${CEREBRAS_API_KEY}
  #   models:  # optional: enable autocomplete for --provider cerebras:<TAB>
  #     - llama-4-scout-17b-16e-instruct
  #     - llama-4-maverick-17b-128e-instruct
  #     - qwen-3-32b

exec:
  suggestions: 3  # number of command suggestions
  # provider: openai    # override provider for exec only
  # model: gpt-4o       # override model for exec only
  instructions: |
    I use Arch Linux with zsh.
    I prefer ripgrep over grep, fd over find.

ask:
  # provider: anthropic
  # model: claude-opus-4  # use a smarter model for questions
  instructions: |
    Be concise. I'm an experienced developer.

edit:
  # provider: openai
  # model: gpt-5.2-codex  # Codex models are optimized for code edits
  diff_format: auto  # auto, udiff, or replace

image:
  provider: gemini  # gemini, openai, xai, flux, or openrouter
  output_dir: ~/Pictures/term-llm

  gemini:
    api_key: ${GEMINI_API_KEY}
    # model: gemini-2.5-flash-image

  openai:
    api_key: ${OPENAI_API_KEY}
    # model: gpt-image-1

  xai:
    api_key: ${XAI_API_KEY}
    # model: grok-2-image-1212

  flux:
    api_key: ${BFL_API_KEY}
    # model: flux-2-pro

  openrouter:
    api_key: ${OPENROUTER_API_KEY}
    # model: google/gemini-2.5-flash-image

search:
  provider: duckduckgo  # exa, brave, google, or duckduckgo (default)

  # exa:
  #   api_key: ${EXA_API_KEY}

  # brave:
  #   api_key: ${BRAVE_API_KEY}

  # google:
  #   api_key: ${GOOGLE_SEARCH_API_KEY}
  #   cx: ${GOOGLE_SEARCH_CX}
Per-Command Provider/Model

Each command (exec, ask, edit) can have its own provider and model, overriding the global default:

default_provider: anthropic  # global default

providers:
  anthropic:
    model: claude-sonnet-4-5
  openai:
    model: gpt-5.2
  zen:
    model: glm-4.7-free

exec:
  provider: zen       # exec uses Zen (free)
  model: glm-4.7-free

ask:
  model: claude-opus-4  # ask uses global provider with a smarter model

edit:
  provider: openai
  model: gpt-5.2       # edit uses OpenAI

Precedence (highest to lowest):

  1. CLI flag: --provider openai:gpt-5.2
  2. Per-command config: exec.provider / exec.model
  3. Global config: default_provider + providers.<name>.model
Reasoning Effort (OpenAI)

For OpenAI models, you can control reasoning effort by appending -low, -medium, -high, or -xhigh to the model name:

term-llm ask --provider openai:gpt-5.2-xhigh "complex question"  # max reasoning
term-llm exec --provider openai:gpt-5.2-low "quick task"         # faster/cheaper

Or in config:

providers:
  openai:
    model: gpt-5.2-high  # effort parsed from suffix
Effort Description
low Faster, cheaper, less thorough
medium Balanced (default if not specified)
high More thorough reasoning
xhigh Maximum reasoning (only on gpt-5.2)
Extended Thinking (Anthropic)

For Anthropic models, you can enable extended thinking by appending -thinking to the model name:

term-llm ask --provider anthropic:claude-sonnet-4-5-thinking "complex question"

Or in config:

providers:
  anthropic:
    model: claude-sonnet-4-5-thinking  # enables 10k token thinking budget

Extended thinking allows Claude to reason through complex problems before responding. The thinking process uses ~10,000 tokens and is not shown in the output.

When using -s/--search, some providers (Anthropic, OpenAI, xAI, Gemini) have native web search built-in. xAI also includes X (Twitter) search. Others use external tools (configurable search provider + Jina Reader).

You can force external search even for providers with native support—useful for consistency, debugging, or when native search doesn't work well for your use case.

CLI flags:

term-llm ask "latest news" -s --no-native-search  # Force external search tools
term-llm ask "latest news" -s --native-search     # Force native (override config)

Global config (applies to all providers):

search:
  force_external: true  # Never use native search, always use external tools

Per-provider config:

providers:
  gemini:
    model: gemini-2.5-flash
    use_native_search: false  # Always use external search for this provider

  anthropic:
    model: claude-sonnet-4-5
    # use_native_search: true  # Default: use native if available

Priority (highest to lowest):

  1. CLI flag: --native-search or --no-native-search
  2. Global config: search.force_external: true
  3. Provider config: use_native_search: false
  4. Default: use native search if provider supports it
Search Providers

When using external search (non-native), you can choose from multiple search providers:

Provider Environment Variable Description
DuckDuckGo (default) Free, no API key required
Exa EXA_API_KEY AI-native semantic search
Brave BRAVE_API_KEY Independent index, privacy-focused
Google GOOGLE_SEARCH_API_KEY + GOOGLE_SEARCH_CX Google Custom Search

Configure in ~/.config/term-llm/config.yaml:

search:
  provider: exa  # exa, brave, google, or duckduckgo (default)

  exa:
    api_key: ${EXA_API_KEY}

  brave:
    api_key: ${BRAVE_API_KEY}

  google:
    api_key: ${GOOGLE_SEARCH_API_KEY}
    cx: ${GOOGLE_SEARCH_CX}  # Custom Search Engine ID

Run term-llm config to see which search providers have credentials configured.

Credentials

Most providers use API keys via environment variables. Some providers use OAuth credentials from companion CLIs:

Provider Credentials Source Description
anthropic ANTHROPIC_API_KEY Anthropic API key
openai OPENAI_API_KEY OpenAI API key
chatgpt ~/.config/term-llm/chatgpt_creds.json ChatGPT Plus/Pro OAuth
gemini GEMINI_API_KEY Google AI Studio API key
gemini-cli ~/.gemini/oauth_creds.json gemini-cli OAuth (Google Code Assist)
xai XAI_API_KEY xAI API key
openrouter OPENROUTER_API_KEY OpenRouter API key
zen ZEN_API_KEY (optional) Empty for free tier

ChatGPT and Gemini CLI work without any API key if you have a subscription or the CLI installed and logged in:

term-llm ask --provider chatgpt "question"    # uses ChatGPT Plus/Pro subscription
term-llm ask --provider gemini-cli "question" # uses ~/.gemini/oauth_creds.json
Dynamic Configuration

For advanced setups, term-llm supports dynamic resolution of API keys and URLs using special prefixes. These are resolved lazily—only when actually making an API call, not when loading config.

1Password Integration (op://)

Retrieve API keys from 1Password using secret references:

providers:
  my-provider:
    type: openai_compatible
    base_url: https://api.example.com/v1
    api_key: "op://Private/My API Key/credential"

For multiple 1Password accounts, use the ?account= query parameter:

providers:
  work-llm:
    type: openai_compatible
    base_url: https://llm.company.com/v1
    api_key: "op://Engineering/LLM Service/api_key?account=company.1password.com"

This requires the 1Password CLI (op) to be installed and signed in.

DNS SRV Records (srv://)

Discover server endpoints dynamically via DNS SRV records:

providers:
  internal-llm:
    type: openai_compatible
    url: "srv://_llm._tcp.internal.company.com/v1/chat/completions"
    api_key: ${LLM_API_KEY}

The SRV record is resolved to https://host:port/path. This is useful for:

  • Load-balanced services with multiple backends
  • Internal services with dynamic IPs
  • Kubernetes services exposed via external-dns
Shell Commands ($())

Execute arbitrary shell commands to get values:

providers:
  vault-backed:
    type: openai_compatible
    base_url: https://api.example.com/v1
    api_key: "$(vault kv get -field=api_key secret/llm)"

  aws-secrets:
    type: openai_compatible
    base_url: https://api.example.com/v1
    api_key: "$(aws secretsmanager get-secret-value --secret-id llm-key --query SecretString --output text)"
Combined Example

Using SRV discovery with 1Password credentials:

providers:
  production-llm:
    type: openai_compatible
    model: "Qwen/Qwen3-30B-A3B"
    url: "srv://_vllm._tcp.ml.company.com/v1/chat/completions"
    api_key: "op://Infrastructure/vLLM Cluster/credential?account=company.1password.com"

When you run term-llm config, these show as [set via 1password] or [set via command] without actually resolving the values (no 1Password prompt until you make an API call).

Diagnostics

Enable diagnostic logging to capture detailed information when edits fail and retry. This is useful for debugging and tuning prompts:

diagnostics:
  enabled: true
  # dir: /custom/path  # optional, defaults to ~/.local/share/term-llm/diagnostics/

When an edit fails and retries, two files are written:

  • edit-retry-{timestamp}.json - Structured data for programmatic analysis
  • edit-retry-{timestamp}.md - Human-readable with syntax-highlighted code blocks

Each diagnostic captures:

  • Provider and model used
  • Full system and user prompts
  • LLM's partial response before failure
  • Failed search pattern or diff
  • Current file content
  • Error reason
Shell Completions

Generate and install shell completions:

term-llm config completion zsh --install   # Install for zsh
term-llm config completion bash --install  # Install for bash
term-llm config completion fish --install  # Install for fish

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
udiff
Package udiff provides parsing and application of unified diffs with elision support.
Package udiff provides parsing and application of unified diffs with elision support.
internal
agents
Package agents provides named configuration bundles for term-llm.
Package agents provides named configuration bundles for term-llm.
edit
Package edit provides streaming edit parsing and application.
Package edit provides streaming edit parsing and application.
llm
mcp
skills
Package skills provides Agent Skills integration for term-llm.
Package skills provides Agent Skills integration for term-llm.
tools
Package tools provides a permission-aware local tool system for term-llm.
Package tools provides a permission-aware local tool system for term-llm.
ui

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL