# Terminal Search Clients

Four command-line search clients, two written for a person sitting at a terminal and two written for whatever is calling them. `ddgr` and `googler` are Arun Prakash Jana's Python scripts for DuckDuckGo and Google. `kagi-ken-cli` (Carlo Zottmann) and `kagi-cli` (Microck) are unofficial clients for Kagi, built by two people who landed on the same trick: use the browser session token instead of paying for API access.

## What a query costs

Jana's two need nothing at all — no account, no key, no subscription. The [[googler]] README explains the refusal directly: Google's Custom Search JSON API runs queries against an instance of a custom search engine, caps the free tier at 100 queries a day, and would tie the tool to whatever Google decides to charge later, so googler fetches HTML instead. [[ddgr]] does the same against DuckDuckGo's `html.duckduckgo.com` endpoint, which has the side effect that it works over Tor. That is the one thing ddgr's README claims googler cannot do.

Both Kagi clients assume you already pay Kagi and then route around the second paywall. Kagi API keys are invite-only and billed separately from the subscription, so both tools read the session token out of Settings → Account → Session Link. That token is not a scoped credential; it is the account. [[kagi-ken-cli]] therefore reads it from `~/.kagi_session_token` by default rather than a flag or an environment variable, and its README names LLM and agent use as the reason — a token in a file never shows up in a process listing or a shell history.

[[kagi-cli]] takes three credentials and routes per command. `KAGI_SESSION_TOKEN` unlocks subscriber features: quick answers, Assistant, translate, ask-page, the subscriber summarizer, and the `--lens`, `--time`, `--order`, `--verbatim` and personalization search flags. `KAGI_API_KEY` reaches the paid `/api/v1` Search and Extract endpoints with Bearer auth. `KAGI_API_TOKEN` reaches the legacy `/api/v0` summarize, fastgpt and enrich with Bot auth. `news` and `smallweb` need no credential. Base search prefers the session path when both are present, and an API-first search falls back to the session path when the key is rejected, including on quota and rate-limit failures. Everything lives in `~/.config/kagi-cli/config.toml`, with named profiles (`kagi --profile work ...`) and environment overrides.

Kagi's own position is printed in kagi-cli's disclaimer: the company discourages automating unsupported interfaces through session auth and reserves the right to refuse or restrict service for clients that do. Both Kagi tools sit on that surface, so the risk is the same for either.

## Interactive by default, or JSON by default

ddgr and googler open an omniprompt: a small REPL over the current result page where `n` and `p` page, a bare index opens that result in `$BROWSER`, `o 1 3 5` opens several at once, `c 2` copies a URL to the clipboard, and anything else fires a new search with the same options. Scripted output exists and is deliberate — `--json` implies `--noprompt`, and `-C` strips the color escapes so the output survives a pipe or a redirect, which is why googler's README shows `googler -C hello world | tee output`.

The Kagi clients invert the default. kagi-ken-cli has no interactive mode at all. `kagi-ken-cli search "steve jobs"` prints JSON shaped after Kagi's official Search API — objects tagged `t: 0` carry `url`, `title` and `snippet`, `t: 1` carries the related-searches list — and `summarize --url` prints `{"data": {"output": "..."}}`. kagi-cli keeps stdout JSON and makes human rendering the opt-in: `--format pretty` for a terminal, plus `toon`, `compact`, `markdown` and `csv`, and `--template '{{rank}}. {{title}} - {{url}}'` for shaping output without reaching for `jq`.

One consequence of the session-token approach: Kagi results arrive already filtered by your account. Blocked and promoted domains, snippet length, personalization — kagi-ken-cli's README says so outright, since what it is parsing is the web search you would see in a browser. ddgr and googler issue an anonymous query and have no settings to inherit.

## Upkeep and breakage

All four use an interface the search engine did not publish for them, so all four break when the markup moves. What differs is how much surface there is to break and how visible the maintenance is.

| | source | language | install | surface |
|---|---|---|---|---|
| ddgr | DuckDuckGo HTML | Python 3.8+, GPLv3 | distro packages, PyPI, snap, single file | one search command plus omniprompt |
| googler | Google HTML | Python 3.6+, GPLv3 | distro packages, release packages, snap, single file | web, news, videos, site search |
| kagi-ken-cli | Kagi HTML via session | Node ESM | `npm install -g github:czottmann/kagi-ken-cli` | search, summarize |
| kagi-cli | Kagi session + both APIs | Rust, MIT | npm, Homebrew, Scoop, AUR, install script | ~20 commands |

The Jana pair are single standalone scripts with no config file, on purpose — the README argues aliases do the job without OS-specific differences and without a startup cost, and `alias g='googler -n 7 -c ru -l ru'` is overridable per invocation because of how `argparse` orders things. Both are packaged nearly everywhere, tracked on Repology. The visible difference between the two: ddgr's copyright line runs to 2026, while googler's Developers section stops at 2021 and the single-file install example pins v4.3.2.

kagi-cli is the most maintained-looking of the four (tagged releases, CI, a documentation site at kagi.micr.dev, four package managers) and also has by far the most to keep working. kagi-ken-cli is two commands wrapped around the `kagi-ken` package with Commander.js, installed straight from a GitHub tarball with no npm registry release.

## Fitness for an agent

An agent that decides for itself when to search ([[agentic-search]]) wants a command it can call cheaply and parse without guessing. On that test kagi-cli is the only one built for the job on purpose: `kagi mcp` runs a stdio MCP server exposing search, summarize, extract, quick-answer and news; `kagi skills` and `kagi agent` print embedded, version-matched skill guides for picking commands and auth paths; `kagi batch` runs several queries in parallel and accepts them on stdin; `--format toon` exists specifically to spend fewer tokens in an LLM context. `kagi watch` reruns a search on an interval and emits added and removed URLs, which is a monitor, not a search.

kagi-ken-cli is the opposite bet. Two commands, an output schema copied from the official API so it stays predictable across changes, and a token read from a file so it stays out of argv. Small enough to audit in an afternoon.

ddgr and googler are usable from a script — `--json`, `--np`, `-C` are all there — and cost nothing, which makes them a reasonable default when all that is needed is a list of URLs and no account should be involved. ddgr's `-i/--instant` returns only DuckDuckGo's instant answer, which is the closest either has to a structured answer rather than a link list.

Search is only the first half of the work in this vault. Something still has to turn the returned pages into readable text: [[claude-defuddle]] does it with the defuddle CLI, and [[pulpie-web-cleaning]] is the model-based version of the same job. kagi-cli folds that step in with `kagi extract`, which returns a page as markdown through the paid API.
