Searching the web from the CLI
Three tools, in rough order of cost. Reach for the cheapest one that can answer the question.
| you have | use |
|---|---|
| a URL | elinks -dump <url> |
| a URL, and need structure (JSON, headers, forms) | curl / WebFetch |
| no URL — you need to find the page | llm + Gemini with Google Search |
elinks -dump is by far the cheapest way to read a page: it strips the markup
and gives you the text, where raw HTML would spend most of its tokens on
<div>s. Only fall back to curl/WebFetch when the structure is the point.
lite.duckduckgo.com (via elinks -dump) is the no-API-key search fallback and
returns a plain list of result links, but it gives you snippets, not answers —
you still have to fetch the pages yourself.
Search-backed Gemini via llm
The llm CLI is installed with the llm-gemini plugin (wired in at
flake.nix:101-104). The plugin exposes Google Search as a model option:
llm -n -m gemini-2.5-flash -o google_search 1 'your question here'
Flags that matter:
-o google_search 1— the grounding tool. Without it the model answers from stale training data and will happily do so without telling you. This is the whole point of the command; forgetting it is the one real failure mode.-n/--no-log— don't write the query into~/.config/io.datasette.llm/logs.db. Keep it for throwaway lookups.-m gemini-2.5-flash— a cheap model that serves the search tool.-m gemini-flash-latesttracks the current flash instead and gave a fresher answer in the example below; thellm-geminiplugin's model list lags the API, so thegemini-3.xnames the tools in this tree use are not offered here even though the key reaches them.
Always ask for source URLs in the prompt. Grounded answers otherwise come back uncited and you cannot check them. A model that searched and a model that guessed produce the same confident prose.
Worked example:
$ llm -n -m gemini-2.5-flash -o google_search 1 \
'What is the latest released version of GHC? Answer in one line with the release date and a source URL.'
The latest released version of GHC is 9.12.4, released on March 27, 2026.
Source URL: https://www.haskell.org/ghc/
The API key
The key is already stored in llm's own keystore (confirm with
llm keys list, which lists gemini), so the bare command above just works —
no pass invocation needed.
The same key also lives at pass internet/ai.google.dev/gemini/api-keys/interactive,
which is where the Go tools in this tree read it from. It is named default
rather than for a model because one key authenticates every model on the
account — the tools here point it at half a dozen — so a model name in the path
would be wrong for most readers and stale at the next bump.
To be explicit, or to use a different key:
llm -n -m gemini-2.5-flash -o google_search 1 \
--key "$(pass internet/ai.google.dev/gemini/api-keys/interactive)" \
'your question'
Other options worth knowing
See the full list with llm models --options -m gemini-2.5-flash.
-o url_context 1— lets the model fetch URLs mentioned in the prompt, so you can combine "search the web and read this specific page" in one call.-x/--xl— extract the first/last fenced code block, for piping.--schema— structured JSON output when you want to parse the result rather than read it.-o thinking_budget 0— disable thinking for simple factual lookups.-u/--usage— show token usage.