Uno CLI
On-demand tool client for the Uno tool gateway (agentools.uno). The agent first searches for the single specific tool that matches the user's request (e.g. 'weather in Beijing' → `…
Agentrix
@lxyd-ai
Install
$ openclaw skills install @lxyd-ai/uno-cliUno CLI
Officially provided by ClawdChat (虾聊) — a narrow, on-demand tool client. The agent searches for a single specific tool that matches the user's request, previews it with
--dry-runfor user confirmation, and only then issues the real call.
Safety & user consent (read this first)
- Search → dry-run → confirm → call. The expected flow is four explicit steps.
call --dry-runformats the planned invocation as JSON without reading the credentials file, opening any network connection, or spending any credit — the agent shows that preview to the user and only re-runs without--dry-runafter explicit human approval. - Consent is per-call, not per-session. Each
callis a single, explicit tool invocation. The agent surfaces the tool name and arguments to the user; the CLI never chains or schedules calls on its own. - No background actions. The CLI exits after each command. It does not run daemons, listeners, or retries without an explicit new invocation from the agent.
- One credential, user-scoped. The CLI uses one ClawdChat-issued API key (
uno_…), stored at~/.uno/credentials.json(mode0600). This is not a browser JWT. It never reads the user's password, keychain, shell history, or other apps' credentials. - Tokens are never echoed to stdout. Every response the CLI writes is funnelled through a secret-field stripper (
uno_cli.cli._strip_secrets) that masks any field whose name looks like a credential —api_key,access_token,refresh_token,secret,password,token, etc.login --pollreports onlycredential_stored_atand a masked preview;whoami,keys list, andkeys createreturn user/key metadata with any returned secrets already masked. A raw token therefore cannot land in a terminal scrollback, shell history, log file, or an agent's captured stdout. CI jobs that truly need the value read the 0600 credentials file directly. (implementation) - Per-server third-party auth is user-initiated. When a tool needs its own OAuth (e.g. a notes service or a code-hosting service), the CLI returns an
auth_url. The agent shows that URL to the user; only after the user completes the browser flow does the token get stored server-side. The CLI itself never receives third-party passwords. - Revocation is trivial and local.
python bin/uno.py disconnect <server>revokes the stored token for one server.python bin/uno.py logoutdeletes the local credential file. Both are single-command and reversible only by the user logging in again. - Credits are real money. Before heavy or exploratory usage, the agent should call
whoamito show the user their remaining credits.
Prerequisites
- Python 3.8+ (pre-installed on most systems)
- The
uno-cliPyPI package, ≥ 1.0.2 (MIT, stdlib-only, no transitive deps) — 1.0.1 introduced unconditional stdout secret-stripping; 1.0.2 addscall --dry-runfor credential-free preview of a planned invocation
The bundled bin/uno.py is a thin launcher that forwards to the uno-cli package. This means upgrades land via pip install --upgrade uno-cli without shipping a new skill release.
CLI path (relative to this file): bin/uno.py
Step 0: Install the Uno CLI (one-time)
python3 -m pip install --user --upgrade 'uno-cli>=1.0.2'
Verify:
python bin/uno.py --version # or: uno --version
If uno-cli is missing the launcher returns {"error": "uno-cli not installed", "hint": "...", "install_url": "https://pypi.org/project/uno-cli/"} and exits with code 2.
Step 1: Check Existing Credentials First
Before doing anything else, always check if valid credentials already exist:
python bin/uno.py whoami --compact
- Success (returns user info with name/email/credits) → credentials are valid, skip login and proceed directly to tool use
- Failure (non-zero exit or
{"error": ...}) → credentials missing or rejected, proceed to Authentication below - Only start a new login flow if credentials are invalid/missing, or the user explicitly requests re-authentication
- Same OS user and same
$HOME→ next sessionwhoamiworks automatically. A new machine or an ephemeral Cloud Agent disk does not keep~/.uno
Authentication
whoami / call may print Run: uno login. Do not run bare login — it blocks the terminal. Use --start / --poll.
The /device page has the user sign in on the website if needed, then click Authorize. Opening the URL is not finished.
Stop after --start. Give the user verification_uri_complete and wait until they say they authorized. Do not run --poll in the same turn.
Check if credentials already exist (~/.uno/credentials.json) before using; only login if they are missing.
# Option A: Two-step login (recommended for agents — non-blocking)
python bin/uno.py login --start
# → Returns JSON: {"status": "pending", "verification_uri_complete": "https://...", "device_code": "xxx", ...}
# After the user confirms they authorized:
python bin/uno.py login --poll <device_code>
# → {"success": true, "name": "...", "email": "..."}
# Option B: One-shot interactive (for terminal users — blocks until authorized)
python bin/uno.py login
# Option C: Direct API Key (https://agentools.uno/dashboard?tab=keys)
python bin/uno.py login --key uno_xxxxx
# Switch accounts (multi-account)
python bin/uno.py use # list all accounts
python bin/uno.py use <name_or_email> # switch to specified account
# Logout
python bin/uno.py logout
python bin/uno.py logout --all # remove all accounts
Env var UNO_API_KEY takes priority over file config (useful for CI).
Auth Flow Details
Uno uses Device Code Flow. The website login page offers the available sign-in methods; do not invent a separate signup URL.
login --startrequests a device code from Uno server- Show
verification_uri_completeto the user. The page is/deviceon agentools.uno — they sign in on the website if needed, then Authorize. Do not--pollin the same turn. - After authorization,
login --pollretrieves an API key (uno_…) and writes it to~/.uno/credentials.json --pollwaits 10 minutes by default. The device code is valid 30 minutes. If poll times out, re-run--pollwith the samedevice_code- Server-side keys do not expire. Re-login only when: new machine / ephemeral
$HOME;logout(local wipe only); key deleted in the dashboard /keys delete; user disabled; a staleUNO_API_KEYoverrides a good file - A tool returning
auth_requiredis that server's OAuth/key, not the Uno key
Command Reference
All commands output pretty-printed JSON by default. Add --compact for single-line JSON (fewer tokens).
Status
python bin/uno.py whoami # current user info (credits, plan, keys)
python bin/uno.py health # server health check
Search Tools
python bin/uno.py search "weather" [--limit 10] [--mode hybrid|keyword|semantic] [--category dev] [--server weather-free]
--limit must be between 1 and 50 (enforced both client-side and server-side).
Each result contains:
tool(slug),name,desc,desc_en— use for display / disambiguationinput_schema(JSON Schema) — use to construct correct arguments forcallserver,server_name,category,auth_requiredstats:{avg_ms, calls_7d, success_rate, rating}— use to pick between equivalent servers (prefer highercalls_7dandrating)pricing:{mode, cost}—per_callcredits orper_tokenprice
If desc ends with …, it was truncated (500 chars for search, 200 for browse). Run tool get <slug> for the full version.
How Search Works (Agent Best Practices)
Search uses hybrid retrieval under the hood:
- Smart tokenizer — drops Chinese/English stopwords (
搜索/关于/项目/please/find/...), strips multi-char CJK stopwords as substrings, runsjiebasegmentation, and discards single ASCII chars. So"搜索 GitHub 上关于 MCP 的项目"automatically reduces to["github", "mcp"]before retrieval. - Keyword channel — OR-based candidate selection with per-row weighted scoring. Strongest signal is an exact server-slug match (e.g.
"github"→ servergithub→ +10 points). - Semantic channel — pgvector cosine similarity over tool description embeddings (30-day Redis cache).
- Adaptive RRF fusion — if the keyword channel has a clear winner (server-slug exact match), its weight is boosted 2.5× so strong keyword signals aren't drowned by mediocre dual-channel matches.
Quality is regression-tested against tests/golden_queries.json (52 bilingual queries) via scripts/evaluate_search.py. Last production measurement (2026-04-18):
| Metric | Score | Target | Status |
|---|---|---|---|
| NDCG@5 | 0.889 | ≥ 0.75 | ✓ PASS |
| MRR | 0.946 | ≥ 0.75 | ✓ PASS |
| Recall@5 | 0.472 | ≥ 0.45 | ✓ PASS (theoretical max on this dataset is 0.54 — see note below) |
English and Chinese queries perform symmetrically: NDCG@5 en=0.886, zh=0.895. The Recall@5 ceiling of ~0.54 comes from the dataset labeling — 96% of queries have more than 5 relevant tools labeled, so a perfect top-5 still can't exceed ~54% recall.
Query tips (most → least important):
- Short capability keywords are best:
"weather","github mcp","image generation"— 1-3 words beats everything else. - Use the server slug when known (e.g.
"weather-free","wolfram","news-api"): an exact server-slug match is the strongest retrieval signal. - Full questions also work, because the tokenizer strips stopwords automatically — but short keywords are still faster and more precise.
- Chinese and English are symmetric:
"天气"≈"weather","搜索"≈"search". - If no results, try a synonym:
"map"→"navigation","translate"→"翻译".
Query pattern examples (read-only look-ups, agent should still surface results to the user):
| User intent | Good query (preferred) | Also works |
|---|---|---|
| "What happened in the markets today?" | ✓ search "news" | search "新闻" |
| "北京明天天气" | ✓ search "weather" | search "天气" |
| "Latest BTC price" | ✓ search "crypto" | search "币价" |
| "List MCP servers about travel" | ✓ search "mcp travel" | search "mcp" + filter |
Tool Details
python bin/uno.py tool get <tool_slug>
# e.g. python bin/uno.py tool get amap-maps.maps_weather
Call a Tool
Step 1 — always preview first with --dry-run (zero network, zero credential read, zero credits):
python bin/uno.py call --dry-run weather-free.weather_now --args '{"city":"Beijing"}'
Response:
{
"success": true,
"dry_run": true,
"preview": {"tool": "weather-free.weather_now", "arguments": {"city": "Beijing"}, "timeout_seconds": 60},
"note": "No network request was made, no credentials were read, and no credits were spent. Re-run without --dry-run to actually invoke the tool."
}
Show this JSON to the user and wait for explicit approval.
Step 2 — after the user approves, re-run without --dry-run:
python bin/uno.py call weather-free.weather_now --args '{"city":"Beijing"}'
Response:
{"success": true, "data": {...}, "meta": {"latency_ms": 234, "credits_used": 1.0}}
Rate a Tool
python bin/uno.py rate <tool_slug> <0-5> [--comment "great tool"]
Browse Servers
python bin/uno.py servers [--query "weather"] [--category search] [--limit 50]
Disconnect Third-party Authorization
python bin/uno.py disconnect <server_slug>
# e.g. python bin/uno.py disconnect weather-free
Revokes the stored OAuth token or API key for that one server. After disconnect, the next call to the same server will return auth_required. Other servers are unaffected. The user can also run python bin/uno.py logout to wipe the entire local credential file in one step.
API Key Management
python bin/uno.py keys list # list active API keys
python bin/uno.py keys create # create a new API key
python bin/uno.py keys delete <key_id> # delete an API key
Tool Categories
The catalogue is grouped into 13 top-level categories. The table below lists the kinds of capability each category covers; concrete provider/server names are resolved at search time, so the agent should still search to find the most relevant server for a given user request.
| Category | Description |
|---|---|
search | Web search, crawling, and information retrieval |
dev | Developer tooling (code-hosting lookups, SQL consoles, docs, error tracking) |
social | Public-feed / community platforms |
data | Data & analytics (knowledge graphs, computation, weather, public datasets) |
creative | Generative content (image, video, music, slide decks) |
finance | Market data (quotes, fundamentals, crypto) |
lifestyle | Location / transit / delivery tracking |
productivity | Office suites, notes, calendars, task boards |
media | A/V processing (TTS, transcription, captioning) |
enterprise | Business-registry and regulatory look-ups |
ecommerce | Shopping & booking helpers |
health | Health & wellness look-ups |
other | Mail, encyclopedia, academic look-ups, misc |
Agent Workflow
- Check credentials — run
whoamifirst; only login if credentials are missing/expired (see Step 0 above) - Search first — never guess tool slugs or parameters
- Read
input_schemafrom search results to construct correct arguments - Dry-run before real call — always run
call --dry-runfirst and show the preview JSON (tool + arguments) to the user; only proceed to a realcallafter explicit user approval - Search by capability ("weather", "search", "translate"), not user intent
- Use
--compactto reduce output size (fewer tokens) - If
descis truncated (ends with…), runtool get <slug>for full description - Check credits with
whoamibefore heavy usage — free plan has 500 daily credits - Handle errors:
auth_requiredwithauth_type: "api_key"→ tell user to provide an API Key (showget_key_urlandfieldsfrom response)auth_requiredwithauth_url→ showauth_urlto user to open in browser for OAuth authorization; after they complete, retry the same calltool_not_found→ search again with different keywordsinsufficient_credits→ inform user, show recharge page: https://agentools.uno/pricing- Connection errors (timeout, cancelled) → retry once, then inform user
- Rate tools after successful calls to improve search quality
- When multiple servers offer the same capability (e.g. two weather providers or two market-data providers), prefer the one with higher
calls_7dorratingin stats - Never execute destructive actions silently. If a tool's
input_schemadescribes a write / send / purchase-class action, the agent must summarize the intended action in natural language and get explicit user confirmation before calling
Output Format
- Call success:
{"success": true, "data": {...}, "meta": {"latency_ms": N, "credits_used": N}} - Other success:
{"success": true, "data": {...}} - Error:
{"error": "description", "hint": "...", ...}, non-zero exit code
Detailed Help
python bin/uno.py --help
python bin/uno.py search --help
python bin/uno.py call --help
API Base URL
Prefer https://agentools.uno. The CLI default https://clawdtools.uno still serves /v1 and /mcp. Override with --base-url or env var UNO_API_URL. Do not use https://clawtools.uno (typo host; redirects drop Authorization).
Top skills in this category
Shop
@shopifyUltimate personal shopping assistant: find, compare, buy, gift, and reorder products across the Shop catalog containing millions of stores. Tracks orders and...
ClawQuest: Agent Mine - OpenClaw Managed Mining
@zhzai30The managed automated mining server interface supports OpenClaw session mode and incremental event retrieval, enabling mining startup, status query, settlement, and stamina management.
Fulcra Morning Briefing
@arc-claw-botCompose a personalized morning briefing using the latest fulcra-context skill for sleep, biometrics, calendar, activity, and weather context. Adapts tone and...
Personal Finance Tracker
@aka-anoopManage personal finances, track spending by category, set budgets, and receive reminders for EMIs and one-time annual expenses. Use for logging expenses, checking budget status, or setting up financial reminders.
AgentGuard
@0xbeekeeperGoPlus AgentGuard — AI agent security guard. Run /agentguard checkup for a full security health check, scans all installed skills, checks credentials, permis...