npm install -g air-cli → air example.com → done. ✅
AIR (Artificial Intelligence Ranking) by airanks makes AI optimization visible — a single 0–10 score for how discoverable a domain is inside AI-generated answers. See any site's AI Rank at airanks.net, or install the toolbar to see it while you browse.
air is the reference command-line client: a zero-dependency, single-file Node.js CLI that hits the exact same public API as the toolbar — the number you get here is the number you'd get there. 🧮
- 🤖 What is AIR?
- 🧭 How it works
- 📦 Install
- 🚀 Quickstart
- 🗂️ Commands
- 🚩 Options
- 🔐 Shared authentication
- 🌱 Environment variables
- 🎨 Output modes
- 🚦 Exit codes
- 🔄 Auto-upgrade
- 🧪 Development
- 🌐 The airanks ecosystem
- 📄 License
A domain that's never been looked up before gets hydrated on the spot — the CLI just polls until the result is ready.
flowchart TD
A["$ air example.com"] --> B{Looks like a domain?}
B -- "yes (or -d)" --> C["GET /api/v1/domains/{host}"]
B -- "no, or -k/-p" --> S["GET /api/v1/search?q=..."]
S --> R1["render domains / brands / phrases"]
C --> D{HTTP 429?}
D -- yes --> E["sleep Retry-After<br/>(clamped to remaining deadline)"] --> C
D -- no --> F{ai_files.status<br/>== pending?}
F -- "yes, budget left" --> G["🌀 spinner + countdown<br/>(AIR_POLL_MS)"] --> C
F -- "yes, deadline hit" --> P["render 'still gathering'<br/>exit code 2"]
F -- no --> H["render AIR score,<br/>gauge, ai_files, summary<br/>exit code 0"]
One wall-clock deadline (AIR_POLL_MAX_MS) covers the whole lookup — both 429 back-off sleeps and pending-poll waits count against it. A cold first hit is usually well under a minute; cached domains return instantly.
npm install -g air-cli- Requires Node.js 18+
- Zero runtime dependencies — one file,
air.js, ships as the whole package - Installs a global
airbinary (seebininpackage.json)
# Look up a domain's AIR score
air example.com
# Search by brand or phrase instead of a domain
air "best crm software"
# Force domain vs. keyword search explicitly
air -d example.com
air -k "project management tools"
# Machine-readable output for scripts / CI
air example.com --json
# Plain text — no color, no icons (also auto-detected for CI / TERM=dumb)
air example.com --txt🖥️ Sample terminal output (colors, gauge, and Nerd Font glyphs not shown in Markdown)
🌐 example.com 🏆 AIR 7.4/10 ██████████░░░ · top 12%
📊 tracked — 213 occurrences · 41 phrases · 9 brands
📄 llms.txt ✅ llms-full ❌ ai.txt ❌ robots.txt ✅ json-ld ✅ (Organization)
🛡️ ai crawlers: 6 allowed · 2 partial ✔ of 8
A one-line lede pulled straight from the API's summary field, italicized,
wrapped to the terminal width, the rest set in plain text.
──────────────────────────────────────────────────────────────────
🔗 airanks.net/page?d=example.com · 🗄️ dataset 2026-08-14
Icons are Font Awesome codepoints — they render with any Nerd Font / FA-patched terminal font. --txt (or NO_COLOR, TERM=dumb, CI=true) drops ANSI color; --txt additionally drops the icons and gauge and falls back to plain words like yes/no.
| Command | What it does |
|---|---|
air <domain|keyword> |
Look up a domain's AIR score, or search domains/brands/phrases if the input isn't a domain |
air login |
Interactive: paste an API key, or log in via your browser (device-code style, PKCE) |
air logout |
Remove the locally saved token (server-side token stays valid until it expires) |
air whoami |
Show who you're logged in as, and which tier the token grants |
air --help / -h |
Show usage |
A bare, never-before-seen argument is auto-classified: something that parses as a hostname (example.com) is looked up as a domain; anything else ("best crm software") is searched across domains, brands, and phrases. Override the guess with -d/-k below.
🔑 First run & browser login (click to expand)
The very first time you run air interactively with no saved key, it offers a one-time setup wizard: paste an API key, log in via browser, or continue anonymously (recorded so you're never asked again). air login re-runs the same chooser any time.
sequenceDiagram
autonumber
participant CLI as air login
participant API as airanks.net API
participant Browser as Your browser
CLI->>API: POST /cli/auth {code_challenge} (PKCE, RFC 7636 S256)
API-->>CLI: {browser_url, confirmation_code, nonce, interval}
CLI->>Browser: open browser_url (same-origin only)
Note over CLI: prints confirmation_code either way
loop until confirmed or expired
CLI->>API: POST /cli/auth/poll {nonce, code_verifier}
API-->>CLI: pending | ok(token) | denied | expired
end
CLI->>CLI: save token to ~/.config/air/auth.json (mode 0600)
Over SSH or on a headless Linux box (no DISPLAY), the CLI skips auto-opening a browser and just prints the URL + code to enter on any device.
| Flag | Description |
|---|---|
-d, --domain |
Force domain lookup |
-k, --keyword, -p, --phrase |
Force keyword/phrase search |
--json |
Emit raw JSON instead of formatted output |
--txt |
Plain text, no ANSI color or icons |
-h, --help |
Show usage |
One login works across every AIR client — this CLI, the MCP server, the SDKs, and friends. Resolution order, first match wins:
flowchart LR
A["AIR_API_KEY env var set?"] -- yes --> T1["✅ use it — always attaches,\neven cross-host"]
A -- no --> B["~/.config/air/auth.json exists?"]
B -- no --> AN["👤 anonymous tier\n(rate-limited)"]
B -- yes --> C{"saved token's host ==\ncurrent API host?"}
C -- yes --> T2["✅ use saved token"]
C -- no --> AN
AIR_API_KEY(env) — highest priority, ideal for CI/scripts, always attached regardless ofAIR_API_BASE.~/.config/air/auth.json— written byair login; only attaches to the host it was minted for, so a token never leaks to a differentAIR_API_BASE.- anonymous — no key found anywhere; still fully functional, just rate-limited.
air loginlifts the limit.
| Variable | Purpose |
|---|---|
AIR_API_KEY |
API key, takes priority over a saved login |
AIR_API_BASE |
Override the API base URL (default https://airanks.net/api/v1) |
AIR_POLL_MS |
Polling interval while a first-time lookup is gathering |
AIR_POLL_MAX_MS |
Total deadline for a lookup before giving up |
AIR_NO_UPDATE |
Disable the once-a-day auto-upgrade check entirely |
NO_COLOR |
Disable ANSI color only (icons stay) |
| Mode | Trigger | Color | Icons | Gauge |
|---|---|---|---|---|
| Rich TTY | default, interactive terminal | ✅ truecolor | ✅ Nerd Font glyphs | ✅ |
NO_COLOR |
NO_COLOR env set |
❌ | ✅ | ✅ |
--txt |
--txt flag, TERM=dumb, or CI=true |
❌ | ❌ (→ yes/no words) |
❌ |
--json |
--json flag |
— raw API JSON on stdout — |
Score coloring runs a red → amber → green truecolor ramp (0 → 10); clickable airanks.net/page links use OSC 8 hyperlinks in terminals that support them (iTerm2, kitty, Ghostty, WezTerm) and degrade to plain text everywhere else.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Hard failure — bad input, auth error, or a rate limit that outlasted the deadline |
2 |
Domain is still being gathered — re-run in a bit (never printed as a fake 0/10) |
Once every 24 hours, on an interactive run only (never in pipes, --json, --txt, or CI), air checks the npm registry for a newer air-cli and self-installs it via npm install -g air-cli@latest. Fully non-fatal — offline, a slow registry, or a permission error just gets silently skipped and your lookup still runs. Opt out entirely with AIR_NO_UPDATE=1.
git clone https://git.shoemoney.ai/airanks-net/node-cli.git
cd node-cli
npm test # node --test — unit + CLI smoke tests, no networkNo build step — air.js is the shipped artifact, run directly.
node-cli is one client among several, all speaking the same public API and sharing the same login:
| Repo | What it is |
|---|---|
chrome-extension |
The AIR toolbar — AI optimization in your browser |
rust-cli · go-cli |
air in Rust and Go |
js-sdk · python-sdk |
Programmatic SDKs for Node/browser and Python |
composer-package |
PHP API client |
mcp-server |
MCP server — air_rank / air_files / air_search tools for any agent |
agent-toolkit |
Giving AI agents (Claude, Codex, Cursor, Hermes) access to AIR |
acp-agent · acp-zed |
ACP agents (BeeAI protocol, and Zed's editor-native protocol) |
homebrew-tap |
brew install for the air CLI |
claude-skills |
Claude skills for AIR, including narrated video generation |
- AIR rankings & search: airanks.net
- Browser toolbar: airanks.net/toolbar
MIT — see LICENSE. 🎉
Built for the terminal-first. If your AIR score made you laugh or cry, that's the score doing its job. 😅