clai
stdin → LLM → stdout.
clai turns a language model into a regular shell command. It reads input (stdin), does what the prompt says, prints the result (stdout). Everything else (grep, jq, git, cat, pbpaste, xclip) works with it the way it always has.

git diff | clai commit
cat article.txt | clai summarize | clai translate
clai code-review main.go | clai -e "Only critical bugs, numbered"

Write programs that do one thing and do it well.
Write programs to work together.
Write programs to handle text streams, because that is a universal interface.
— Doug McIlroy
More docs:
Examples ·
Advanced ·
Philosophy
Highlights
- Pipeline native. stdin in, stdout out. Composes with grep, jq, awk, and everything else.
- Works with any source. YouTube transcripts, web pages, PDFs, git diffs, clipboard. Pipe it in. See Examples.
- Zero config. Set one API key and go. No setup wizards, no interactive prompts.
- Built-in prompts. summarize, code-review, commit, translate, explain, and more.
- Multi-provider. OpenAI, Anthropic, Gemini, Vertex AI, Bedrock, Ollama, or any OpenAI-compatible endpoint.
- Local models. Point it at Ollama and nothing leaves your machine.
- Reasoning strategies. Chain-of-Thought, Tree-of-Thought, Chain-of-Draft, Self-Refine.
- Structured output. JSON Schema validation with a dedicated exit code.
Why clai
There are other terminal AI tools: llm, mods, fabric, aichat. They are good, and most of them keep growing into sessions, plugins, and chat modes.
clai bets the other way. A tool, not a platform. It amplifies your workflow without capturing it. There is no REPL and no session state; the command runs, prints its result, and exits. Behaviors live in markdown files you can open and edit. See Philosophy.
Install
brew install maxrodrigo/tap/clai
Or with Go:
go install github.com/maxrodrigo/clai/cmd/clai@latest
Pre-built binaries available on the Releases page.
Note: go install installs the binary only. For system prompts and strategies, run:
curl -sL https://github.com/maxrodrigo/clai/releases/latest/download/clai-data.tar.gz | tar -xz -C ~/.local/share
Quick Start
# Set a provider key
export OPENAI_API_KEY="sk-..."
# Named prompts
clai summarize article.txt
clai code-review main.go
# Inline prompt
clai -e "Explain in simple terms" complex.txt
# Pipeline
git diff --cached | clai commit
curl -s https://api.example.com/data | clai -e "Find anomalies"
Configuration
clai reads configuration from TOML files:
~/.config/clai/config.toml # User config
.clai/config.toml # Project config (overrides user)
Example:
model = "openai/gpt-4.1"
temperature = 1.0
max_tokens = 4096
[providers.openai]
api_key = "${OPENAI_API_KEY}"
[providers.anthropic]
api_key = "${ANTHROPIC_API_KEY}"
See docs/ADVANCED.md – Configuration Reference for a complete sample with all available options and their defaults.
Environment Variables
All config values can be set via CLAI_ prefix:
export CLAI_MODEL="anthropic/claude-sonnet"
export CLAI_TEMPERATURE="0.7"
export CLAI_MAX_TOKENS="8192"
Provider API keys use their standard environment variables:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export AWS_BEARER_TOKEN_BEDROCK="..."
Precedence
Configuration is merged in order (later overrides earlier):
- Built-in defaults
- Prompt frontmatter defaults
- User config (
~/.config/clai/config.toml)
- Project config (
.clai/config.toml)
- Environment variables (
CLAI_*)
- CLI flags
Providers
Models are specified as provider/model-name. Each provider requires an API key, set via environment variable or config file.
OpenAI
API Key: https://platform.openai.com/api-keys
export OPENAI_API_KEY="sk-..."
clai summarize -m openai/gpt-4.1 article.txt
Anthropic
API Key: https://console.anthropic.com/settings/keys
export ANTHROPIC_API_KEY="sk-ant-..."
clai summarize -m anthropic/claude-sonnet article.txt
# Extended thinking
clai -e "Find the root cause" -m anthropic/claude-sonnet --think problem.txt
AWS Bedrock
Docs: https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started-api.html
export AWS_BEARER_TOKEN_BEDROCK="..."
clai summarize -m bedrock/us.anthropic.claude-sonnet article.txt
Config (to change region):
[providers.bedrock]
api_key = "${AWS_BEARER_TOKEN_BEDROCK}"
base_url = "https://bedrock-runtime.us-west-2.amazonaws.com"
Gemini (Google AI Studio)
API Key: https://aistudio.google.com/apikey
export GOOGLE_API_KEY="..."
clai summarize -m gemini/gemini-2.5-flash article.txt
# Thinking mode
clai -e "Find the root cause" -m gemini/gemini-2.5-pro --think problem.txt
Vertex AI
Docs: https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstarts/quickstart-multimodal
Uses Application Default Credentials. Set up with gcloud auth application-default login or a service account.
export GOOGLE_CLOUD_PROJECT="my-project-id"
export GOOGLE_CLOUD_LOCATION="us-central1"
clai summarize -m vertex/gemini-2.5-flash article.txt
Config (alternative to env vars):
[providers.vertex]
project = "my-project-id"
location = "us-central1"
Custom Providers (Ollama, Groq, etc.)
Any OpenAI-compatible API:
[providers.groq]
api_key = "${GROQ_API_KEY}"
base_url = "https://api.groq.com/openai/v1"
[providers.ollama]
base_url = "http://localhost:11434/v1"
clai summarize -m groq/llama-4-scout article.txt
clai summarize -m ollama/llama3.3 article.txt
Prompts
Prompts are markdown files that tell the model what to do.

