Installation
# Install via pip (Python 3.8+)
pip install llm
# Or via Homebrew (macOS)
brew install llm
# Or via pipx (isolated environment, recommended)
pipx install llm
# Verify installation
llm --version
# Quick test (requires API key)
llm "Say hello in one sentence"
Configuration
# Set OpenAI API key (default provider)
llm keys set openai
# Prompts for key: sk-your-key-here
# Set Anthropic API key
llm keys set anthropic
# Set Google API key
llm keys set gemini
# List stored keys
llm keys
# View key storage location
llm keys path
# Keys stored at:
# macOS: ~/Library/Application Support/io.datasette.llm/keys.json
# Linux: ~/.config/io.datasette.llm/keys.json
# Windows: %APPDATA%\io.datasette.llm\keys.json
# Set a default model
llm models default gpt-4o
# View current default model
llm models default
# View log database location
llm logs path
# Open log database in sqlite-utils or Datasette
datasette "$(llm logs path)"
Core Commands / API
| Command | Description |
|---|
llm "prompt" | Run a one-shot prompt |
llm -m MODEL "prompt" | Use a specific model |
llm -s "system" | Add a system prompt |
llm -c "prompt" | Continue previous conversation |
llm chat | Start interactive chat session |
llm chat -m MODEL | Interactive chat with specific model |
llm models | List all available models |
llm models default MODEL | Set default model |
llm keys set PROVIDER | Store an API key |
llm keys | List configured keys |
llm logs | Show recent conversation logs |
llm logs list | List recent log entries |
llm logs -n 5 | Show last 5 logs |
llm logs -c | Show logs for current conversation |
llm logs path | Show log database path |
llm templates | List saved templates |
llm templates show NAME | Show a template |
llm -t TEMPLATE | Use a saved template |
llm aliases | List model aliases |
llm aliases set NAME MODEL | Create model alias |
llm embed | Create embeddings |
llm install PLUGIN | Install a plugin |
llm plugins | List installed plugins |
Advanced Usage
Model Selection and Aliases
# List all models (built-in + plugins)
llm models
# Use specific models
llm -m gpt-4o "Explain recursion"
llm -m claude-3-5-sonnet-20241022 "Write a poem about code"
llm -m gemini-1.5-pro "Analyze this data"
# Create convenient aliases
llm aliases set opus claude-3-opus-20240229
llm aliases set sonnet claude-3-5-sonnet-20241022
llm aliases set mini gpt-4o-mini
llm aliases set big gpt-4o
# Now use short aliases
llm -m sonnet "Review this PR"
llm -m mini "Quick question: what is 42 * 7?"
# List all aliases
llm aliases
# Remove an alias
llm aliases remove mini
System Prompts
# Add a system prompt inline
llm -s "You are a senior Python developer. Be concise and use type hints." \
"How do I implement a binary search?"
# Combine system prompt with template (see Templates section)
llm -s "You are a DBA." -m gpt-4o "Optimize this query: SELECT * FROM users"
# Multi-line system prompts
llm -s "$(cat system_prompt.txt)" "Do your task"
Templates
# Create a template
llm templates edit code_review
# Opens $EDITOR with YAML template format
# Template YAML format:
# ---
# system: "You are an expert code reviewer. Focus on security, performance, and readability."
# model: gpt-4o
# ---
# List all templates
llm templates
# Show a template
llm templates show code_review
# Use a template
cat my_code.py | llm -t code_review
# Template with default prompt (pre-filled)
# template.yaml:
# ---
# system: "You are a helpful assistant."
# prompt: "Summarize the following text:"
# model: gpt-4o-mini
# ---
# Template file location
llm templates path
# Create templates programmatically
mkdir -p "$(llm templates path)"
cat > "$(llm templates path)/summarize.yaml" << 'EOF'
system: |
You are an expert summarizer. Create clear, concise summaries that capture
the key points. Use bullet points for readability. Keep it under 200 words.
model: gpt-4o-mini
prompt: "Summarize the following:\n"
EOF
# Use it
cat article.txt | llm -t summarize
Conversation Continuation
# Start a conversation
llm "What is the capital of France?"
# Response: Paris is the capital of France.
# Continue the conversation with -c
llm -c "What is its population?"
# Remembers context: "Paris has a population of approximately 2.1 million..."
llm -c "What language do they speak?"
# Continues the thread
# Start interactive chat (persistent session)
llm chat
# Type messages, use Ctrl+C or type "exit" to quit
llm chat -m claude-3-5-sonnet-20241022
# Chat with a specific model
# View conversation history
llm logs -c
# Continue the last conversation from a new shell
llm -c "Keep going from where we left off"
Plugin System
# Install plugins for additional model providers
pip install llm-anthropic # Claude models (claude-3-opus, etc.)
pip install llm-gemini # Google Gemini models
pip install llm-ollama # Local models via Ollama
pip install llm-gpt4all # Local GPT4All models
pip install llm-mistral # Mistral API models
pip install llm-cohere # Cohere models
pip install llm-replicate # Run any Replicate model
pip install llm-groq # Groq fast inference
pip install llm-perplexity # Perplexity AI models
# List installed plugins
llm plugins
# After installing, set the API key
llm keys set anthropic
llm keys set gemini
# Use newly available models
llm models list | grep claude
llm -m claude-3-5-sonnet-20241022 "Hello!"
# Local models via Ollama plugin
llm install llm-ollama
ollama pull llama3
llm -m ollama/llama3 "Explain transformers"
Embeddings
# Embed a string
llm embed -m text-embedding-3-small "The quick brown fox"
# Embed from file
llm embed -m text-embedding-3-small - < document.txt
# Create an embedding collection (SQLite-backed)
llm embed-multi documents \
-m text-embedding-3-small \
--files . "*.txt"
# Semantic search across embedded collection
llm similar documents -c "machine learning concepts"
# Compare two strings
llm embed-multi comparison \
-m text-embedding-3-small \
--store \
- << 'EOF'
apple: "A fruit that grows on trees"
orange: "A citrus fruit"
car: "A motorized vehicle"
EOF
llm similar comparison -c "fruit"
Log Database Queries
# Show recent conversations
llm logs list
# Show last 5 conversations
llm logs list -n 5
# Show a specific log entry (by ID)
llm logs show 1
# Open the SQLite database directly
sqlite3 "$(llm logs path)"
# Query logs with SQL via sqlite-utils
sqlite-utils "$(llm logs path)" "SELECT * FROM responses ORDER BY datetime_utc DESC LIMIT 10"
# Use Datasette for a web UI
pip install datasette
datasette "$(llm logs path)"
# Search logs for a keyword
sqlite-utils "$(llm logs path)" \
"SELECT id, model, datetime_utc, prompt FROM responses WHERE prompt LIKE '%python%'"
# Export all logs to JSON
sqlite-utils "$(llm logs path)" "SELECT * FROM responses" > all_logs.json
Piping and Scripting
# Pipe content to llm
echo "Explain this error: NameError: name 'x' is not defined" | llm
# Process a file
cat code.py | llm "Explain what this code does"
# Summarize output of another command
git log --oneline -20 | llm "Summarize these recent commits"
# Process multiple files in a loop
for file in *.py; do
echo "=== $file ===" >> review.md
cat "$file" | llm -t code_review >> review.md
done
# Use with other Unix tools
curl -s https://api.example.com/data | jq . | llm "Analyze this API response"
# Extract structured data
cat emails.txt | llm "Extract all email addresses and return as JSON array"
# Transform data format
cat data.csv | llm "Convert this CSV to a markdown table"
Python API
import llm
# Get default model
model = llm.get_model()
# Get specific model
model = llm.get_model("gpt-4o")
# Simple prompt
response = model.prompt("What is 2+2?")
print(response.text())
# With system prompt
response = model.prompt(
"Explain recursion",
system="You are a computer science professor. Use simple analogies."
)
print(response.text())
# Stream response
for chunk in model.prompt("Tell me a long story", stream=True):
print(chunk, end="", flush=True)
# Conversation
conversation = model.conversation()
response1 = conversation.prompt("My name is Alice")
print(response1.text())
response2 = conversation.prompt("What is my name?")
print(response2.text()) # Remembers "Alice"
# Embeddings
embedding_model = llm.get_embedding_model("text-embedding-3-small")
vector = embedding_model.embed("Hello world")
print(len(vector)) # 1536 dimensions
Common Workflows
Code Review Helper
# Create a code review template
cat > "$(llm templates path)/review.yaml" << 'EOF'
system: |
You are a senior software engineer doing a code review.
Identify: security issues, bugs, performance problems, and style issues.
Format your response with clear sections for each category.
Be specific and constructive.
model: gpt-4o
EOF
# Review a file
cat mycode.py | llm -t review
# Review a git diff
git diff | llm -t review
# Review a PR
git diff main | llm -t review > review_output.md
Writing Assistant
# Create writing templates
cat > "$(llm templates path)/improve.yaml" << 'EOF'
system: "Improve this writing for clarity, conciseness, and impact. Keep the author's voice."
model: gpt-4o
EOF
cat > "$(llm templates path)/proofread.yaml" << 'EOF'
system: "Proofread for grammar, spelling, and punctuation. Show corrections with explanations."
model: gpt-4o-mini
EOF
# Use them
cat draft.txt | llm -t improve > improved.txt
cat essay.txt | llm -t proofread
Quick Reference Lookup
# Create aliases for common questions
alias lw="llm -m gpt-4o-mini" # lightweight/cheap model
# Quick syntax lookups
lw "Python: how do I format a date as YYYY-MM-DD?"
lw "Bash: one-liner to find files larger than 100MB"
lw "SQL: how do I calculate a running total?"
lw "git: undo last commit but keep changes"
Document Summarization
# Summarize any document
cat research_paper.pdf | pdftotext - - | llm "Summarize this paper in 3 bullet points"
# Summarize a webpage
curl -s "https://example.com/article" | \
python3 -c "import sys; from html.parser import HTMLParser; ..." | \
llm "Summarize the key points"
# Process a folder of notes
find ~/notes -name "*.md" -exec cat {} \; | \
llm "What are the recurring themes in these notes?"
Tips and Best Practices
Cost Management
| Model | Cost | Best For |
|---|
gpt-4o-mini | Low | Quick questions, summaries, templates |
gpt-4o | Medium | Complex reasoning, code review |
claude-3-haiku | Low | Fast, cheap tasks |
claude-3-5-sonnet | Medium | Balanced quality/cost |
ollama/llama3 | Free | Privacy, offline, experimentation |
# Check which model you're using (avoid accidentally using expensive one)
llm models default
# Use mini for bulk/scripted tasks
for f in *.txt; do cat "$f" | llm -m gpt-4o-mini "Summarize"; done
# Use full model only when quality matters
cat important_contract.txt | llm -m gpt-4o "Identify any concerning clauses"
Shell Integration Tips
# Add to ~/.bashrc or ~/.zshrc:
# Quick AI question
ai() { llm -m gpt-4o-mini "$*"; }
# Explain a command
explain() { echo "$*" | llm "Explain this shell command in plain English"; }
# Fix an error
fix() { llm -c "I got this error: $*. How do I fix it?"; }
# Summarize stdin
alias summarize="llm -m gpt-4o-mini 'Summarize this in 3 bullet points'"
# Usage:
ai "What does chmod 755 do?"
explain "find . -name '*.py' -exec grep -l 'import os' {} ;"
fix "ModuleNotFoundError: No module named 'requests'"
cat logfile.txt | summarize
Privacy Considerations
# Use local models for sensitive content
llm install llm-ollama
ollama pull llama3
# Set as default for private work
llm models default ollama/llama3
# Or use per-command
cat sensitive_document.txt | llm -m ollama/llama3 "Summarize"
# Review what's been logged
llm logs list -n 20
# The log database contains your full prompt/response history
# Location: $(llm logs path)
# Contains all queries unless disabled
Debugging
# See full request details
llm --verbose "Hello"
# Check plugin status
llm plugins
# Test a model is working
llm -m gpt-4o-mini "Reply with just: OK"
# Reinstall if issues
pip install --upgrade llm