clai

clai — AI for the Command Line

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) works with it the way it always has.

stdin LLM stdout

brew install maxrodrigo/tap/clai
go install github.com/maxrodrigo/clai/cmd/clai@latest

Setup the model

export OPENAI_API_KEY=sk-...    # or ANTHROPIC_API_KEY, GOOGLE_API_KEY
ollama pull llama3.3            # or run fully local
clai demo: git diff piped to clai commit

How a clai pipeline works

Every token has a job.

$ clai summarize article.txt
  • clai — reads from stdin, calls the LLM, writes to stdout.
  • summarize — built-in prompt: condenses the input into key points.
  • article.txt — any text file passed as an argument. Piped stdin also works.
$ git diff | clai code-review
  • git diff — produces a unified diff of your working changes.
  • | — connects stdout of git to stdin of clai. No temp files.
  • clai — reads the diff from stdin and passes it to the LLM.
  • code-review — built-in prompt: finds bugs, security issues, and performance problems.
$ clai draft research/*.md --strategy self-refine
  • clai — reads all input files, concatenates them, sends to LLM.
  • draft — built-in prompt: writes a long-form blog post from notes, outlines, or sources.
  • research/*.md — glob pattern: all markdown files in your research folder, read concurrently.
  • --strategy — applies a reasoning strategy before generating output.
  • self-refine — the LLM critiques its own draft and rewrites it. More tokens, better output.
$ pdftotext invoice.pdf - | clai parse -s '{"vendor":"str","amount":"float"}'
  • pdftotext — extracts text from a PDF. clai doesn't parse files, that's the shell's job.
  • | — passes the extracted text directly to clai.
  • clai — processes the text through the LLM.
  • parse — built-in prompt: extracts structured data from unstructured text.
  • -s — validates output against a JSON schema. Exit code 3 on mismatch.
  • schema — shorthand syntax. clai validates the output and retries if the shape is wrong.
$ clai draft sources/*.md | clai proofread > post.md
  • clai (1) — first LLM call: synthesizes multiple source files into a draft.
  • draft — writes a long-form blog post from the input.
  • sources/*.md — all markdown files in the sources folder.
  • | — the draft output becomes input to the next LLM call.
  • clai (2) — second LLM call: polishes the draft from the previous step.
  • proofread — built-in prompt: fixes grammar, clarity, and flow without changing meaning.
  • > post.md — redirect final output to a file. Compose with any shell tool.

What is clai?

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.

Summarize a web page. Code-review a diff. Turn research notes into a blog post. Extract structured JSON from a PDF. Or chain two LLM calls together, first one drafts, second one edits. You stay in the terminal the whole time.

Works with OpenAI, Anthropic, Gemini, Bedrock, Vertex AI, Ollama, and anything OpenAI-compatible. Switch providers with -m. Run locally with Ollama if nothing should leave your machine.

Prompts

A prompt is a markdown file that tells the model what to do. Call it by name, or write one inline with -e.

echo "find all Go files modified this week over 10KB" | clai shell-cmd
find . -name '*.go' -mtime -7 -size +10k

Strategies

A flag that changes how the model thinks before answering. cot for step-by-step, cod for minimal notes (cheaper), tot to explore multiple paths, self-refine to critique and rewrite. Learn more →

clai explain --strategy cot problem.txt

Custom prompts

Your prompts live in plain files. Edit them. Version them. Frontmatter sets defaults; the body is the instruction. Full guide →

cat ~/.config/clai/prompts/standup.md
---
description: Turn a git log into a standup update
model: openai/gpt-4.1-mini
---

Write a three-bullet standup update from this git log.
git log --oneline --since=yesterday | clai standup

Structured output

Pass a schema with -s and clai validates the output. If it doesn't match, you get exit code 3. Scripts can rely on the shape. Schema syntax →

clai parse -s '{"vendor": "str", "amount": "float"}' invoice.txt
{"vendor": "Acme Hosting", "amount": 129.00}

What can you do with clai?

Real one-liners you can copy and run. Each one pairs clai with tools you already have. More examples →

Content

Summarize a YouTube video from the command line

Grab the transcript with yt-dlp, pipe it to clai. Done.

auto-generated subtitles via yt-dlp

yt-dlp --write-auto-subs --skip-download -o "/tmp/video" "URL"
cat /tmp/video*.vtt | sed '/^[0-9]/d; /-->/d' | clai summarize

or use whisper for better transcription

yt-dlp -x --audio-format wav -o /tmp/audio.wav "URL"
whisper /tmp/audio.wav --output_format txt
clai summarize < /tmp/audio.txt
Generate a blog post from multiple sources

Point draft at a folder of notes. It reads them all and writes a post.

blog post from a folder of notes

clai draft research/topic/*.md

steer the angle

clai draft research/*.md -e "Focus on the developer experience angle"

self-refine for better output

clai draft notes.md transcript.txt --strategy self-refine

fetch a source, combine with notes, draft and polish

curl -s "https://r.jina.ai/URL" > /tmp/ref.txt
clai draft /tmp/ref.txt my-notes.md --strategy self-refine | clai proofread > post.md
Summarize a web page from the terminal

Fetch the page as clean text, pipe it in.

jina reader strips navigation and ads

curl -s "https://r.jina.ai/https://example.com/article" | clai summarize

or lynx for simple pages

lynx -dump "https://example.com/article" | clai summarize
Write a LinkedIn post or tweet from an article

Two prompts, chained. First one reads, second one formats.

straight from a url

curl -s "https://r.jina.ai/URL" | clai linkedin
curl -s "https://r.jina.ai/URL" | clai tweet

or from a local file

clai summarize article.txt | clai tweet

Git & Code

Code review a pull request

Pipe the diff through clai before you read it yourself.

review a github pr

gh pr diff 42 | clai code-review

filter to critical issues only

gh pr diff 42 | clai code-review | clai -e "Only critical bugs, numbered"

review working changes

git diff | clai code-review
Write git commit messages

Pipe your staged diff. Get a conventional commit message back.

git diff --cached | clai commit
Explain a confusing diff or error

Pipe it in, ask what it means.

explain a commit

git show abc1234 | clai -e "Explain what this change does and why"

explain the last error

!! 2>&1 | clai -e "Explain this error and suggest a fix"
Generate a changelog from git log

Feed it the commits between two tags. Get a formatted changelog.

git log --oneline v0.1.0..HEAD | clai changelog

Data & Documents

Extract structured JSON from a PDF

clai doesn't read PDFs. Extract the text first, then parse it.

extract invoice fields

pdftotext invoice.pdf - | clai parse -s '{"vendor":"str","amount":"float","date":"date","items":"list"}'

pipe to jq

pdftotext invoice.pdf - | clai parse -s '{"title":"str","tags":"list"}' | jq '.tags[]'
Convert prose to CSV or JSON

Free-form notes in, structured data out.

clai to-csv report.txt > data.csv
clai to-json notes.txt | jq .
Process files in bulk

Let the shell fan out. clai handles each file.

parallel code review

find . -name "*.go" | xargs -P4 -I{} sh -c 'clai code-review "{}" > "{}.review"'

add frontmatter to all docs

for f in docs/*.md; do
  clai -e "Add YAML frontmatter with title and description" "$f" > "$f.new" && mv "$f.new" "$f"
done

Advanced

Use reasoning strategies for hard problems

Pick a strategy based on the task. Some cost more tokens but think harder.

step-by-step for debugging

cat failing-test.go | clai -e "Why does this test fail?" --strategy cot

explore multiple solutions

clai -e "How should I structure this API?" --strategy tot design.md

self-critique for polished writing

clai draft notes.txt --strategy self-refine

save tokens in batch jobs

for f in src/*.go; do
  clai code-review --strategy cod "$f" >> reviews.txt
done
Write in your own voice

Make a voice file. Extend any prompt with it. Full guide →

create your voice file

mkdir -p ~/.config/clai/prompts/shared
cat > ~/.config/clai/prompts/shared/voice.md << 'EOF'
I write in first person. Short sentences. No corporate speak.
Words I never use: leverage, synergy, unlock.
EOF

create a prompt that uses it

cat > ~/.config/clai/prompts/my-draft.md << 'EOF'
---
extends: draft
prepend:
  - shared/voice.md
---
EOF

use it

clai my-draft research/*.md
Pick models per task

Cheap local models for simple stuff. Frontier models when it matters.

local model, nothing leaves your machine

clai summarize -m ollama/llama3.3 confidential.txt

frontier model for hard reasoning

clai -e "Evaluate this architecture" --strategy tot -m anthropic/claude-sonnet design.md

set defaults per prompt

export CLAI_MODEL_CODE_REVIEW="anthropic/claude-sonnet"
export CLAI_MODEL_SUMMARIZE="openai/gpt-4.1-mini"
export CLAI_MODEL_COMMIT="ollama/llama3.3"
Preview without spending tokens

--dry-run shows what would be sent. Free.

clai draft research/*.md --strategy self-refine --dry-run