# Named prompts
clai summarize article.txt
clai code-review code.patch
clai translate notes.md
# Multiple files
clai summarize report.txt notes.txt
# Inline prompt with -e
clai -e "Explain this code" main.go
# Prompt from file with -f
clai -f my-prompt.md article.txt
# Natural language to a shell command
echo "find all Go files modified this week over 10KB" | clai shell-cmd
# -> find . -name '*.go' -mtime -7 -size +10k
# List available prompts
clai prompt list
clai prompt show summarize

Creating Prompts
Create a file in ~/.config/clai/prompts/:
---
description: One-line for `clai prompt`
model: anthropic/claude-sonnet # optional
temperature: 0.7 # optional
strategy: cot # optional
---
Your prompt instructions here.
Use it immediately:
clai your-prompt input.txt
Prompts are resolved in order (first match wins):
.clai/prompts/ (project-local)
~/.config/clai/prompts/ (user)
- Built-in
Per-Prompt Model Override
Override a prompt's model via environment variable using the pattern CLAI_MODEL_<PROMPT_NAME>:
export CLAI_MODEL_CODE_REVIEW="anthropic/claude-sonnet"
export CLAI_MODEL_SUMMARIZE="openai/gpt-4.1-mini"
See docs/ADVANCED.md for prompt authoring principles, composition, and the evaluation checklist.
Strategies
Strategies modify how the model reasons through problems.
| Strategy |
Description |
cot |
Chain-of-Thought: think step by step |
cod |
Chain-of-Draft: minimal notes per step (saves tokens) |
tot |
Tree-of-Thought: explore multiple paths, pick the best |
self-refine |
Answer, critique, improve |
clai explain --strategy cot problem.txt
clai explain --strategy none problem.txt # disable
clai strategy list # list all
Create custom strategies in ~/.config/clai/strategies/. See docs/ADVANCED.md for research basis, when to use each, and custom strategy authoring.
Structured Output
Use --schema to get JSON output conforming to a schema.

# Shorthand syntax
clai parse -s '{"name": "str", "amount": "float"}' invoice.txt
# Full JSON Schema
clai parse -s '{"type": "object", "properties": {"items": {"type": "array"}}}' data.txt
Shorthand types: str, int, float, bool, date, list, {"nested": "str"}.
Schema can also be set in prompt frontmatter:
---
schema:
title: str
author: str
tags: list
---
Extract metadata from this article.
CLI Reference
clai [flags] <prompt> [files...]
Flags
| Flag |
Description |
-e, --expression |
Inline prompt text |
-f, --file |
Read prompt from file |
-m, --model |
Model to use (e.g., openai/gpt-4.1) |
-t, --temperature |
Sampling temperature (0.0–2.0) |
--max-tokens |
Maximum tokens to generate |
-s, --schema |
Output schema (shorthand or JSON Schema) |
--strategy |
Reasoning strategy (cot, cod, tot, self-refine) |
--think |
Enable extended thinking (Anthropic/Bedrock) |
-n, --dry-run |
Show what would be sent without calling model |
-v, --verbose |
Print token counts and timing to stderr |
--color |
Force colored output even when stdout is not a TTY |
--no-color |
Disable colored output |
--version |
Print version and exit |
Commands
| Command |
Description |
clai prompt list |
List available prompts |
clai prompt show <name> |
Show prompt content |
clai prompt path <name> |
Show prompt file location |
clai prompt add <name> |
Create a new prompt and open in $EDITOR |
clai prompt update <name> |
Edit an existing prompt in $EDITOR |
clai prompt remove <name> |
Remove a user-installed prompt |
clai prompt install <owner/name> <file> |
Install a prompt from a file under a namespace |
clai strategy list |
List available strategies |
clai strategy show <name> |
Show strategy content |
clai strategy path <name> |
Show strategy file location |
clai model list |
List available models |
Exit Codes
| Code |
Meaning |
| 0 |
Success |
| 1 |
Runtime error (API failure, network error) |
| 2 |
Usage error (invalid arguments, missing config) |
| 3 |
Schema validation error (output doesn't match schema) |
Shell Completion
clai completion zsh --help
clai completion bash --help
clai completion fish --help
If clai fits your workflow, star the repo. It helps others find it.
Prompts are the easiest contribution: they're markdown files, no Go required. See CONTRIBUTING.md.