# LLM CLI Deep Dive

## What Is It?

**LLM** is Simon Willison's command-line tool for interacting with any LLM from the terminal. With **10.7k+ stars**, it provides a unified interface for OpenAI, Claude, Gemini, local models via Ollama, and 50+ other providers through its plugin system.

**Repository:** [simonw/llm](https://github.com/simonw/llm)

---

## The Problem It Solves

Working with multiple LLM providers means:
- Different APIs, SDKs, and authentication
- No unified logging of conversations
- Hard to compare models
- Complex scripting for automation

LLM provides:
- **Single CLI** for all providers
- **SQLite logging** of every interaction
- **Plugin ecosystem** for extensibility
- **Templates** for reusable prompts
- **Embeddings** support built-in

---

## Key Statistics

| Metric | Value |
|--------|-------|
| **Stars** | 10,700 |
| **Forks** | 718 |
| **License** | Apache 2.0 |
| **Latest Version** | 0.28 |
| **Python** | 3.10+ |

---

## Core Features

### Basic Usage

```bash
# Simple prompt
llm "Explain quantum computing"

# Specify model
llm -m claude-3.5-sonnet "Write a haiku"

# System prompt
llm -s "You are a pirate" "Tell me about treasure"

# Continue conversation
llm -c "Tell me more"
```

### Streaming Output

```bash
# Stream response (default)
llm "Write a story"

# Wait for complete response
llm --no-stream "Analyze this code"
```

### Pipe Input

```bash
# Analyze file
cat code.py | llm "Explain this code"

# Summarize webpage
curl https://example.com | llm "Summarize"

# Git diff explanation
git diff | llm "Explain these changes"
```

---

## Supported Providers

### Built-in
- **OpenAI:** GPT-4, GPT-4o, GPT-4o-mini, o1, o3-mini, GPT-5.x

### Via Plugins

| Plugin | Provider |
|--------|----------|
| `llm-anthropic` | Claude models |
| `llm-gemini` | Google Gemini |
| `llm-ollama` | Local models via Ollama |
| `llm-gpt4all` | 17+ local models |

### OpenAI-Compatible APIs

```bash
# Custom endpoint
llm --api-base https://your-api.com/v1 "Hello"
```

---

## Installation

### Options

```bash
# pip
pip install llm

# Homebrew (macOS)
brew install llm

# pipx (isolated)
pipx install llm

# uv (modern)
uv tool install llm

# Temporary use
uvx llm "Hello world"
```

### API Key Setup

```bash
# Set OpenAI key
llm keys set openai

# Set other providers
llm keys set anthropic
llm keys set gemini
```

---

## Plugin System

### Installation

```bash
# Install plugin
llm install llm-anthropic
llm install llm-ollama

# List installed
llm plugins

# Uninstall
llm uninstall llm-anthropic
```

### Popular Plugins

| Plugin | Purpose |
|--------|---------|
| `llm-anthropic` | Claude models |
| `llm-gemini` | Google Gemini |
| `llm-ollama` | Local LLMs |
| `llm-gpt4all` | Local GPT4All models |
| `llm-mcp` | MCP integration |
| `llm-embed-ollama` | Ollama embeddings |

---

## Conversation Management

### SQLite Logging

Every interaction is automatically logged:

```bash
# View recent conversations
llm logs

# View last 10
llm logs -n 10

# Search by content
llm logs -q "quantum"

# Filter by model
llm logs -m claude-3.5-sonnet

# JSON output
llm logs --json

# Extract code blocks
llm logs -x
```

### Database Location

```bash
# Show database path
llm logs path

# macOS: ~/Library/Application Support/io.datasette.llm/logs.db
# Linux: ~/.config/io.datasette.llm/logs.db
```

### Browsing with Datasette

```bash
# Interactive web interface
datasette "$(llm logs path)"
```

---

## Templates

### Create Reusable Prompts

```bash
# Save template
llm --save explain_code "Explain this $input code in simple terms"

# Use template
cat script.py | llm -t explain_code
```

### Template Features

- System prompts
- Default model selection
- Custom parameters
- Tool definitions
- JSON schemas

---

## Structured Output

### JSON Schema

```bash
# DSL syntax
llm "Extract name and age" --schema "name, age int, bio"

# JSON schema file
llm "Parse this" --schema schema.json

# Multiple objects
llm "Extract all people" --schema-multi
```

### Example

```bash
echo "John is 30 years old" | llm --schema "name, age int"
# {"name": "John", "age": 30}
```

---

## Embeddings

### Generate Embeddings

```bash
# Single text
llm embed "Hello world"

# Store in collection
llm embed -c my_collection "Text to embed"

# Search similar
llm similar -c my_collection "Find similar text"
```

### Supported Models

- OpenAI: text-embedding-3-small, text-embedding-3-large
- Ollama: via llm-embed-ollama
- Custom providers via plugins

---

## Interactive Chat

```bash
# Start chat session
llm chat -m gpt-4o

# Continue previous chat
llm chat -m gpt-4o -c

# Commands in chat:
# !multi    - Multi-line mode
# !edit     - Open in editor
# !fragment - Insert fragment
```

---

## Advanced Features

### Model Aliases

```bash
# Create alias
llm aliases set 4o gpt-4o
llm aliases set sonnet claude-3.5-sonnet

# Use alias
llm -m 4o "Hello"
```

### Fragments (Reusable Content)

```bash
# Load from file
llm -f docs.txt "Summarize"

# Load from URL
llm -f https://example.com/guide.txt "Explain"

# Multiple fragments
llm -f file1.txt -f file2.txt "Compare"
```

### Attachments (Multi-modal)

```bash
# Analyze image
llm "Describe this image" -a photo.jpg

# Multiple attachments
llm "Compare these" -a img1.png -a img2.png
```

### Voice Input

```bash
# Voice mode (in chat)
/voice
# Records speech → transcription → prompt
```

---

## Python API

```python
import llm

# Get model
model = llm.get_model("gpt-4o-mini")

# Simple prompt
response = model.prompt("Hello")
print(response.text())

# With system prompt
response = model.prompt(
    "Write code",
    system="You are a Python expert"
)

# Streaming
for chunk in response:
    print(chunk, end="", flush=True)

# Conversation
conversation = model.conversation()
conversation.add_user("Hello")
response = conversation.add_user("Follow up")
```

---

## Configuration

### File Locations

```
~/.config/io.datasette.llm/
├── keys.json         # API keys
├── aliases.json      # Model aliases
├── templates/        # Saved templates
└── logs.db          # Conversation log
```

### Environment Variables

```bash
export OPENAI_API_KEY=sk-...
export LLM_USER_PATH=/custom/path
export LLM_MODEL=claude-3.5-sonnet
```

---

## Integration with Simon's Ecosystem

### files-to-prompt

```bash
# Convert directory to LLM input
files-to-prompt src/ | llm "Explain this codebase"
```

### Datasette

```bash
# Query logs interactively
datasette "$(llm logs path)"
```

### shot-scraper

```bash
# Screenshot → analysis
shot-scraper https://example.com | llm "Describe this page"
```

---

## Use Cases

### Development
```bash
# Code review
git diff | llm "Review this code for issues"

# Documentation
cat module.py | llm "Write docstrings"
```

### Research
```bash
# Summarize papers
cat paper.txt | llm "Key findings in bullet points"
```

### Automation
```bash
# Shell scripts
result=$(llm "Generate JSON config for nginx")
echo "$result" > nginx.conf
```

### Learning
```bash
# Explain concepts
llm "Explain monads like I'm 5"
```

---

## Best Practices

### Prompt Engineering

```bash
# Good: Specific
llm -s "You are a Python expert" "Review this for security issues" < code.py

# Good: Chained
cat code.py | llm "List issues" | llm "Prioritize by severity"
```

### Cost Management

```bash
# Use cheaper models for simple tasks
llm -m gpt-4o-mini "Quick question"

# Check logs for usage
llm logs --json | jq '.usage'
```

### Privacy

```bash
# Use local models
llm -m ollama/llama3.2 "Private data analysis"
```

---

## Comparison to Alternatives

| Tool | Strengths | Best For |
|------|-----------|----------|
| **LLM** | Plugins, logging, Unix | CLI workflows |
| **Claude Code** | Full IDE integration | Development |
| **ChatGPT CLI** | Simple, single provider | Quick OpenAI |

---

## Resources

- **Repository:** https://github.com/simonw/llm
- **Documentation:** https://llm.datasette.io
- **Plugins:** https://llm.datasette.io/en/stable/plugins/directory.html
- **Author:** Simon Willison

---

*LLM is the Swiss Army knife for command-line LLM interaction. If you work in the terminal and use multiple AI providers, this tool unifies everything with excellent logging and extensibility.*
