# Uni-CLI Full Documentation This file is generated from the same VitePress site map as the public docs. ## Snapshot - Sites: 317 - Commands: 1772 - Adapters: 1222 - Pipeline steps: 103 --- # Page: Overview Canonical: https://olo-dot-io.github.io/Uni-CLI/ Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/index.md # Overview - Canonical: https://olo-dot-io.github.io/Uni-CLI/ - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/index.md - Section: Start ## Universal computer-control platform for agents Uni-CLI turns websites, logged-in browsers, desktop apps, local tools, files, MCP servers, accessibility trees, screenshots, and system capabilities into searchable, governed, observable, repairable operations. Agents use one path to select an action substrate by intent, inspect risk, execute with policy, return evidence, and repair or reroute the failed source path. ## Control Surface - Intent search - Policy-gated execution - AgentEnvelope v2 - MCP + ACP - Desktop AX - Visual fallback - Adapter self-repair ## First Command ```bash npm install -g @zenalexa/unicli unicli do "find the Hacker News frontpage" unicli extract https://example.com --max-chars 1200 unicli compute snapshot --app Calculator --format compact unicli mcp serve --transport streamable --port 19826 ``` ## Positioning Agent execution does not need a longer resident tool list or another website wrapper. It needs a universal hand for controlling the whole computer. Operation search handles discovery. Operation policy exposes permissions and risk. The control kernel chooses the substrate. The v2 AgentEnvelope stabilizes output. Run evidence supports review. The delivery/repair loop points failures to source paths, alternatives, and verification commands. - **Intent.** Bilingual BM25 search turns a natural-language task into a site, operation, arguments, auth posture, and risk fields. - **Substrate.** HTTP, cookies, browser CDP, macOS AX, subprocess, service, protocol, and visual fallback share one control kernel. - **Evidence.** Markdown is the agent-friendly default; JSON, YAML, CSV, and compact formats serve programs. - **Repair or reroute.** Structured errors include source path, step or boundary, retryability, suggestion, and alternatives. ## Common Tasks - `unicli search` and `unicli do` read the local operation catalog first, then execution can inspect operation, args, auth, risk, and output fields. - When a page, API, app, or local boundary changes, the error envelope names the source path and failing step or boundary. - Web APIs, browser automation, macOS, desktop apps, external CLIs, files, MCP, ACP, HTTP API, and agent backend routes share the same operation contract and receipt. ## Coverage - Sites and tools: 317 - Operations: 1772 - Pipeline steps: 103 - Tests: 9183 These numbers come from the current generated repo artifacts: operations, adapters, pipeline steps, tests, and substrates are counted by the build. ## Entrypoints - [First Run](/guide/getting-started): install, search, execute, authenticate, choose output formats, and read exit codes. - [Operation Catalog](/reference/sites): browse by site, substrate, auth strategy, and examples. - [Adapters](/guide/adapters): YAML adapters, pipeline steps, self-repair, and verification. - [Integrations](/guide/integrations): native CLI, MCP, ACP, and output modes for agent runtimes. ## Current Version Latest: v0.225.2 · Apollo · Gordon. ## Agent Index - [/llms.txt](/llms.txt) - [/llms-full.txt](/llms-full.txt) --- # Page: First Run Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/getting-started Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/getting-started.md # First Run - Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/getting-started - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/getting-started.md - Section: Start - Parent: Start (/) Uni-CLI turns websites, logged-in browsers, desktop apps, services, local tools, files, protocols, external CLIs, operating-system capabilities, and visual evidence into governed operations agents can search, run, record, and repair. An operation is a stable contract for controlling real software. It keeps arguments, auth posture, action substrate, output shape, permission profile, evidence, and error handling in one place. When an external page, app, API, or local boundary changes, the failure points back to a repairable source path and step. ## Install ```bash npm install -g @zenalexa/unicli unicli --version ``` Requires Node.js 22.19 or later. Every command follows the same shape: ```bash unicli SITE COMMAND [args] [-f json|md|yaml|csv|compact] ``` Markdown is the default output format. Use `-f json` when a script or other machine-oriented consumer needs JSON. ## Understand The Flow The common path follows the computer-control loop: 1. **Intent**: `unicli search` finds candidate operations from natural language without touching the external surface. 2. **Select**: the operation contract chooses the smallest substrate that can act: API, browser, desktop, subprocess, protocol, or visual fallback. 3. **Govern and act**: `unicli SITE COMMAND` runs the selected operation with inspectable arguments, auth boundaries, and permission policy. 4. **Observe**: every result returns a v2 `AgentEnvelope` with data, context, retryability, timing, and evidence. 5. **Record**: `--record` or `UNICLI_RECORD_RUN=1` can write append-only run traces under `~/.unicli/runs` for review and debugging. 6. **Repair or reroute**: structured failures include the source path, failing step or boundary, suggestion, retryability, and alternatives. Browser automation, CDP, accessibility trees, subprocesses, service APIs, MCP, ACP, and Visual are action substrates. The stable layer is the operation contract, control kernel, evidence envelope, and delivery/repair loop. ## Find A Command ```bash unicli search "hacker news frontpage" unicli search "github trending" unicli list --site hackernews ``` Search narrows the candidate set. Before execution, the agent can still inspect the command name, arguments, auth requirements, and surface type. That keeps "found a possible operation" separate from "performed the operation." ## Run A Command Run the selected command: ```bash unicli hackernews top --limit 5 ``` The default Markdown output contains data, context, and suggested next actions. It is meant to stay readable in terminals, chat transcripts, and agent logs. Use JSON when a script needs it: ```bash unicli hackernews top --limit 5 -f json | jq '.[0]' ``` Supported formats and automatic selection: ```bash unicli hackernews top -f md unicli hackernews top -f json unicli hackernews top -f yaml unicli hackernews top -f csv unicli hackernews top -f compact ``` Priority is `-f` flag, then `UNICLI_OUTPUT`, then agent/non-TTY detection, then Markdown. Agent UA variables include `CLAUDE_CODE`, `CODEX_CLI`, `OPENCODE`, `HERMES_AGENT`, and `UNICLI_AGENT`. ## Authentication Some adapters need local cookies: ```bash unicli auth setup bilibili unicli auth check bilibili unicli bilibili feed ``` Cookies live at `~/.unicli/cookies/SITE.json`. Auth failures return exit code `77` and a structured error with the next command to run. ## Repair A Broken Command When a command fails, read the structured error. It includes the adapter path and pipeline step that need attention. ```bash unicli repair SITE COMMAND ``` Typical loop: ```text 1. Read error.adapter_path and error.step. 2. Patch the YAML adapter. 3. Save a local override under ~/.unicli/adapters/SITE/COMMAND.yaml. 4. Re-run unicli repair SITE COMMAND. ``` The goal is not to retry until it works. The goal is to make the command match its public output shape again. YAML adapters are usually short enough for agents to read, patch, diff, and verify; use TypeScript adapters only when the runtime logic cannot stay declarative. ## Browser Automation Browser adapters use Chrome/CDP when HTTP is not enough. ```bash unicli operate goto "https://example.com" unicli operate snapshot unicli operate click --ref 42 unicli operate type --ref 7 --text "hello" unicli operate screenshot --path ./page.png ``` Browser actions can attach before/after evidence, stale-ref detail, movement dimensions, watchdog results, session lease metadata, tab target identity, cookie posture, and render-aware reads when a command needs reviewable proof. When score thresholds are set, replay and compare output a `gate` object with the thresholds, actual scores, and failed gates. The score block also lists failed or unknown behavior and context check names. Evidence coverage is context too: missing screenshots, operator logs, or result envelopes show up as evidence check names. `unicli runs list` also shows `evidence_count` and `evidence_by_type`, so an agent can pick runs with reviewable proof before opening the trace. ```bash unicli browser evidence --render-aware --expect-domain example.com unicli browser extract --render-aware --expect-domain example.com --no-screenshot unicli runs list unicli runs show unicli runs probe unicli runs replay --permission-profile confirm --yes --min-score 1 --min-context-score 1 --min-overall-score 1 unicli runs compare --min-score 1 --min-context-score 1 --min-overall-score 1 unicli --permission-profile locked --yes --remember-approval word set-font "Inter" unicli approvals list unicli approvals revoke ``` Remembered approvals are bound to the command capability and stable resource metadata, such as domain, app, account surface, and path argument slots. Runtime argument values stay out of the approval store. Use local deny rules for scopes that a machine must block: ```json { "schema_version": "1", "rules": [ { "id": "deny-public-posting", "decision": "deny", "match": { "effect": "publish_content", "resources": { "domains": ["x.com", "twitter.com"] } }, "reason": "Publishing is disabled on this machine" } ] } ``` Save the file as `~/.unicli/permission-rules.json`, or point `UNICLI_PERMISSION_RULES_PATH` at it. The same rules run again inside the pipeline for runtime resources. A denied domain stops `fetch`, `fetch_text`, `download`, and browser `navigate` before the request is sent. A denied path stops downloads and command output files before the directory or file is created. A denied executable stops `exec` before the subprocess starts. ## Protocol Servers MCP: ```bash npx @zenalexa/unicli mcp serve npx @zenalexa/unicli mcp serve --transport streamable --port 19826 npx @zenalexa/unicli mcp serve --transport streamable --port 19826 --auth ``` `--transport sse` still works as a legacy alias for Streamable, but new deployments should use `--transport streamable`. ACP: ```bash unicli acp ``` ACP is an editor compatibility gateway. For coding-agent runtime routing: ```bash unicli agents matrix unicli agents recommend codex unicli agents generate --for codex ``` ## Exit Codes | Code | Meaning | Agent action | | ---- | ------------------- | ---------------------------------------- | | 0 | Success | Use the data | | 66 | Empty result | Try different parameters | | 69 | Service unavailable | Retry later | | 75 | Temporary failure | Retry with backoff | | 77 | Auth required | Run `unicli auth setup SITE` | | 78 | Config error | Read the error envelope and adapter YAML | ## Next Steps - [Adapters](/guide/adapters) - [Integrations](/guide/integrations) - [Self-Repair](/guide/self-repair) - [Pipeline Steps](/reference/pipeline) - [Exit Codes](/reference/exit-codes) --- # Page: How It Works Canonical: https://olo-dot-io.github.io/Uni-CLI/how-it-works Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/how-it-works.md # How It Works - Canonical: https://olo-dot-io.github.io/Uni-CLI/how-it-works - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/how-it-works.md - Section: Start - Parent: Start (/) Uni-CLI is the universal computer-control platform for agents. It turns websites, logged-in browsers, desktop apps, local tools, files, operating-system capabilities, MCP servers, external CLIs, accessibility trees, screenshots, and app-specific wrappers into one governed operation layer. This page walks through the control loop: how intent becomes an operation contract, how Uni-CLI chooses an action substrate, how the v2 AgentEnvelope returns evidence, and how delivery/repair keeps the path alive when real software changes. ## The computer-control contract Every Uni-CLI operation runs through the same product loop. Agents can stop at any phase and reason about the result. 1. **Intent.** `unicli search ""` and `unicli do ""` map a task into candidate operations with args, auth posture, examples, and risk signals. 2. **Select.** The operation contract chooses the smallest boundary that can act: API, browser, desktop accessibility, subprocess, protocol, visual fallback, or app wrapper. 3. **Govern.** Permission profiles, deny rules, capability scope, and local policy gate risky effects before requests, writes, process spawns, or UI actions. 4. **Act.** The shared control kernel invokes the selected substrate instead of letting CLI, MCP, ACP, or docs define behavior separately. 5. **Observe.** AgentEnvelope v2 returns data, context, retryability, timing, and evidence hooks in the same shape on success and failure. 6. **Diagnose.** Delivery assessment classifies failure as auth, policy, missing context, upstream drift, environment trouble, or adapter defect. 7. **Repair or reroute.** The next experiment is bounded by source path, alternatives, evidence, and verification command. 8. **Deliver.** Evidence gates decide whether the objective is satisfied, still active, blocked, or exhausted. 9. **Expose.** The same operation can be reused from native CLI, JSON stream, MCP, ACP, HTTP, docs, skills, CI, and scripts. This contract holds across all action substrates. Adapter type is an implementation detail below the product boundary. ## Substrates, not identities Browser automation, computer-use sandboxes, natural-language local execution, MCP servers, and per-site wrappers are useful, but they are not Uni-CLI's category. They are concrete technical boundaries that Uni-CLI can use or expose. | Substrate | What it contributes | What Uni-CLI keeps above it | | ----------------- | ----------------------------------------------------------------- | ----------------------------------------------------------- | | Web/API | typed fetch, cookie/header auth, downloads, extraction | operation contracts, policy, evidence, repair | | Browser | CDP control, DOM/accessibility refs, screenshots, network capture | selection, receipts, delivery, reroute | | Desktop/OS | installed apps, accessibility trees, screenshots, local state | governed actions, post-state evidence, platform diagnostics | | Local tools/files | subprocesses, PDFs, media tools, developer CLIs | typed args, output envelopes, retryability | | Protocols | MCP, ACP, Streamable HTTP, JSON streams | shared semantics instead of wrapper-specific behavior | | Visual fallback | last-mile screen interaction | truthfulness gate: can see, act, and verify | ## Domain-aware discovery The catalog search layer is not a plain site-name lookup. It combines bilingual BM25 with command metadata, aliases, and domain vocabulary so an agent can search for an entity first and only then pick the right surface. For example, a query such as `Sparkle Honkai Star Rail character` can route toward character/wiki/anime sources, while `blue_archive rating:safe` can route toward booru tag search. Japanese names, romaji variants, Chinese names, and English titles are represented as aliases on the relevant adapter surfaces rather than hard-coded as one-off site shortcuts. The same rule keeps broad searches honest. Domain boosts only apply when the query uses explicit ACG, paper, wiki, tag, game, anime, manga, or visual-novel vocabulary; generic queries still rank the normal web, developer, finance, or app commands by their own evidence. ## Internal authoring format: YAML adapters YAML adapters are the default way to author reusable operation contracts. They are not the platform identity; they are the cheap, inspectable format that lets agents read, patch, and verify many substrate paths. Here's a complete adapter for a public RSS feed: ```yaml site: techcrunch name: latest type: web-api strategy: public pipeline: - fetch_text: url: https://techcrunch.com/feed/ - parse_rss: {} - limit: 10 - map: title: "${{ item.title }}" url: "${{ item.link }}" published: "${{ item.published }}" columns: [title, published, url] ``` Five fields define the authoring unit: `site` (the integration name), `name` (the command), `type` (which substrate: web-api, browser, desktop, bridge, service), `strategy` (auth path), and `pipeline` (the steps that produce the result). An adapter without imports, classes, or compile steps lets an agent read it, patch a selector, and verify the fix in seconds. ## Internal pipeline registry Every adapter runs through the same 103-step pipeline registry. Steps are grouped by purpose: API fetch, transform, browser, desktop, media, control flow, and assertion. Each step is deterministic — same inputs produce same outputs — so adapters compose into reliable execution graphs. | Group | Examples | Purpose | | --------- | ------------------------------------------------------------------- | ---------------------------------------- | | API | `fetch`, `fetch_text`, `parse_rss`, `html_to_md` | HTTP retrieval and structured extraction | | Transform | `select`, `map`, `filter`, `sort`, `limit` | Reshape JSON between steps | | Browser | `navigate`, `evaluate`, `click`, `type`, `wait`, `intercept`, `tap` | CDP control over Chrome | | Desktop | `exec`, `write_temp` | Subprocess control | | Media | `download`, `websocket` | File and stream capture | | Control | `set`, `if`, `each`, `parallel`, `rate_limit`, `assert`, `retry` | Composition primitives | | Output | `extract`, columns | Final shape for the agent | The pipeline runs top to bottom with a shared context object. Each step reads `ctx.data` and writes back. Templates (`${{ item.field }}`) interpolate from prior step outputs. ## The strategy cascade Authentication is the messiest part of touching the modern web. Every adapter declares one of five strategies, and Uni-CLI auto-probes the cheapest one that returns valid data. | Strategy | Auth source | Typical cost | | ----------- | ---------------------------------------------- | ------------------------------------------ | | `public` | None | Direct fetch | | `cookie` | Cookie file at `~/.unicli/cookies/.json` | Inject into headers | | `header` | Cookie + auto-extracted CSRF | Read CSRF from cookie, inject into request | | `intercept` | Live browser session | Navigate page, capture XHR/fetch responses | | `ui` | Live browser session | Click, type, snapshot | The cascade order is `public → cookie → header → intercept → ui`. On the first run for a site, Uni-CLI tries each strategy until one returns parseable data, then caches the result. Subsequent calls skip the probe. ## The v2 AgentEnvelope Every command returns a v2 AgentEnvelope — the same shape on success or failure. Agents parse one schema across 1772 commands. ```json { "ok": true, "version": "v2", "data": [ /* the result */ ], "meta": { "site": "reddit", "command": "search", "strategy": "public", "duration_ms": 412, "adapter_path": "/Users/me/.unicli/adapters/reddit/search.yaml" }, "exit_code": 0 } ``` On failure, `ok` becomes `false`, `data` becomes `null`, and `error` populates with structured fields. Exit codes follow `sysexits.h` (0=ok, 1=error, 2=usage, 66=empty, 69=unavailable, 75=temp, 77=auth, 78=config) so shell pipelines can route by failure class. ## The self-repair loop This is the design choice that makes the rest of the architecture worth building. When a site changes shape, the error envelope gives the agent a bounded fix: ```json { "ok": false, "version": "v2", "data": null, "error": { "adapter_path": "/Users/me/.unicli/adapters/twitter/search.yaml", "step": "fetch", "action": "request returned 404", "suggestion": "endpoint may have moved; check x.com/i/api/graphql/* in DevTools Network tab", "retryable": false, "alternatives": ["unicli twitter timeline @user", "unicli twitter trending"] }, "exit_code": 69 } ``` The agent has everything it needs: the file to edit, the failing step, a one-line hypothesis, and at least one alternative path. After the YAML edit, `unicli repair twitter search` re-runs the failing step against a known-good fixture. The patch persists in `~/.unicli/adapters/`, so `npm update` cannot wipe it. A bug that would have cost 30 minutes of human debugging closes in 30 seconds of agent runtime. That two-orders-of-magnitude difference is the entire economic argument for adapters as YAML. ## Why CLI is the first runtime surface CLI is the cheapest primary exposure surface for many agent runs; it is not the product boundary. Three forces make it the right first runtime surface. **Token economics.** [docs/BENCHMARK.md](/BENCHMARK) measures `--limit 5` list-style adapters at a 364-423 token total call budget (median 412). An MCP server keeps its tool list resident in the agent's context window — typically 1,500-3,000 tokens per server — even when the agent does not invoke it. The CLI pays for what it uses; the MCP server pays to be available. **Determinism.** A CLI call is a pure function of arguments and time. Same arguments, same minute, same output. MCP roundtrips add a stateful server, a transport, and a protocol layer that can drift. For agent automation, fewer moving parts reduces failure modes. **Composability.** Shell pipelines are the lingua franca of automation. `unicli reddit hot r/programming -n 50 -f json | jq '.data[].title' | unicli huggingface summarize -` works the day Uni-CLI installs. Same composition with MCP requires a glue layer. ## When MCP still wins CLI is not a universal replacement. MCP is the better surface for: - **Stateful auth** — long-lived OAuth flows, refreshing tokens, session-bound resources. - **Real-time** — WebSocket-driven chat platforms, server-sent events, streaming completions. - **Single-platform deep integration** — a vendor-built MCP server for a vertical platform usually outperforms a third-party CLI adapter for that platform. Most production agent stacks need both. Uni-CLI ships an MCP gateway (`unicli mcp serve`) that wraps the same catalog, so a runtime that only speaks MCP gets the same execution surface without a second integration. ## The operation catalog as a first-class artifact Search beats discovery-by-prompt. `unicli search "find AI agent discussions on reddit"` returns a ranked list of matching commands with arguments, auth, and example output. The agent picks one, runs it, and never has to enumerate the catalog. The token budget stays low because the runtime loads the catalog index, not the catalog body. ## Putting it together A typical agent run looks like this: ```bash # 1. Discover $ unicli search "summarize today's Hacker News top stories" → suggested: unicli hackernews top -n 10 → next: unicli huggingface summarize - # 2. Execute and pipe $ unicli hackernews top -n 10 -f json \ | jq -r '.data[] | .title + "\n" + .url' \ | unicli huggingface summarize - -f md # 3. On failure, the error envelope names the adapter to fix # 4. The agent edits the YAML and re-verifies with `unicli repair` ``` That is the simplest exposure path. The same operation contract can also run through MCP, ACP, HTTP, skills, or CI without changing semantics. One command shape across 317 sites and 1772 commands. One error envelope across every failure. One self-repair path across every adapter. ## Further reading - [Adapter Format](/ADAPTER-FORMAT) — full reference for the YAML adapter schema. - [Pipeline Reference](/reference/pipeline) — every pipeline step and its parameters. - [Self-Repair Guide](/guide/self-repair) — the repair loop in detail. - [FAQ](/faq) — quick answers to the most common questions. - [Glossary](/glossary) — definitions for every term used in this guide. --- # Page: Integrations Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/integrations Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/integrations.md # Integrations - Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/integrations - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/integrations.md - Section: Start - Parent: Start (/) Uni-CLI is designed to be called directly from a shell. Agent clients that need a protocol server can use the same operation contracts over MCP, ACP, or generated platform configuration while keeping behavior identical. ## Choose A Path | Client need | Use | | ----------------------------------- | ------------------------------------------------ | | Any agent can run shell commands | Native `unicli` CLI | | Tool-calling clients that speak MCP | `unicli mcp serve` | | Editor clients that speak ACP | `unicli acp` | | Platform-specific setup | `unicli agents generate` | | Runtime/backend selection | `unicli agents matrix` / `recommend` | | Skill-native adapter discovery | `unicli skills export` / `unicli skills publish` | Prefer the native CLI when the agent has shell access. It keeps discovery lazy, outputs compact, and preserves Unix composition. ## Native CLI ```bash unicli search "hacker news frontpage" unicli hackernews top --limit 5 -f json ``` Add this short contract to `AGENTS.md`, `CLAUDE.md`, or the equivalent agent context file: ```markdown Use `unicli search "intent"` before choosing a command. Run commands as `unicli SITE COMMAND [args]`. Prefer `-f json` for scripts and structured Markdown for human-readable agent output. ``` For higher-risk runs, inspect before execution: ```bash unicli describe SITE COMMAND unicli SITE COMMAND --dry-run unicli SITE COMMAND --record ``` ## MCP Start a stdio server: ```bash npx @zenalexa/unicli mcp serve ``` Start a Streamable HTTP server: ```bash npx @zenalexa/unicli mcp serve --transport streamable --port 19826 ``` Legacy SSE compatibility: ```bash npx @zenalexa/unicli mcp serve --transport sse --port 19826 ``` `sse` is a deprecated alias for the Streamable transport. Use `--transport streamable` for new setups. Remote deployments can enable OAuth 2.1 PKCE: ```bash npx @zenalexa/unicli mcp serve --transport streamable --port 19826 --auth ``` Default MCP tools: | Tool | Purpose | | ---------------- | ------------------------------------------- | | `unicli_search` | Search commands by natural-language intent. | | `unicli_run` | Run a selected site command. | | `unicli_list` | List sites and commands. | | `unicli_explore` | Inspect a page before authoring an adapter. | `mcp serve` and `acp` keep raw stdio protocol behavior. Normal command surfaces return the v2 `AgentEnvelope`. For local computer control, start the dedicated profile: ```bash npx @zenalexa/unicli mcp serve --profile computer-use ``` It exposes the `computer-use.*` tool set backed by `unicli compute`. Client snippets are available for [Claude Desktop](/mcp/clients/claude-desktop.md), [Claude Code](/mcp/clients/claude-code.md), [Codex](/mcp/clients/codex.md), [Cursor](/mcp/clients/cursor.md), and [Gemini CLI](/mcp/clients/gemini-cli.md). Claude-style stdio config: ```json { "mcpServers": { "unicli": { "command": "npx", "args": ["@zenalexa/unicli", "mcp", "serve"] } } } ``` Codex CLI config: ```toml [mcp_servers.unicli] command = "npx" args = ["@zenalexa/unicli", "mcp", "serve"] ``` ## ACP ACP is an editor compatibility path for clients such as avante.nvim and Zed. MCP fits structured tool calls. ACP fits prompt/session frames. ```bash unicli acp ``` Minimal avante.nvim provider: ```lua require("avante").setup({ providers = { { name = "unicli", command = "unicli", args = { "acp" }, type = "acp", }, }, }) ``` ACP prompts should include an explicit command: ```text Show the top 10 HN posts: unicli hackernews top --limit 10 ``` ## Agent Platform Recipes Generate config where possible instead of hand-writing it: ```bash unicli agents matrix unicli agents recommend codex unicli agents generate --for claude unicli agents generate --for codex unicli agents generate --for opencode ``` Backend recommendations model native CLI, JSON stream, MCP, ACP, HTTP API, OpenAI-compatible routes, bridge CLIs, and Visual candidates explicitly. ## Skills Export adapter commands as `SKILL.md` files when the agent runtime has a local skills directory: ```bash unicli skills export unicli skills publish --to ~/.cursor/skills/uni-cli/ unicli skills catalog --out /tmp/unicli-skills.json ``` The generated files include command name, when-to-use text, auth notes, and a call example. They complement runtime discovery for agents that load skills at startup. Manual examples: ```bash # Claude Code MCP claude mcp add unicli -- npx @zenalexa/unicli mcp serve ``` ```jsonc // OpenCode { "mcp": { "unicli": { "type": "local", "command": ["npx", "-y", "@zenalexa/unicli", "mcp", "serve"], "enabled": true, }, }, } ``` ```yaml # Hermes Agent mcp_servers: unicli: command: "npx" args: ["-y", "@zenalexa/unicli", "mcp", "serve"] ``` ## Auth All integration paths use the same local credentials as the CLI: ```bash unicli auth setup SITE unicli auth check SITE ``` Cookie path: ```text ~/.unicli/cookies/SITE.json ``` ## Verify ```bash unicli list unicli search "hacker news frontpage" unicli hackernews top --limit 5 ``` --- # Page: Recipes Canonical: https://olo-dot-io.github.io/Uni-CLI/RECIPES Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/RECIPES.md # Recipes - Canonical: https://olo-dot-io.github.io/Uni-CLI/RECIPES - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/RECIPES.md - Section: Start - Parent: Start (/) Worked examples showing how agents chain Uni-CLI commands to solve real end-user tasks. All examples assume: - Uni-CLI is on `$PATH` (`npm install -g @zenalexa/unicli`) - Commands that feed `jq` or shell scripts pass `-f json` explicitly ## 1. Triage your morning inbox — list iMessages + Notes in one JSON blob **Use-case.** An agent needs a single structured view of "what the user might be behind on" across iMessage and Apple Notes before drafting a stand-up update. ### Command sequence ```bash # Recent messages from the last hour (take the top 10 for brevity) unicli imessage recent --limit 10 -f json > /tmp/recent-msgs.json # Your "Work" notes folder (titles only — body fetch is a separate call) unicli apple-notes list --folder "Work" -f json > /tmp/work-notes.json # Merge client-side (bash): jq -n --slurpfile m /tmp/recent-msgs.json \ --slurpfile n /tmp/work-notes.json \ '{messages: $m[0], notes: $n[0]}' ``` ### Expected output ```json { "messages": [ { "ts": "2026-04-15 08:42:11", "is_from_me": 0, "handle_id": "+14155550123", "text": "Standup at 10?" } ], "notes": [ { "stdout": "Roadmap Q2\nFollow-ups from design review\nOKR draft" } ] } ``` ### Troubleshooting - `imessage recent` returns `[]` on non-macOS hosts. The adapter gates on `uname = Darwin` and exits cleanly. - If you see `OSError: Operation not permitted`, grant your terminal Full Disk Access under **System Settings → Privacy & Security → Full Disk Access**. - `apple-notes list` returns an empty `stdout` when the folder does not exist. AppleScript does not distinguish "empty folder" from "missing folder" — confirm with `unicli apple-notes list` (default "Notes" folder) first. ## 2. Auto-file a Linear bug from a user iMessage **Use-case.** The agent scans recent iMessage for the phrase "bug:" and opens a Linear issue so nothing slips through. ### Command sequence ```bash # Step 1 — search iMessage for the phrase unicli imessage search "bug:" --limit 5 -f json > /tmp/bug-msgs.json # Step 2 — extract the first message body (agent logic in jq) TITLE=$(jq -r '.[0].text' /tmp/bug-msgs.json | head -c 120) # Step 3 — file the Linear issue export LINEAR_API_KEY=lin_api_xxxxxxxxxxxx unicli linear issue-create "$TITLE" \ --team ENG \ --description "Auto-filed from iMessage on $(date -Iseconds)" \ -f json ``` ### Expected output ```json [ { "identifier": "ENG-742", "title": "bug: settings page 500s when language=zh-hk", "url": "https://linear.app/my-team/issue/ENG-742" } ] ``` ### Troubleshooting - If `LINEAR_API_KEY` is unset, the Linear API returns `401 Authentication required` — the adapter surfaces this as a structured error with `exit_code: 77` (AUTH_REQUIRED). - Omitting `--team` works if your workspace has a default team. Otherwise Linear returns a GraphQL error telling you which field is missing; Uni-CLI emits that verbatim in `stderr`. - Linear's Authorization header is the API key itself, **not** `Bearer KEY`. If you see `403 Forbidden`, double-check you didn't prepend `Bearer`. ## 3. Close a Linear issue from a note you just wrote **Use-case.** You finish a task, write a "done: ENG-123" note, and want the Linear state flipped to Done without leaving the terminal. ### Command sequence ```bash # Step 1 — search notes for the completion marker unicli apple-notes search "done: ENG-" -f json > /tmp/done-notes.json # Step 2 — extract the Linear identifier from the first match (agent # logic). Here we assume the note body is a single line "done: ENG-123". ID=$(jq -r '.[0].stdout' /tmp/done-notes.json \ | grep -oE 'ENG-[0-9]+' | head -1) # Step 3 — flip the state export LINEAR_API_KEY=lin_api_xxxxxxxxxxxx unicli linear issue-update "$ID" --state "Done" -f json ``` ### Expected output ```json [ { "identifier": "ENG-123", "title": "Ship adapter coverage", "url": "https://linear.app/my-team/issue/ENG-123" } ] ``` ### Troubleshooting - `issue-update` makes three HTTP calls (fetch issue → resolve state → apply update). If any step returns an empty result, the final mutation silently does nothing. Use `-f json` to inspect the intermediate pipeline via `unicli dev` — see `docs/guide/getting-started.md`. - State names are case-sensitive and team-scoped. "Done" in one team might be "Shipped" in another; list states per team with `unicli linear issue-list --state Done --limit 1` to confirm a working name. ## 4. Stand-up digest — what changed since yesterday? **Use-case.** Generate a one-page summary for your daily stand-up combining: yesterday's Linear Done issues + any iMessage threads mentioning them. ### Command sequence ```bash export LINEAR_API_KEY=lin_api_xxxxxxxxxxxx # Step 1 — Linear issues in "Done" state, top 10 unicli linear issue-list --state "Done" --limit 10 -f json > /tmp/done-issues.json # Step 2 — for each issue, search iMessage for its identifier for ID in $(jq -r '.[].id' /tmp/done-issues.json); do echo "=== $ID ===" unicli imessage search "$ID" --limit 3 -f json done > /tmp/digest.json # Step 3 — hand the blob to your LLM of choice, which can now cite # specific messages that corroborate each shipped issue. ``` ### Expected output Mixed `=== ENG-42 ===` headers followed by JSON arrays of messages mentioning `ENG-42`. Consumers typically pipe this to an LLM that summarises in 3-5 bullets. ### Troubleshooting - `issue-list` returns only issues you have access to — API key scope matters. A read-only key will not list other users' private projects. - iMessage `search` is `LIKE` over the full `chat.db`. For large databases (>100K messages) a query takes 1-3 seconds. Avoid running it in a tight loop with >50 iterations. ## 5. Paper workflow — search, download, and read a PDF locally **Use-case.** An agent needs to collect a paper, keep the PDF on disk, and read only the relevant pages before summarizing or comparing it. ### Command sequence ```bash # Step 1 — search arXiv for a topic unicli arxiv search "retrieval augmented generation" --limit 5 -f json > /tmp/arxiv.json # Step 2 — choose an ID and download the PDF locally ID=$(jq -r '.[0].id' /tmp/arxiv.json) unicli arxiv download "$ID" --output ./papers -f json # Step 3 — read the opening pages from the local PDF unicli pdf read "./papers/$ID.pdf" --first_page 1 --last_page 3 -f json ``` ### Troubleshooting - If the downloaded filename differs from `.pdf`, inspect the `arxiv download` JSON output and pass that path to `pdf read`. - `pdf read` works on local files. If the remote site only exposes a landing page, download the actual PDF first instead of passing the web URL to the reader. ## 6. ACG character discovery — from intent to wiki and catalog sources **Use-case.** The user asks for a character such as `Sparkle`, meaning the Honkai: Star Rail character rather than a generic word. The agent should search by entity intent, then verify on structured ACG sources. ### Command sequence ```bash # Step 1 — let the catalog rank likely command surfaces unicli search "Sparkle Honkai Star Rail character" --limit 8 # Step 2 — check a general anime/character index unicli anilist characters "Sparkle" --limit 5 -f json # Step 3 — check a Chinese ACG wiki surface unicli moegirl search "Sparkle Honkai Star Rail" --limit 5 -f json # Step 4 — inspect booru tag vocabulary for image search follow-up unicli danbooru tags sparkle --limit 10 -f json ``` ### Troubleshooting - Use source names or franchise terms (`Honkai Star Rail`, `Star Rail`, `Sparkle character`) when a character name is ambiguous. - Prefer tag commands before post searches on booru sites; they reveal the canonical tag spelling that search commands expect. ## 7. Booru tag workflow — confirm tags, then search posts **Use-case.** The agent needs tagged illustration results and should avoid guessing the exact tag form. ### Command sequence ```bash # Confirm the tag spelling first unicli safebooru tags blue_archive --limit 5 -f json unicli danbooru tags blue_archive --limit 5 -f json # Then search posts with an explicit tag query unicli safebooru search "blue_archive rating:safe" --limit 10 -f json unicli danbooru search "blue_archive rating:safe" --limit 10 -f json # Use detail/download commands only after selecting a concrete post ID unicli danbooru detail 123456 -f json ``` ### Troubleshooting - Safebooru search expects Moebooru-style tag syntax such as `blue_archive rating:safe`; it is not a free-form Japanese sentence search. - Some booru sources use underscores and romanized tags. Let `tags` or `wiki` commands confirm the spelling before fetching posts. ## 8. Visual novel and 2024-2026 media lookup **Use-case.** The user asks for a studio, game, or recent ACG trend such as `Yuzusoft` or a 2024-2026 title. The agent should combine catalog search with source-native filters and sort orders. ### Command sequence ```bash # Discover the best source first unicli search "Yuzusoft visual novel games" --limit 8 # Query visual-novel and anime/game catalogs directly unicli vndb search "Yuzusoft" --limit 10 -f json unicli bangumi game "Gakuen Idolmaster" --year 2024 --sort rank -f json unicli anilist anime "2026" --year 2026 --sort trending --limit 10 -f json # Cross-check wiki-style context when the entity is ambiguous unicli moegirl search "Yuzusoft" --limit 5 -f json ``` ### Troubleshooting - Search with Japanese, romaji, Chinese, and English aliases when a source has localized titles. - Use source-supported sort values. If a command rejects a sort, run `unicli describe -f json` and use the enum in `args_schema`. ## Common flags All current adapters support: | Flag | What it does | | ---------------- | ------------------------------------------------- | | `-f json` | Machine output (auto-on when stdout is not a TTY) | | `-f yaml` / `md` | Human-readable alternatives | | `--limit N` | Caps row count where applicable | Exit codes follow `sysexits.h`: | Code | Meaning | | ---- | ---------------------------------------- | | 0 | Success | | 66 | Empty result (not an error) | | 69 | Service unavailable (non-darwin, no key) | | 77 | Auth required (`LINEAR_API_KEY` unset) | | 78 | Config error (malformed adapter) | See `docs/reference/exit-codes.md` for how agents detect and handle each exit code. --- # Page: FAQ Canonical: https://olo-dot-io.github.io/Uni-CLI/faq Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/faq.md # FAQ - Canonical: https://olo-dot-io.github.io/Uni-CLI/faq - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/faq.md - Section: Start - Parent: Start (/) Quick answers to the questions agents and developers ask most often. Each answer is a standalone summary so AI assistants can quote it directly. ## What is Uni-CLI? Uni-CLI is the universal computer-control platform for agents. It turns websites, logged-in browsers, desktop apps, local tools, files, operating-system capabilities, MCP servers, screenshots, accessibility trees, and app-specific wrappers into governed operations. One path accepts intent, selects an action substrate, executes with policy, returns evidence, diagnoses failure, and repairs or reroutes across 317 sites and tools. ## How is Uni-CLI different from a browser automation library? Browser automation is one action substrate. Uni-CLI sits above it with operation contracts, permission policy, evidence receipts, delivery assessment, and repair/reroute paths. A browser command, desktop action, subprocess bridge, MCP route, or app wrapper should all return the same AgentEnvelope and follow the same control loop. ## How is Uni-CLI different from a computer-use sandbox? A computer-use sandbox gives an agent an environment with screen, mouse, keyboard, and often benchmark hooks. Uni-CLI can use that kind of boundary, but its category is broader: it controls the user's real software environment through the smallest available substrate, from typed APIs and browser CDP to desktop accessibility, subprocesses, files, protocols, and visual fallback. ## Why a CLI instead of an MCP server? A measured Uni-CLI list-style call lands at a 364-423 token total budget (median 412) per [docs/BENCHMARK.md](/BENCHMARK), while an equivalent MCP server keeps its tool list resident — typically 1,500-3,000 tokens per server, even when idle. Uni-CLI publishes both surfaces; the CLI is the cheap, deterministic primary, and MCP wraps it for runtimes that only speak MCP. ## How does self-repair work in Uni-CLI? When an operation fails, Uni-CLI emits a structured error JSON containing the source path, failing step or boundary, action, retryability, alternatives, and a one-line suggestion. An agent can edit the YAML or code at that path, run `unicli repair ` or a bounded delivery verification, and keep the patch in `~/.unicli/adapters/` when the repair is user-local. ## Which AI agent runtimes work with Uni-CLI? Any runtime that can spawn a subprocess can use Uni-CLI directly. Uni-CLI also exposes an MCP server, an ACP gateway, and an `AGENTS.md` discovery surface so agents pick it up without manual configuration. ## How many sites and commands does Uni-CLI ship? v0.225.2 ships a generated operation catalog with 317 sites, 1772 commands, 1222 adapters, 103 pipeline steps, and 9183 tests. The headline is not the count; it is the shared control contract: intent, policy, action substrate, evidence, delivery, repair, and the same AgentEnvelope across web, browser, desktop, local tools, files, and protocols. ## Can Uni-CLI download papers and read local PDFs? Yes. `unicli arxiv download --output ./papers -f json` downloads a paper PDF, and `unicli pdf read ./papers/.pdf --first_page 1 --last_page 3 -f json` extracts local text into the same structured envelope shape as web adapters. Agents can search arXiv, download the PDF, read selected pages, and summarize the result without leaving the CLI contract. ## How should agents search ACG, anime, manga, and booru content? Start with intent search, then narrow by the domain-specific command: `unicli search "Sparkle Honkai Star Rail character"`, `unicli anilist characters "Sparkle" -f json`, `unicli moegirl search "Sparkle Honkai Star Rail" -f json`, or `unicli danbooru tags sparkle -f json`. Booru adapters expose explicit tag workflows, while anime/game/wiki adapters expose entity search, media catalogs, year filters, and popularity/rank/trending sort options where the source supports them. ## Can I add a new site without writing TypeScript? Yes. The preferred contribution format is a short YAML adapter that names the site, command, strategy, and pipeline. YAML is an authoring format below the operation contract, not the product identity. Run `unicli init ` to scaffold one, then `unicli dev ` to hot-reload while iterating. Most adapters ship without a single line of TypeScript. ## Does Uni-CLI handle authenticated sites? Yes. Strategies cascade across `public`, `cookie`, `header` (cookie + CSRF), `intercept` (browser XHR capture), and `ui` (interactive). Cookies live in `~/.unicli/cookies/`, and Uni-CLI auto-probes the cheapest strategy that returns valid data. ## How does Uni-CLI compare to MCP for token cost? [docs/BENCHMARK.md](/BENCHMARK) measures real Uni-CLI call budgets at 364-423 tokens (median 412) for `--limit 5` list-style adapters. An MCP server has to keep its tool list in resident context — usually 1,500-3,000 tokens per server — before any tool is invoked. Uni-CLI emits structured error envelopes so agents avoid retry loops that further inflate context. ## Is Uni-CLI free and open source? Yes. Uni-CLI is Apache-2.0 licensed on GitHub at [olo-dot-io/Uni-CLI](https://github.com/olo-dot-io/Uni-CLI) and on npm as [@zenalexa/unicli](https://www.npmjs.com/package/@zenalexa/unicli). There are no paid features, no gated commands, and no telemetry. YAML adapters and pipeline steps are agent-readable and agent-editable. ## Where can I see all commands? The full operation catalog lives at [/reference/sites](/reference/sites). For agent-readable indexes, fetch [/llms.txt](/llms.txt) for a curated map or [/llms-full.txt](/llms-full.txt) for the concatenated docs. ## How do I report a broken adapter? Open an issue at [github.com/olo-dot-io/Uni-CLI/issues](https://github.com/olo-dot-io/Uni-CLI/issues) with the structured error JSON. The error envelope already includes the adapter path and failing step, so a fix is usually a single YAML edit. --- # Page: Glossary Canonical: https://olo-dot-io.github.io/Uni-CLI/glossary Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/glossary.md # Glossary - Canonical: https://olo-dot-io.github.io/Uni-CLI/glossary - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/glossary.md - Section: Start - Parent: Start (/) Definitions for the terms used across Uni-CLI documentation, source, and YAML adapters. Each entry is a standalone explanation so AI assistants can quote it directly when answering questions about the project. ## Action substrate A concrete technical boundary Uni-CLI can use to make real software act: HTTP, browser CDP, desktop accessibility, subprocess, file operation, protocol server, visual fallback, or app-specific wrapper. Substrates are below the computer-control platform boundary. ## Adapter A YAML or TypeScript file that maps one site or tool to a set of operations. Adapters declare site, command name, type, strategy, arguments, pipeline steps, and column projection. The preferred contribution format is YAML; TypeScript is reserved for adapters that need imperative control flow beyond the shared pipeline registry. ## Adapter type The integration surface an adapter targets. Five types: `web-api` for HTTP APIs, `browser` for full Chrome control via CDP, `desktop` for local subprocesses, `bridge` for passthrough to existing CLIs, and `service` for WebSocket or HTTP services like Ollama, OBS, or ComfyUI. ## AgentEnvelope (v2) The structured response shape returned by every Uni-CLI operation. Contains `ok`, `version`, `data`, `meta`, optional `error`, and `exit_code`. On success `data` carries the result. On failure `data` is null and `error` populates with source path, `step`, `action`, `suggestion`, `retryable`, and `alternatives`. ## AGENTS.md A discovery file that agent runtimes read at startup to learn about available tools. Uni-CLI is registered in `AGENTS.md` so agents pick it up without per-runtime configuration. ## Bilingual BM25 search The operation discovery algorithm Uni-CLI uses to map natural-language intent to a site, operation, and arguments. Indexes adapter metadata in English and Chinese with TF-IDF weighting. Returns ranked candidates for `unicli search ""`. ## Bridge adapter An adapter that wraps an existing CLI (e.g., `gh`, `docker`, `yt-dlp`, `lark-cli`) and exposes its operations through Uni-CLI's catalog. Pure passthrough — Uni-CLI does not re-implement the wrapped CLI, only registers, auto-installs, and aggregates discovery. ## Browser adapter An adapter that drives Chrome via the Chrome DevTools Protocol (CDP) for sites that require interactive sessions, JavaScript execution, or login state. Uses `navigate`, `evaluate`, `click`, `type`, `wait`, `intercept`, `tap`, `snapshot`, and `screenshot` pipeline steps. ## Catalog The local index of all sites, operations, arguments, strategies, and output schemas. Generated at install time and updated when adapters change. Searched via `unicli search` rather than enumerated, so agents pay catalog cost only when they need to discover. ## CDP (Chrome DevTools Protocol) The wire protocol Uni-CLI uses to control a real Chrome instance for browser adapters. Implemented as a raw WebSocket client in `src/browser/cdp-client.ts` with no third-party browser library. Supports the full Page, Network, DOM, and Runtime domains. ## Compute (Visual) The local computer-control and visual fallback adapter family. When structured substrates (web-api, desktop AX, browser CDP, app API, subprocess) cannot reach a target, Compute can drive the screen with screenshots, clicks, typing, and post-action evidence through a unified action verb set. ## Cookie file Per-site authentication state stored at `~/.unicli/cookies/.json`. Read by adapters with `strategy: cookie` or `strategy: header`. Never sent off the local machine. ## Daemon A long-lived browser process Uni-CLI can manage on port 19825. Spawns Chrome with the `--remote-debugging-port` flag, holds session state across CLI calls, and exits on idle timeout. Optional — most adapters work without it. ## Desktop adapter An adapter that shells out to a local binary (e.g., `ffmpeg`, `imagemagick`, `blender`) via the `exec` and `write_temp` pipeline steps. Used for media processing, file conversion, and any CLI tool already on the user's PATH. ## Discovery The phase where an agent maps natural-language intent to concrete operations. Performed by `unicli search ""` against the local operation catalog. Discovery cost is bounded — see [docs/BENCHMARK.md](/BENCHMARK) for measured token budgets. ## Error envelope The `error` field on a v2 AgentEnvelope when `ok` is false. Carries source path or `adapter_path`, `step` or failing boundary, `action` (one-line description), `suggestion` (a hypothesis the agent can test), `retryable` (whether retry would help), and `alternatives` (other operations that might satisfy the intent). ## Exit code A `sysexits.h`-compatible numeric status returned by every Uni-CLI invocation. 0 is success. 1 is generic error. 2 is usage error. 66 is empty result. 69 is service unavailable. 75 is temporary failure. 77 is auth error. 78 is config error. Shell pipelines can route on these classes. ## Header strategy An auth strategy that reads a cookie file and auto-extracts a CSRF token from it, then injects both into request headers. Used by sites that require CSRF on state-changing requests (e.g., Reddit `vote`, Twitter `like`). ## Intercept strategy An auth strategy that navigates a real browser session to the target page and captures the XHR/fetch response that the page itself loaded. Used when a site's API is undocumented or requires session state too complex to replicate manually. ## llms.txt A standardized agent-readable index file at the site root (`/llms.txt` and `/llms-full.txt`). Lists key documentation pages with Markdown companion URLs so AI assistants can fetch and cite docs without rendering HTML. ## MCP (Model Context Protocol) The Anthropic-led protocol for letting AI assistants invoke tools through a stateful server. Uni-CLI ships an optional MCP gateway (`unicli mcp serve`) that exposes the same operation contracts for runtimes that only speak MCP. ## Operation contract The stable product primitive in Uni-CLI. An operation contract describes identity, args, output shape, auth posture, action substrate, effect, risk, capability, source path, and repair path. CLI, MCP, ACP, docs, skills, and generated configs should all project the same contract instead of defining behavior separately. ## Pipeline The ordered list of steps an adapter runs to produce its result. Drawn from the 103-step registry covering API fetch, transform, browser, desktop, media, control flow, and assertion. Steps share a context object — each step reads `ctx.data` and writes back. ## Pipeline step One unit of work in an adapter's pipeline. Examples: `fetch`, `select`, `map`, `filter`, `navigate`, `click`, `intercept`, `if`, `each`, `assert`. Every step is deterministic — same inputs produce same outputs — so adapters compose into reliable execution graphs. ## Public strategy The cheapest auth strategy. Direct fetch with no credentials. Used by sites with public APIs (RSS feeds, search endpoints, public stats). Always tried first by the strategy cascade. ## Repair The stage where a failed operation becomes a bounded source change or reroute. After an error envelope names a failing source path and step or boundary, the agent edits the YAML/code or chooses an alternative, then runs `unicli repair ` or a delivery verification to prove the fix. User-local patches persist in `~/.unicli/adapters/`. ## Self-repair The capability that lets agents fix their own integrations when software drifts. Composed of: structured error envelopes, agent-readable source paths, a repair verification command, alternatives, and a persistent overlay directory. This is one design choice that makes operation-as-YAML economically viable. ## Service adapter An adapter that talks to a long-lived service (Ollama, OBS Studio, ComfyUI) over WebSocket or HTTP with optional API-key auth. Distinct from `web-api` because the connection persists across pipeline steps. ## Site The integration target for an adapter. Typically a website (`reddit`, `twitter`, `bilibili`), but can also be a desktop app (`obsidian`), an external CLI (`gh`), or a local service (`ollama`). ## Snapshot A DOM accessibility tree generated by the `snapshot` pipeline step in browser adapters. Produces interactive ref numbers that subsequent `click`, `type`, and `extract` steps reference. Used by adapters that need stable element targeting across page state changes. ## Strategy The auth path an adapter declares. Five strategies in cascade order: `public`, `cookie`, `header`, `intercept`, `ui`. Auto-probed on first run; cached afterward. ## Strategy cascade The auto-probe sequence Uni-CLI runs on first call to a site. Tries each strategy from cheapest to most expensive (`public` to `ui`) until one returns parseable data. The selected strategy is then cached so subsequent calls skip the probe. ## Tap A pipeline step that bridges Vue stores (Pinia, Vuex) to network capture. Drives the page's own state actions, then captures the resulting XHR/fetch responses. Used for sites with deep client-side state (Twitter, Bilibili, Notion). ## UI strategy The most expensive auth strategy. Drives a real browser session interactively — clicks, types, snapshots, waits. Used when a site requires multi-step user interaction that cannot be replicated by header injection or XHR replay. ## v2 envelope version The current AgentEnvelope schema. v1 was a flat `{ ok, data, error }` shape; v2 added structured `error` fields, `meta`, `version`, and `exit_code` for shell-friendly routing. All adapters as of v0.213 emit v2. ## Web-api adapter An adapter that hits HTTP APIs directly, with no browser involvement. The most common adapter type. Uses `fetch`, `fetch_text`, `parse_rss`, and `html_to_md` for retrieval; `select`, `map`, `filter` for shaping. ## YAML adapter The preferred adapter format. A 20-30 line file declaring site, name, type, strategy, args, pipeline, and columns. Agent-readable, agent-editable, and free of Turing-complete logic so agents can patch it deterministically. Lives at `~/.unicli/adapters//.yaml`. --- # Page: Guide Index Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/ Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide.md # Guide Index - Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/ - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide.md - Section: Guides Use these pages when you are trying to accomplish a task. | Task | Page | | ----------------------- | ------------------------------------ | | Install and run Uni-CLI | [Getting Started](/guide/getting-started) | | Connect an agent client | [Integrations](/guide/integrations) | | Create an adapter | [Adapters](/guide/adapters) | | Repair a broken command | [Self-Repair](/guide/self-repair) | | Combine commands | [Recipes](/RECIPES) | Reference pages stay under [Reference](/reference/) and should describe contracts rather than walk through a workflow. --- # Page: Adapters Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/adapters Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/adapters.md # Adapters - Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/adapters - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/adapters.md - Section: Guides - Parent: Guides (/guide/) An adapter maps one site or tool to a set of CLI commands. Uni-CLI supports five adapter types, each optimized for a different integration surface. ## Adapter Types | Type | Surface | Auth | Example Sites | | --------- | -------------------- | ----------------------- | ---------------------------- | | `web-api` | HTTP APIs | None, cookie, or header | hackernews, reddit, bilibili | | `browser` | Full browser control | Chrome session | chatgpt, notion, discord | | `desktop` | Local subprocess | None | ffmpeg, imagemagick, blender | | `bridge` | Existing CLIs | Passthrough | gh, docker, vercel, yt-dlp | | `service` | WebSocket / HTTP | API key or none | ollama, obs-studio, comfyui | ## YAML Format Most adapters are ~20 lines of YAML. No imports, no build step, no runtime dependencies. ```yaml site: example name: command-name type: web-api strategy: public pipeline: - fetch: { url: "https://api.example.com/data" } - select: "items" - map: { title: "${{ item.title }}", score: "${{ item.score }}" } columns: [title, score] ``` ## web-api — HTTP APIs The most common type. Fetches data from REST APIs, transforms the response with pipeline steps. ### Public API (no auth) ```yaml site: hackernews name: top description: Top stories from Hacker News type: web-api strategy: public pipeline: - fetch: url: "https://hacker-news.firebaseio.com/v0/topstories.json" - limit: 30 - each: parallel: 10 pipeline: - fetch: url: "https://hacker-news.firebaseio.com/v0/item/${{ item }}.json" - map: title: "${{ item.title }}" score: "${{ item.score }}" by: "${{ item.by }}" url: "${{ item.url }}" columns: [title, score, by, url] ``` ### Cookie-authenticated API ```yaml site: bilibili name: feed description: Personal feed (requires login) type: web-api strategy: cookie pipeline: - fetch: url: "https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd" params: ps: 20 - select: "data.item" - map: title: "${{ item.title }}" author: "${{ item.owner.name }}" view: "${{ item.stat.view }}" url: "https://www.bilibili.com/video/${{ item.bvid }}" columns: [title, author, view, url] ``` ### Header-authenticated API (cookie + CSRF) ```yaml site: twitter name: timeline description: Home timeline type: web-api strategy: header pipeline: - fetch: url: "https://api.x.com/graphql/timeline" method: POST body: variables: count: 20 - select: "data.home.timeline_items" - map: text: "${{ item.content.text }}" author: "${{ item.core.user.screen_name }}" likes: "${{ item.engagement.likes }}" columns: [author, text, likes] ``` ## browser — Full Browser Automation For sites with no public API or heavy anti-bot protection. Drives Chrome via CDP. ### Intercept mode (capture network requests) ```yaml site: xiaohongshu name: trending description: Trending posts type: browser strategy: intercept pipeline: - navigate: url: "https://www.xiaohongshu.com/explore" waitUntil: networkidle - intercept: pattern: "**/api/sns/web/v1/homefeed" trigger: "scroll:down" timeout: 10000 - select: "data.items" - map: title: "${{ item.note_card.title }}" likes: "${{ item.note_card.interact_info.liked_count }}" columns: [title, likes] ``` ### UI mode (interact with page elements) ```yaml site: chatgpt name: ask description: Send a prompt to ChatGPT type: browser strategy: ui args: - name: prompt required: true positional: true pipeline: - navigate: url: "https://chatgpt.com" - wait: "#prompt-textarea" - click: "#prompt-textarea" - type: selector: "#prompt-textarea" text: "${{ args.prompt }}" - press: Enter - wait: 5000 - snapshot: { interactive: false } ``` ## desktop — Local Software Runs local executables via subprocess. No network, no browser. ```yaml site: ffmpeg name: info description: Show media file information type: desktop binary: ffmpeg detect: "ffmpeg -version" args: - name: file required: true positional: true pipeline: - exec: command: "ffprobe" args: [ "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "${{ args.file }}", ] parse: json - map: format: "${{ item.format.format_long_name }}" duration: "${{ item.format.duration }}" size: "${{ item.format.size }}" streams: "${{ item.streams.length }}" columns: [format, duration, size, streams] ``` ### Using write_temp for scripts For tools that accept script files (GIMP Script-Fu, Blender Python): ```yaml site: gimp name: resize description: Resize an image type: desktop binary: gimp args: - name: file required: true positional: true - name: width required: true type: int pipeline: - write_temp: ext: ".scm" content: | (let* ((image (car (gimp-file-load RUN-NONINTERACTIVE "${{ args.file }}" "${{ args.file }}"))) (drawable (car (gimp-image-get-active-drawable image)))) (gimp-image-scale-full image ${{ args.width }} 0 INTERPOLATION-CUBIC) (gimp-file-overwrite RUN-NONINTERACTIVE image drawable "${{ args.file }}" "${{ args.file }}")) - exec: command: "gimp" args: [ "-i", "-b", '(gimp-script-fu-console-run 0 "${{ steps.write_temp.path }}")', ] ``` ## bridge — CLI Passthrough Wraps an existing CLI tool, parsing its output into structured data. ```yaml site: gh name: repos description: List GitHub repositories type: bridge binary: gh autoInstall: "brew install gh" detect: "gh --version" pipeline: - exec: command: "gh" args: [ "repo", "list", "--json", "name,description,stargazerCount,updatedAt", "--limit", "20", ] parse: json - map: name: "${{ item.name }}" description: "${{ item.description }}" stars: "${{ item.stargazerCount }}" updated: "${{ item.updatedAt }}" columns: [name, stars, description, updated] ``` Bridge adapters can declare `autoInstall` — Uni-CLI will suggest the install command if the binary is missing. ## service — WebSocket and HTTP Services For persistent connections to local or remote services. ```yaml site: obs-studio name: scene description: Get current OBS scene type: service health: "http://localhost:4455" pipeline: - websocket: url: "ws://localhost:4455" auth: obs send: op: 6 d: requestType: GetCurrentProgramScene requestId: "1" receive: match: { "d.requestId": "1" } - select: "d.responseData" - map: scene: "${{ item.sceneName }}" uuid: "${{ item.sceneUuid }}" columns: [scene, uuid] ``` ## TypeScript Adapters For complex logic that exceeds what YAML can express, use TypeScript: ```typescript import { cli, Strategy } from "../../registry.js"; cli({ site: "example", name: "search", description: "Search with pagination", strategy: Strategy.COOKIE, args: [ { name: "query", required: true, positional: true }, { name: "page", type: "int", default: 1 }, ], func: async (page, kwargs) => { const resp = await fetch( `https://api.example.com/search?q=${kwargs.query}&p=${kwargs.page}`, ); const data = await resp.json(); return data.results.map((r: Record) => ({ title: r.title, url: r.url, })); }, }); ``` TypeScript adapters use the `cli()` helper from the registry. They have full access to the `IPage` interface for browser automation. ## File Locations | Location | Purpose | | --------------------------------- | --------------------------------- | | `src/adapters/SITE/` | Built-in adapters (ship with npm) | | `~/.unicli/adapters/SITE/` | User-local overrides | | `~/.unicli/adapters/SITE/CMD.yml` | Single command override | User-local adapters take precedence over built-in ones. This is how self-repair works — an agent edits the YAML in `~/.unicli/adapters/`, and the fix survives `npm update`. ## Arguments Adapters declare arguments in the `args` field: ```yaml args: - name: query required: true positional: true # unicli site cmd "my query" description: Search term - name: limit type: int default: 20 description: Max results - name: sort choices: [hot, new, top] default: hot ``` | Field | Type | Description | | ------------- | -------- | -------------------------------- | | `name` | string | Argument name (becomes `--name`) | | `type` | string | `str`, `int`, `float`, or `bool` | | `required` | boolean | Fail if missing | | `positional` | boolean | Can be passed without `--name` | | `default` | any | Default value | | `choices` | string[] | Allowed values | | `description` | string | Help text | --- # Page: Self-Repair Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/self-repair Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/self-repair.md # Self-Repair - Canonical: https://olo-dot-io.github.io/Uni-CLI/guide/self-repair - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/guide/self-repair.md - Section: Guides - Parent: Guides (/guide/) The web breaks constantly. Selectors change, APIs version, auth tokens rotate, desktop permission channels disappear, and CLIs change flags. Uni-CLI is designed to fail as structured data with a bounded repair path. ## The Problem Traditional scrapers and API wrappers fail silently or catastrophically when the target changes. The fix cycle is slow: notice failure, read logs, find the change, edit code, test, deploy. Uni-CLI compresses this cycle by making adapters readable, errors structured as v2 `AgentEnvelope` objects, and fixes persistent through the `~/.unicli/adapters/` overlay. ## Repair Levels ### Level 0: Auto-Retry Transient failures (network timeouts, rate limits, 5xx errors) are retried automatically with exponential backoff. ``` Request failed (503) → wait 1s → retry → wait 2s → retry → wait 4s → retry → give up ``` Configuration is per-step in the pipeline: ```yaml pipeline: - fetch: url: "https://api.example.com/data" retry: 3 backoff: exponential ``` Exit code `75` (temporary failure) signals the agent to retry the entire command later. ### Level 1: Auto-Fix When a pipeline step fails, the engine preserves enough failure context for the next actor: - **Selector miss**: a CSS selector or JSON path matched nothing. - **Empty result**: the upstream returned data but the adapter projected none of it. - **Schema change**: expected fields are missing or renamed. - **Auth/permission failure**: cookies, local app automation, or platform permissions are unavailable. These diagnostics appear in the structured error output, giving the next level (agent-assisted repair) a bounded starting point. ### Level 2: Agent-Assisted This is Uni-CLI's core differentiator. When a command fails, the error is emitted as a structured envelope: ```json { "ok": false, "schema_version": "2", "command": "bilibili.feed", "meta": { "duration_ms": 82 }, "data": null, "error": { "code": "selector_miss", "message": "select path returned no rows", "adapter_path": "/Users/you/.unicli/adapters/bilibili/feed.yml", "step": 3, "suggestion": "Try: select: data.result.feeds", "retryable": false, "alternatives": ["bilibili.search"] } } ``` An AI agent reads this error, opens the 20-line YAML at `adapter_path`, applies the fix, and retries: ``` unicli bilibili feed → fails with structured error JSON → agent reads error: selector_miss at step 3 → agent reads ~/.unicli/adapters/bilibili/feed.yml → agent changes "data.items" to "data.result.feeds" → agent runs: unicli bilibili feed → success ``` The fix persists in `~/.unicli/adapters/` and survives `npm update` because user-local adapters override built-in ones. ### Level 3: Community Fix When many agents encounter the same failure, the fix propagates through the adapter registry: 1. Agent fixes a broken adapter locally 2. Agent submits the fix (PR or registry update) 3. Other users receive the fix via `npm update` or adapter sync The `unicli repair` command helps diagnose issues: ```bash unicli repair bilibili feed ``` This runs the adapter, catches the failure, and prints a detailed diagnostic report with the suggested fix. ### Level 4: AI Generation For entirely new sites with no existing adapter, agents can generate one from scratch: 1. **Record**: `unicli record https://example.com` opens Chrome, records your interactions, and captures network requests. 2. **Generate**: The recording is translated into a YAML adapter draft. 3. **Test**: `unicli test example` verifies the generated adapter works. 4. **Iterate**: The agent refines the YAML based on test output. ## Structured Errors Every error includes enough context for an agent to act without asking a human: | Field | Type | Description | | -------------------- | ------- | ------------------------------------------------------------- | | `ok` | boolean | `false` for failures | | `schema_version` | string | Envelope schema, currently `"2"` | | `command` | string | Fully qualified command, such as `bilibili.feed` | | `error.code` | string | Stable error code, such as `selector_miss` or `auth_required` | | `error.message` | string | Human-readable failure detail | | `error.adapter_path` | string | Adapter file to inspect | | `error.step` | number | Pipeline step index when known | | `error.suggestion` | string | Actionable next step | | `error.retryable` | boolean | Whether retrying the same command may help | | `error.alternatives` | array | Nearby commands to try | ## Error Types | Error code | Meaning | Typical fix | | ------------------------------------- | --------------------------------------- | ------------------------------------------- | | `selector_miss` | CSS selector or JSON path missed | Update selector in YAML | | `auth_required` / `not_authenticated` | Cookie/token missing or expired | `unicli auth setup SITE` | | `network_error` | Connection failed | Check network, retry later | | `rate_limited` | Too many requests | Wait, add `rate_limit` or lower `limit` | | `unavailable` | Required local runtime is missing | Install or grant permission | | `invalid_input` | Argument failed validation | Fix args or adapter schema | | `internal_error` | Runtime bug or unhandled upstream shape | Run `unicli repair` and inspect the adapter | ## Repair Workflow The `unicli repair` command automates diagnosis: ```bash # Diagnose a specific command unicli repair bilibili feed # Test all commands for a site unicli test bilibili # Test all adapters unicli test ``` `unicli repair` runs the command, catches the failure, and outputs a structured diagnostic that includes: - The exact step that failed - The current YAML configuration - The actual response shape when available - A suggested fix ## Design Principles 1. **Errors are structured data.** JSON to stderr, parseable by any agent. 2. **Adapters are small.** YAML-first adapters are short enough for an agent to inspect directly. 3. **Fixes are local.** `~/.unicli/adapters/` overrides survive updates. 4. **Exit codes are semantic.** `sysexits.h` codes tell agents _what kind_ of failure occurred. 5. **Suggestions are actionable.** "Try: select: data.result.feeds" gives the next edit. --- # Page: Reference Index Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/ Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference.md # Reference Index - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/ - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference.md - Section: Reference Use these pages when you need exact behavior, fields, commands, or release rules. | Contract | Page | | --------------------- | ---------------------------------- | | Adapter schema | [Adapter Format](/ADAPTER-FORMAT) | | Supported sites | [Sites Catalog](/reference/sites) | | Pipeline step catalog | [Pipeline Steps](/reference/pipeline) | | Process exit behavior | [Exit Codes](/reference/exit-codes) | | Maintenance commands | [Maintenance Tools](/reference/maintenance) | | Plugin public API | [Plugin Authoring](/PLUGIN) | | Release mechanics | [Release](/reference/release) | The reference section should stay terse and scan-friendly. Put task walkthroughs in [Guides](/guide/) and broader rationale in the explanation pages. --- # Page: Operation Catalog Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/sites Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/sites.md # Operation Catalog - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/sites - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/sites.md - Section: Reference - Parent: Reference (/reference/) Uni-CLI publishes the same generated operation manifest to the docs site that the CLI uses for discovery. This page is the human-readable operation catalog: filter by substrate, search by site or command, and inspect representative operations before running `unicli search`. ## Generated Site Catalog This catalog is generated from the adapter manifest: 317 sites, 1772 commands. | Site | Surface | Commands | Auth | Example commands | | --- | --- | ---: | --- | --- | | 12306 | web-api | 3 | no | unicli 12306 price
unicli 12306 stations
unicli 12306 trains | | 1688 | web-api | 5 | yes | unicli 1688 item
unicli 1688 search
unicli 1688 store | | 1point3acres | web-api | 9 | yes | unicli 1point3acres hot
unicli 1point3acres latest
unicli 1point3acres digest | | 36kr | web-api | 5 | no | unicli 36kr article
unicli 36kr hot
unicli 36kr latest | | 51job | web-api | 4 | yes | unicli 51job search
unicli 51job hot
unicli 51job detail | | acl-anthology | web-api | 2 | no | unicli acl-anthology search
unicli acl-anthology paper | | adguardhome | service | 5 | no | unicli adguardhome add-rule
unicli adguardhome rules
unicli adguardhome stats | | aibase | web-api | 1 | no | unicli aibase news | | amazon | web-api | 8 | yes | unicli amazon bestsellers
unicli amazon discussion
unicli amazon movers-shakers | | anilist | web-api | 5 | no | unicli anilist anime
unicli anilist manga
unicli anilist characters | | antigravity | web-api | 16 | no | unicli antigravity extract-code
unicli antigravity watch
unicli antigravity ask | | apple-notes | desktop | 3 | no | unicli apple-notes list
unicli apple-notes read
unicli apple-notes search | | apple-podcasts | web-api | 3 | no | unicli apple-podcasts episodes
unicli apple-podcasts search
unicli apple-podcasts top | | arxiv | web-api | 6 | no | unicli arxiv download
unicli arxiv paper
unicli arxiv search | | audacity | desktop | 8 | no | unicli audacity convert
unicli audacity effects
unicli audacity info | | autoagent | bridge | 1 | no | unicli autoagent eval-run | | aws | bridge | 1 | no | unicli aws s3-ls | | baidu | web-api | 2 | yes | unicli baidu hot
unicli baidu search | | baidu-scholar | web-api | 1 | no | unicli baidu-scholar search | | band | web-api | 4 | yes | unicli band bands
unicli band mentions
unicli band post | | bangumi | web-api | 5 | no | unicli bangumi characters
unicli bangumi subject
unicli bangumi anime | | barchart | web-api | 4 | yes | unicli barchart flow
unicli barchart greeks
unicli barchart options | | bbc | web-api | 5 | no | unicli bbc news
unicli bbc technology
unicli bbc top | | bilibili | web-api | 20 | yes | unicli bilibili coin
unicli bilibili dynamic
unicli bilibili favorites | | binance | web-api | 13 | no | unicli binance asks
unicli binance depth
unicli binance gainers | | blender | desktop | 13 | no | unicli blender animation
unicli blender camera
unicli blender convert | | bloomberg | web-api | 10 | no | unicli bloomberg businessweek
unicli bloomberg economics
unicli bloomberg feeds | | bluesky | web-api | 12 | yes | unicli bluesky feeds
unicli bluesky followers
unicli bluesky following | | boss | web-api | 14 | yes | unicli boss batchgreet
unicli boss chatlist
unicli boss chatmsg | | brave | web-api | 1 | no | unicli brave search | | chaoxing | web-api | 2 | yes | unicli chaoxing assignments
unicli chaoxing exams | | chatgpt | web-api | 17 | yes | unicli chatgpt image
unicli chatgpt history
unicli chatgpt detail | | chatwise | web-api | 16 | no | unicli chatwise history
unicli chatwise export
unicli chatwise ask | | chrome | desktop | 2 | no | unicli chrome bookmarks
unicli chrome tabs | | cipo | web-api | 3 | no | unicli cipo get
unicli cipo legal-status
unicli cipo search | | claude | web-api | 14 | yes | unicli claude ask
unicli claude send
unicli claude new | | claude-code | bridge | 1 | no | unicli claude-code version | | cloudcompare | desktop | 4 | no | unicli cloudcompare compare
unicli cloudcompare convert
unicli cloudcompare info | | cnipa | web-api | 3 | no | unicli cnipa get
unicli cnipa legal-status
unicli cnipa search | | cnki | web-api | 1 | no | unicli cnki search | | cnn | web-api | 2 | no | unicli cnn technology
unicli cnn top | | cocoapods | web-api | 2 | no | unicli cocoapods info
unicli cocoapods search | | codex | web-api | 18 | no | unicli codex extract-diff
unicli codex history
unicli codex export | | codex-cli | bridge | 1 | no | unicli codex-cli version | | coinbase | web-api | 2 | no | unicli coinbase prices
unicli coinbase rates | | coingecko | web-api | 7 | no | unicli coingecko coin
unicli coingecko top
unicli coingecko trending | | comfyui | service | 4 | no | unicli comfyui generate
unicli comfyui history
unicli comfyui nodes | | coupang | web-api | 4 | yes | unicli coupang add-to-cart
unicli coupang hot
unicli coupang search | | crates | web-api | 2 | no | unicli crates search
unicli crates crate | | crates-io | web-api | 3 | no | unicli crates-io info
unicli crates-io search
unicli crates-io versions | | crossref | web-api | 2 | no | unicli crossref search
unicli crossref work | | ctrip | web-api | 4 | yes | unicli ctrip search
unicli ctrip hotel-suggest
unicli ctrip hotel-search | | cursor | web-api | 18 | no | unicli cursor composer
unicli cursor extract-code
unicli cursor export | | cvf | web-api | 1 | no | unicli cvf search | | danbooru | web-api | 8 | no | unicli danbooru artists
unicli danbooru comments
unicli danbooru detail | | dangdang | web-api | 2 | yes | unicli dangdang hot
unicli dangdang search | | dblp | web-api | 4 | no | unicli dblp search
unicli dblp paper
unicli dblp venue | | deepseek | web-api | 9 | yes | unicli deepseek chat
unicli deepseek models
unicli deepseek ask | | defillama | web-api | 2 | no | unicli defillama protocols
unicli defillama protocol | | defuddle | web-api | 1 | no | unicli defuddle read | | devto | web-api | 6 | no | unicli devto latest
unicli devto search
unicli devto tag | | dianping | web-api | 3 | yes | unicli dianping hot
unicli dianping search
unicli dianping shop | | dictionary | web-api | 3 | no | unicli dictionary examples
unicli dictionary search
unicli dictionary synonyms | | dingtalk | bridge | 8 | no | unicli dingtalk version
unicli dingtalk open-app
unicli dingtalk status-app | | discord-app | web-api | 15 | no | unicli discord-app servers
unicli discord-app channels
unicli discord-app read | | dlsite | web-api | 8 | no | unicli dlsite search
unicli dlsite manga
unicli dlsite cg | | docker | desktop | 7 | no | unicli docker build
unicli docker images
unicli docker logs | | docker-hub | web-api | 3 | no | unicli docker-hub info
unicli docker-hub search
unicli docker-hub tags | | dockerhub | web-api | 2 | no | unicli dockerhub search
unicli dockerhub image | | doctl | bridge | 1 | no | unicli doctl droplets | | douban | web-api | 12 | yes | unicli douban book-hot
unicli douban download
unicli douban group-hot | | doubao | web-api | 9 | yes | unicli doubao ask
unicli doubao new
unicli doubao status | | doubao-web | web-api | 9 | yes | unicli doubao-web ask
unicli doubao-web detail
unicli doubao-web history | | douyin | web-api | 13 | yes | unicli douyin activities
unicli douyin collections
unicli douyin delete | | douyu | web-api | 2 | yes | unicli douyu hot
unicli douyu search | | dpma | web-api | 2 | no | unicli dpma get
unicli dpma search | | drawio | desktop | 1 | no | unicli drawio export | | duckduckgo | web-api | 2 | no | unicli duckduckgo search
unicli duckduckgo suggest | | eastmoney | web-api | 18 | no | unicli eastmoney fund
unicli eastmoney hot
unicli eastmoney market | | ehentai | web-api | 6 | no | unicli ehentai search
unicli ehentai artist
unicli ehentai tag | | ele | web-api | 2 | yes | unicli ele hot
unicli ele search | | endoflife | web-api | 1 | no | unicli endoflife product | | epo | web-api | 4 | no | unicli epo family
unicli epo get
unicli epo legal-status | | espacenet | web-api | 4 | no | unicli espacenet family
unicli espacenet get
unicli espacenet legal-status | | excel | desktop | 7 | no | unicli excel insert-image
unicli excel insert-link
unicli excel list | | exchangerate | web-api | 2 | no | unicli exchangerate convert
unicli exchangerate list | | facebook | web-api | 15 | yes | unicli facebook add-friend
unicli facebook events
unicli facebook feed | | feishu | bridge | 4 | no | unicli feishu calendar
unicli feishu docs
unicli feishu send | | ffmpeg | desktop | 11 | no | unicli ffmpeg compress
unicli ffmpeg concat
unicli ffmpeg convert | | figma | browser | 8 | yes | unicli figma export-selected
unicli figma open-app
unicli figma status-app | | fips | web-api | 2 | no | unicli fips get
unicli fips search | | flathub | web-api | 2 | no | unicli flathub search
unicli flathub app | | flyctl | bridge | 1 | no | unicli flyctl apps | | freecad | desktop | 15 | no | unicli freecad assembly
unicli freecad bom
unicli freecad boolean | | freepatentsonline-web | web-api | 2 | no | unicli freepatentsonline-web get
unicli freepatentsonline-web search | | futu | web-api | 2 | yes | unicli futu hot
unicli futu quote | | gemini | web-api | 5 | yes | unicli gemini ask
unicli gemini deep-research-result
unicli gemini deep-research | | gh | bridge | 6 | no | unicli gh issue
unicli gh pr
unicli gh release | | gimp | desktop | 12 | no | unicli gimp adjust
unicli gimp batch
unicli gimp convert | | gitee | web-api | 4 | no | unicli gitee repos
unicli gitee search
unicli gitee trending | | github-trending | web-api | 3 | no | unicli github-trending daily
unicli github-trending developers
unicli github-trending weekly | | gitlab | web-api | 3 | no | unicli gitlab projects
unicli gitlab search
unicli gitlab trending | | godot | desktop | 2 | no | unicli godot project-run
unicli godot scene-export | | google | web-api | 4 | no | unicli google news
unicli google search
unicli google suggest | | google-patents-bq | web-api | 2 | yes | unicli google-patents-bq prior-art
unicli google-patents-bq search | | google-patents-web | web-api | 2 | no | unicli google-patents-web get
unicli google-patents-web search | | google-scholar | web-api | 3 | no | unicli google-scholar cite
unicli google-scholar profile
unicli google-scholar search | | goproxy | web-api | 2 | no | unicli goproxy module
unicli goproxy versions | | gov-law | web-api | 2 | no | unicli gov-law search
unicli gov-law recent | | gov-policy | web-api | 2 | no | unicli gov-policy search
unicli gov-policy recent | | grok | web-api | 8 | yes | unicli grok ask
unicli grok read
unicli grok history | | hackernews | web-api | 11 | no | unicli hackernews ask
unicli hackernews best
unicli hackernews comments | | hermes | desktop | 3 | no | unicli hermes sessions-search
unicli hermes skills-list
unicli hermes skills-read | | hf | web-api | 5 | no | unicli hf datasets
unicli hf models
unicli hf spaces | | homebrew | web-api | 5 | no | unicli homebrew info
unicli homebrew search
unicli homebrew formula | | huggingface-papers | web-api | 2 | no | unicli huggingface-papers daily
unicli huggingface-papers search | | hupu | web-api | 7 | yes | unicli hupu detail
unicli hupu hot
unicli hupu like | | imagemagick | desktop | 6 | no | unicli imagemagick compare
unicli imagemagick composite
unicli imagemagick convert | | imdb | web-api | 7 | no | unicli imdb box-office
unicli imdb person
unicli imdb reviews | | imessage | desktop | 3 | no | unicli imessage contact
unicli imessage recent
unicli imessage search | | indeed | web-api | 2 | yes | unicli indeed search
unicli indeed job | | infoq | web-api | 2 | no | unicli infoq articles
unicli infoq latest | | inkscape | desktop | 3 | no | unicli inkscape convert
unicli inkscape export
unicli inkscape optimize | | inpi-br | web-api | 2 | no | unicli inpi-br get
unicli inpi-br search | | inpi-fr | web-api | 2 | no | unicli inpi-fr get
unicli inpi-fr search | | instagram | web-api | 29 | yes | unicli instagram activity
unicli instagram comment
unicli instagram explore | | ip-info | web-api | 1 | no | unicli ip-info lookup | | ipaustralia | web-api | 2 | no | unicli ipaustralia get
unicli ipaustralia search | | itch-io | web-api | 3 | no | unicli itch-io popular
unicli itch-io search
unicli itch-io top | | ithome | web-api | 3 | no | unicli ithome hot
unicli ithome latest
unicli ithome news | | jd | web-api | 7 | yes | unicli jd hot
unicli jd item
unicli jd search | | jianyu | browser | 2 | yes | unicli jianyu search
unicli jianyu detail | | jike | browser | 10 | yes | unicli jike feed
unicli jike notifications
unicli jike post | | jimeng | web-api | 4 | yes | unicli jimeng generate
unicli jimeng history
unicli jimeng new | | jina | web-api | 1 | no | unicli jina read | | jpo | web-api | 2 | no | unicli jpo get
unicli jpo search | | jq | bridge | 2 | no | unicli jq format
unicli jq query | | juejin | web-api | 2 | no | unicli juejin hot
unicli juejin search | | kdenlive | desktop | 3 | no | unicli kdenlive effects
unicli kdenlive info
unicli kdenlive render | | ke | browser | 4 | yes | unicli ke ershoufang
unicli ke xiaoqu
unicli ke zufang | | kipris | web-api | 3 | no | unicli kipris get
unicli kipris legal-status
unicli kipris search | | konachan | web-api | 4 | no | unicli konachan detail
unicli konachan download
unicli konachan search | | krita | desktop | 4 | no | unicli krita batch
unicli krita convert
unicli krita export | | kuaishou | web-api | 2 | yes | unicli kuaishou hot
unicli kuaishou search | | lark | bridge | 8 | no | unicli lark version
unicli lark open-app
unicli lark status-app | | leetcode | web-api | 1 | no | unicli leetcode discuss-search | | lens | web-api | 2 | yes | unicli lens get
unicli lens search | | lesswrong | web-api | 15 | no | unicli lesswrong comments
unicli lesswrong curated
unicli lesswrong frontpage | | libreoffice | desktop | 2 | no | unicli libreoffice convert
unicli libreoffice print | | lichess | web-api | 2 | no | unicli lichess top
unicli lichess user | | linear | web-api | 10 | no | unicli linear issue-create
unicli linear issue-list
unicli linear issue-update | | linkedin | web-api | 4 | yes | unicli linkedin jobs
unicli linkedin profile
unicli linkedin search | | linux-do | web-api | 11 | yes | unicli linux-do categories
unicli linux-do category
unicli linux-do feed | | lobsters | web-api | 7 | no | unicli lobsters active
unicli lobsters hot
unicli lobsters newest | | macos | desktop | 60 | no | unicli macos active-app
unicli macos apps-list
unicli macos apps | | maimai | browser | 2 | yes | unicli maimai search
unicli maimai search-talents | | mangadex | web-api | 2 | no | unicli mangadex manga
unicli mangadex authors | | maoyan | web-api | 2 | yes | unicli maoyan hot
unicli maoyan search | | markdown-new | web-api | 1 | no | unicli markdown-new read | | marxists-cn | web-api | 7 | no | unicli marxists-cn index
unicli marxists-cn reading-list
unicli marxists-cn western-marxism | | mastodon | web-api | 5 | no | unicli mastodon search
unicli mastodon timeline
unicli mastodon trending | | maven | web-api | 3 | no | unicli maven info
unicli maven search
unicli maven artifact | | mdn | web-api | 1 | no | unicli mdn search | | medium | web-api | 6 | no | unicli medium article
unicli medium feed
unicli medium search | | meituan | web-api | 1 | yes | unicli meituan search | | mermaid | desktop | 1 | no | unicli mermaid render | | minimax | web-api | 3 | yes | unicli minimax chat
unicli minimax models
unicli minimax tts | | moegirl | web-api | 3 | no | unicli moegirl search
unicli moegirl page
unicli moegirl links | | motion-studio | web-api | 1 | no | unicli motion-studio component-get | | mubu | web-api | 6 | yes | unicli mubu list
unicli mubu search
unicli mubu docs | | musescore | desktop | 5 | no | unicli musescore convert
unicli musescore export
unicli musescore info | | neonctl | bridge | 1 | no | unicli neonctl projects | | netease-music | web-api | 17 | no | unicli netease-music hot
unicli netease-music playlist
unicli netease-music search | | netlify | bridge | 1 | no | unicli netlify sites | | neurips | web-api | 1 | no | unicli neurips search | | notebooklm | web-api | 15 | yes | unicli notebooklm current
unicli notebooklm get
unicli notebooklm history | | notion | web-api | 18 | yes | unicli notion databases
unicli notion pages
unicli notion search | | novita | service | 3 | no | unicli novita generate
unicli novita models
unicli novita status | | nowcoder | web-api | 16 | yes | unicli nowcoder hot
unicli nowcoder trending
unicli nowcoder topics | | npm | web-api | 5 | no | unicli npm downloads
unicli npm info
unicli npm search | | npm-trends | web-api | 2 | no | unicli npm-trends compare
unicli npm-trends trending | | nuget | web-api | 3 | no | unicli nuget info
unicli nuget search
unicli nuget package | | nvd | web-api | 1 | no | unicli nvd cve | | nytimes | web-api | 2 | no | unicli nytimes search
unicli nytimes top | | obs | service | 8 | no | unicli obs record-start
unicli obs record-stop
unicli obs scenes | | obsidian | desktop | 10 | no | unicli obsidian daily
unicli obsidian open
unicli obsidian search | | oeis | web-api | 2 | no | unicli oeis search
unicli oeis sequence | | ollama | service | 4 | no | unicli ollama generate
unicli ollama list
unicli ollama models | | ollama-cloud | web-api | 2 | no | unicli ollama-cloud fetch
unicli ollama-cloud search | | ones | web-api | 11 | yes | unicli ones enrich-tasks
unicli ones login
unicli ones logout | | openalex | web-api | 2 | no | unicli openalex search
unicli openalex work | | opencode | bridge | 1 | no | unicli opencode version | | openfda | web-api | 2 | no | unicli openfda drug-label
unicli openfda food-recall | | openharness | desktop | 2 | no | unicli openharness memory-read
unicli openharness skills-list | | openreview | web-api | 5 | no | unicli openreview search
unicli openreview paper
unicli openreview author | | openrouter | web-api | 2 | no | unicli openrouter models
unicli openrouter search | | osv | web-api | 2 | no | unicli osv query
unicli osv vulnerability | | packagist | web-api | 3 | no | unicli packagist info
unicli packagist search
unicli packagist package | | pandoc | desktop | 1 | no | unicli pandoc convert | | paperreview | web-api | 3 | no | unicli paperreview feedback
unicli paperreview review
unicli paperreview submit | | patsnap | web-api | 2 | yes | unicli patsnap get
unicli patsnap search | | pdf | desktop | 1 | no | unicli pdf read | | perplexity | web-api | 8 | yes | unicli perplexity ask
unicli perplexity open-app
unicli perplexity status-app | | pexels | web-api | 2 | yes | unicli pexels curated
unicli pexels search | | pinduoduo | web-api | 2 | yes | unicli pinduoduo hot
unicli pinduoduo search | | pixiv | web-api | 6 | yes | unicli pixiv detail
unicli pixiv download
unicli pixiv illusts | | pmlr | web-api | 2 | no | unicli pmlr search
unicli pmlr paper | | powerchina | web-api | 1 | yes | unicli powerchina search | | powerpoint | desktop | 7 | no | unicli powerpoint add-slide
unicli powerpoint insert-image
unicli powerpoint insert-link | | pqai | web-api | 2 | no | unicli pqai prior-art
unicli pqai search | | producthunt | web-api | 5 | no | unicli producthunt browse
unicli producthunt hot
unicli producthunt posts | | pscale | bridge | 1 | no | unicli pscale databases | | pub-dev | web-api | 2 | no | unicli pub-dev info
unicli pub-dev search | | pubmed | web-api | 5 | no | unicli pubmed search
unicli pubmed article
unicli pubmed author | | pypi | web-api | 5 | no | unicli pypi info
unicli pypi search
unicli pypi versions | | quark | web-api | 8 | yes | unicli quark ls
unicli quark search
unicli quark mkdir | | qweather | web-api | 2 | no | unicli qweather forecast
unicli qweather now | | qwen | web-api | 8 | yes | unicli qwen ask
unicli qwen read
unicli qwen send | | railway | bridge | 1 | no | unicli railway deploy | | reddit | web-api | 24 | yes | unicli reddit comment
unicli reddit comments
unicli reddit read | | rednote | web-api | 7 | yes | unicli rednote note
unicli rednote search
unicli rednote user | | renderdoc | desktop | 2 | no | unicli renderdoc capture-list
unicli renderdoc frame-export | | replicate | web-api | 3 | yes | unicli replicate run
unicli replicate search
unicli replicate trending | | rest-countries | web-api | 2 | no | unicli rest-countries country
unicli rest-countries region | | reuters | web-api | 5 | no | unicli reuters article
unicli reuters latest
unicli reuters search | | rfc | web-api | 1 | no | unicli rfc rfc | | rubygems | web-api | 3 | no | unicli rubygems info
unicli rubygems search
unicli rubygems gem | | safebooru | web-api | 4 | no | unicli safebooru detail
unicli safebooru download
unicli safebooru search | | semantic-scholar | web-api | 4 | no | unicli semantic-scholar search
unicli semantic-scholar paper
unicli semantic-scholar citations | | shotcut | desktop | 3 | no | unicli shotcut effects
unicli shotcut info
unicli shotcut render | | sinablog | browser | 4 | no | unicli sinablog article
unicli sinablog hot
unicli sinablog search | | sinafinance | web-api | 5 | no | unicli sinafinance market
unicli sinafinance news
unicli sinafinance rolling-news | | sketch | desktop | 3 | no | unicli sketch artboards
unicli sketch export
unicli sketch symbols | | slack | web-api | 14 | yes | unicli slack channels
unicli slack messages
unicli slack post | | slay-the-spire-ii | service | 6 | no | unicli slay-the-spire-ii deck
unicli slay-the-spire-ii end-turn
unicli slay-the-spire-ii map | | slock | browser | 1 | yes | unicli slock servers | | smzdm | web-api | 3 | yes | unicli smzdm article
unicli smzdm hot
unicli smzdm search | | spotify | web-api | 24 | yes | unicli spotify now-playing
unicli spotify playlists
unicli spotify search | | sspai | web-api | 2 | no | unicli sspai hot
unicli sspai latest | | stackoverflow | web-api | 10 | no | unicli stackoverflow bounties
unicli stackoverflow hot
unicli stackoverflow question | | stagehand | bridge | 1 | no | unicli stagehand wrap-observe | | steam | web-api | 7 | no | unicli steam app-details
unicli steam new-releases
unicli steam search | | substack | web-api | 4 | no | unicli substack feed
unicli substack publication
unicli substack search | | supabase | bridge | 1 | no | unicli supabase projects | | taobao | browser | 6 | yes | unicli taobao hot
unicli taobao search
unicli taobao detail | | tdx | web-api | 1 | yes | unicli tdx hot-rank | | techcrunch | web-api | 2 | no | unicli techcrunch latest
unicli techcrunch search | | theverge | web-api | 2 | no | unicli theverge latest
unicli theverge search | | threads | web-api | 6 | yes | unicli threads hot
unicli threads search
unicli threads user | | ths | web-api | 1 | yes | unicli ths hot-rank | | tieba | web-api | 4 | no | unicli tieba hot
unicli tieba posts
unicli tieba read | | tiktok | web-api | 18 | yes | unicli tiktok comment
unicli tiktok explore
unicli tiktok follow | | toutiao | web-api | 3 | yes | unicli toutiao hot
unicli toutiao search
unicli toutiao articles | | tvmaze | web-api | 2 | no | unicli tvmaze search
unicli tvmaze show | | twitch | web-api | 4 | yes | unicli twitch games
unicli twitch search
unicli twitch streams | | twitter | web-api | 47 | yes | unicli twitter lists
unicli twitter media
unicli twitter mentions | | uisdc | web-api | 1 | no | unicli uisdc news | | uiverse | web-api | 2 | no | unicli uiverse code
unicli uiverse preview | | ukipo | web-api | 1 | no | unicli ukipo info | | unpaywall | web-api | 1 | no | unicli unpaywall oa | | unsplash | web-api | 2 | no | unicli unsplash random
unicli unsplash search | | uspto | web-api | 3 | no | unicli uspto get
unicli uspto legal-status
unicli uspto search | | v2ex | web-api | 12 | yes | unicli v2ex daily
unicli v2ex hot
unicli v2ex latest | | vercel | bridge | 1 | no | unicli vercel list | | vndb | web-api | 7 | no | unicli vndb search
unicli vndb vn
unicli vndb releases | | vscode | desktop | 10 | no | unicli vscode extensions
unicli vscode install-ext
unicli vscode open | | wanfang | web-api | 1 | no | unicli wanfang search | | web | web-api | 1 | no | unicli web read | | wechat-channels | web-api | 2 | yes | unicli wechat-channels hot
unicli wechat-channels search | | weibo | web-api | 12 | yes | unicli weibo comments
unicli weibo feed
unicli weibo hot | | weixin | browser | 6 | yes | unicli weixin article
unicli weixin download
unicli weixin hot | | weread | web-api | 8 | yes | unicli weread book
unicli weread highlights
unicli weread notebooks | | wikidata | web-api | 2 | no | unicli wikidata search
unicli wikidata entity | | wikipedia | web-api | 6 | no | unicli wikipedia random
unicli wikipedia search
unicli wikipedia summary | | wipo-patentscope | web-api | 1 | no | unicli wipo-patentscope info | | wiremock | service | 5 | no | unicli wiremock create-stub
unicli wiremock delete-stub
unicli wiremock reset | | word | desktop | 7 | no | unicli word insert-image
unicli word insert-link
unicli word insert-text | | wrangler | bridge | 1 | no | unicli wrangler list | | wttr | web-api | 2 | no | unicli wttr current
unicli wttr forecast | | xianyu | web-api | 4 | yes | unicli xianyu chat
unicli xianyu item
unicli xianyu search | | xiaoe | web-api | 5 | yes | unicli xiaoe catalog
unicli xiaoe content
unicli xiaoe courses | | xiaohongshu | web-api | 22 | yes | unicli xiaohongshu feed
unicli xiaohongshu follow
unicli xiaohongshu hashtag | | xiaoyuzhou | web-api | 5 | yes | unicli xiaoyuzhou episode
unicli xiaoyuzhou podcast-episodes
unicli xiaoyuzhou podcast | | xueqiu | web-api | 14 | yes | unicli xueqiu comments
unicli xueqiu earnings-date
unicli xueqiu feed | | yahoo | web-api | 1 | no | unicli yahoo search | | yahoo-finance | web-api | 3 | no | unicli yahoo-finance quote
unicli yahoo-finance search
unicli yahoo-finance trending | | yandere | web-api | 4 | no | unicli yandere detail
unicli yandere download
unicli yandere search | | ycombinator | web-api | 1 | no | unicli ycombinator launches | | yollomi | web-api | 12 | yes | unicli yollomi background
unicli yollomi edit
unicli yollomi face-swap | | youtube | web-api | 17 | yes | unicli youtube playlist
unicli youtube shorts
unicli youtube trending | | yt-dlp | bridge | 5 | no | unicli yt-dlp download
unicli yt-dlp extract-audio
unicli yt-dlp info | | yuanbao | web-api | 8 | yes | unicli yuanbao ask
unicli yuanbao new
unicli yuanbao shared | | zhihu | web-api | 27 | yes | unicli zhihu answer
unicli zhihu answers
unicli zhihu article | | zlibrary | web-api | 2 | yes | unicli zlibrary search
unicli zlibrary info | | zoom | desktop | 3 | no | unicli zoom join
unicli zoom start
unicli zoom toggle-mute | | zotero | service | 8 | no | unicli zotero add-note
unicli zotero add-tag
unicli zotero collections | | zsxq | web-api | 5 | yes | unicli zsxq dynamics
unicli zsxq groups
unicli zsxq search | | chatgpt-app | web-api | 8 | no | unicli chatgpt-app ask
unicli chatgpt-app send
unicli chatgpt-app read | | doubao-app | web-api | 13 | no | unicli doubao-app ask
unicli doubao-app send
unicli doubao-app read | | logseq | web-api | 7 | no | unicli logseq open-app
unicli logseq status-app
unicli logseq dump | | typora | web-api | 7 | no | unicli typora open-app
unicli typora status-app
unicli typora dump | | postman | web-api | 7 | no | unicli postman open-app
unicli postman status-app
unicli postman dump | | insomnia | web-api | 7 | no | unicli insomnia open-app
unicli insomnia status-app
unicli insomnia dump | | bitwarden | web-api | 7 | no | unicli bitwarden open-app
unicli bitwarden status-app
unicli bitwarden dump | | signal | web-api | 7 | no | unicli signal open-app
unicli signal status-app
unicli signal dump | | whatsapp | web-api | 7 | no | unicli whatsapp open-app
unicli whatsapp status-app
unicli whatsapp dump | | teams | web-api | 7 | no | unicli teams open-app
unicli teams status-app
unicli teams dump | | todoist | web-api | 7 | no | unicli todoist open-app
unicli todoist status-app
unicli todoist dump | | github-desktop | web-api | 7 | no | unicli github-desktop open-app
unicli github-desktop status-app
unicli github-desktop dump | | gitkraken | web-api | 7 | no | unicli gitkraken open-app
unicli gitkraken status-app
unicli gitkraken dump | | docker-desktop | web-api | 7 | no | unicli docker-desktop open-app
unicli docker-desktop status-app
unicli docker-desktop dump | | lm-studio | web-api | 7 | no | unicli lm-studio open-app
unicli lm-studio status-app
unicli lm-studio dump | | wechat-work | web-api | 7 | no | unicli wechat-work open-app
unicli wechat-work status-app
unicli wechat-work dump | | zoom-app | web-api | 7 | no | unicli zoom-app open-app
unicli zoom-app status-app
unicli zoom-app dump | | evernote-app | web-api | 7 | no | unicli evernote-app open-app
unicli evernote-app status-app
unicli evernote-app dump | | jikan | web-api | 4 | no | unicli jikan anime
unicli jikan manga
unicli jikan characters | | kitsu | web-api | 2 | no | unicli kitsu anime
unicli kitsu manga | --- # Page: Adapter Format Canonical: https://olo-dot-io.github.io/Uni-CLI/ADAPTER-FORMAT Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ADAPTER-FORMAT.md # Adapter Format - Canonical: https://olo-dot-io.github.io/Uni-CLI/ADAPTER-FORMAT - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ADAPTER-FORMAT.md - Section: Reference - Parent: Reference (/reference/) > The canonical reference for writing Uni-CLI adapters. 90% of adapters > are YAML; the TypeScript escape hatch covers the remaining 10% where > pipeline primitives are insufficient. ## Principles 1. **YAML first.** If the command is expressible as a finite pipeline over typed steps, write YAML. The system validates, migrates, and self-repairs YAML in ways it cannot do for arbitrary TypeScript. 2. **Agent-editable.** Keep adapters under ~50 lines of YAML whenever possible. Agents read and patch these files during self-repair. 3. **Deterministic.** The pipeline must be reproducible given the same inputs and upstream state. No wall-clock randomness, no hidden subprocess state. 4. **Minimum capability.** Declare the smallest transport surface the command needs (`http.fetch`, not `visual.anything`). Dispatchers use this to route calls safely. ## Table of Contents 1. [YAML schema (default path)](#yaml-schema-default-path) 2. [TypeScript escape hatch](#typescript-escape-hatch) 3. [Schema-v2 required fields](#schema-v2-required-fields) 4. [Strategy → transport migration](#strategy-transport-migration) 5. [Full examples](#full-examples) 6. [Troubleshooting](#troubleshooting) --- ## YAML schema (default path) A minimum viable YAML adapter: ```yaml site: example name: top description: "List top items from example.com" type: web-api transport: http strategy: public capabilities: [fetch, map, limit] minimum_capability: http.fetch trust: public confidentiality: public quarantine: false pipeline: - fetch: url: "https://example.com/api/top" - select: "data.items" - map: id: "${{ item.id }}" title: "${{ item.title }}" - limit: 20 columns: [id, title] ``` ### All fields | Field | Required | Type | Notes | | -------------------- | ----------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | `site` | yes | string | Adapter site/service key, kebab-case. Used as `unicli SITE CMD`. | | `name` | yes | string | Command name; unique per site. | | `description` | recommended | string | One-line description for `unicli list` and for agents. | | `type` | optional | `web-api` \| `browser` \| `bridge` \| `desktop` \| `service` | Omit for implicit `web-api`. Historical; the `transport` field is the v2 source of truth. | | `transport` | yes (v2) | `http` \| `cdp-browser` \| `subprocess` \| `desktop-ax` \| `desktop-uia` \| `desktop-atspi` \| `visual` | The runtime dispatcher key. | | `strategy` | optional | `public` \| `cookie` \| `header` \| `intercept` \| `ui` | Kept for 1 release as alias; see migration table below. | | `capabilities` | yes (v2) | `string[]` | List of pipeline step names this command may invoke (e.g. `[fetch, map, limit]`). | | `minimum_capability` | yes (v2) | string | Single dispatcher capability required (e.g. `http.fetch`, `cdp-browser.navigate`). | | `trust` | yes (v2) | `public` \| `user` \| `system` | Provenance trust level. Default for committed YAML: `public`. | | `confidentiality` | yes (v2) | `public` \| `internal` \| `private` | Data sensitivity. Default: `public`. Auth-required adapters: `internal` or `private`. | | `quarantine` | yes (v2) | boolean | If `true`, command is skipped by `unicli test` and marked `[quarantined]` in `unicli list` until repaired. | | `args` | optional | list | Named + positional command arguments. | | `pipeline` | yes | list of step objects | Ordered sequence of pipeline steps. | | `columns` | recommended | `string[]` | Default column order for the `md` / `csv` formatters. | | `rate_limit` | optional | object | Per-domain token bucket config; see `src/engine/steps/rate-limit.ts`. | ### Args ```yaml args: - { name: query, type: string, required: true, positional: true } - { name: limit, type: int, default: 20 } - { name: sort, type: string, default: "hot" } ``` Types: `string`, `int`, `float`, `bool`, `string[]`. Positional args populate `${{ args.NAME }}` in pipeline templates. Named flags become `--NAME VALUE` on the command line. ### Pipeline steps Pipeline steps are documented in `docs/reference/pipeline.md`. The most common ones: | Step | Transport | Purpose | | -------------- | --------------------------------- | ------------------------------------------------------ | | `fetch` | http | HTTP request with retry, cookie injection, JSON parse. | | `fetch_text` | http | HTTP request returning raw text (RSS, HTML). | | `select` | pure | JSONPath-style navigation into the response. | | `map` | pure | Transform each item via template with `${{ item.x }}`. | | `filter` | pure | Keep items matching a predicate. | | `sort` | pure | Sort by field. | | `limit` | pure | Cap result count. | | `navigate` | cdp-browser | Navigate a Chrome page via CDP. | | `intercept` | cdp-browser | Capture matching XHR/fetch responses. | | `exec` | subprocess | Run a subprocess with stdin/env/timeout. | | `snapshot` | cdp-browser + desktop-ax + visual | DOM/AX tree snapshot with `ref` numbers. | | `visual_click` | visual | Coordinate-level click via Visual backend. | Each step has a typed schema; unknown fields are rejected at load time. --- ## TypeScript escape hatch Use TS when: - The command needs control flow that YAML pipelines cannot express (multi-phase retries with domain-specific backoff, cursor-based pagination with server-computed tokens, stateful protocols like OAuth dance). - The adapter wraps a library that is easier to call than to shell out. - You need a typed response shape exported for downstream consumers. Do not use TS because "it's faster to write" — YAML is the shared vocabulary the self-repair loop and `unicli migrate` understand. ```typescript // src/adapters/example/complex.ts import { cli, Strategy } from "../../registry.js"; cli({ site: "example", name: "complex", description: "Paginated search with server-computed cursors", strategy: Strategy.COOKIE, args: [ { name: "query", required: true, positional: true }, { name: "max_pages", type: "int", default: 5 }, ], func: async (page, kwargs) => { const results: unknown[] = []; let cursor: string | undefined; for (let i = 0; i < kwargs.max_pages; i++) { const res = await fetch(`https://example.com/search`, { method: "POST", body: JSON.stringify({ q: kwargs.query, cursor }), }); const json = await res.json(); results.push(...json.hits); cursor = json.next_cursor; if (!cursor) break; } return results; }, }); ``` ### Required schema-v2 metadata for TS adapters Because TS adapters cannot be statically analysed, the `cli({...})` call must still carry the v2 metadata fields so they appear in manifests and the CI lint: ```typescript cli({ site: "example", name: "complex", capabilities: ["fetch"], minimum_capability: "http.fetch", trust: "public", confidentiality: "public", quarantine: false, // ... }); ``` Omitting these is a build error under `npm run lint:adapters`. --- ## Schema-v2 required fields Schema v2 requires five metadata fields for CI safety, capability routing, and honest provenance: | Field | Why it exists | Default when absent | | -------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `capabilities` | Declares the step surface. Used by dispatchers and by `unicli lint` to ensure only declared steps are used. | Inferred from pipeline by `unicli migrate schema-v2`. | | `minimum_capability` | Smallest transport the dispatcher must support. | `http.fetch` for legacy YAML (safe baseline). | | `trust` | Provenance — is this adapter first-party, community, or user-supplied? | `public` for committed YAML. | | `confidentiality` | Data-sensitivity label. Drives dispatcher routing when `--confidentiality` flag is set. | `public` unless `strategy` is `cookie` \| `header` \| `intercept` \| `ui` (in which case the migrator sets `internal`). | | `quarantine` | Skip this command in CI until repaired. Set by `unicli repair` when the command has failed three times. | `false`. | Migration is automated: `unicli migrate schema-v2` reads all committed YAML, fills defaults deterministically, and writes back. The migration tool is idempotent — re-running it on a migrated file is a no-op. ## Strategy → transport migration The old `strategy` field mapped to a mix of transport and auth concerns. In v2, the concerns split: `transport` routes the call, `strategy` stays only as a short-lived alias for the auth hint. | Old `strategy` | New `transport` | New auth hint (kept in `strategy` for 1 release) | | ----------------- | ------------------------------------------------ | ------------------------------------------------ | | `public` | `http` | `public` | | `cookie` | `http` | `cookie` | | `header` | `http` | `header` | | `intercept` | `cdp-browser` | `intercept` | | `ui` | `cdp-browser` | `ui` | | _(new)_ `desktop` | `desktop-ax` \| `desktop-uia` \| `desktop-atspi` | none | | _(new)_ `visual` | `visual` | none | The `unicli migrate` tool handles the split. For a hand-written adapter, set both fields explicitly and do not rely on legacy alias inference. --- ## Full examples ### 1. YAML, simplest case (web-api, public) ```yaml # src/adapters/hackernews/top.yaml site: hackernews name: top description: "Hacker News front page — top stories right now" type: web-api transport: http strategy: public capabilities: [fetch, select, map, limit] minimum_capability: http.fetch trust: public confidentiality: public quarantine: false args: - { name: limit, type: int, default: 30 } pipeline: - fetch: url: "https://hacker-news.firebaseio.com/v0/topstories.json" - limit: "${{ args.limit }}" - parallel: max: 10 map: - fetch: url: "https://hacker-news.firebaseio.com/v0/item/${{ item }}.json" - map: rank: "${{ index + 1 }}" title: "${{ item.title }}" score: "${{ item.score }}" author: "${{ item.by }}" comments: "${{ item.descendants }}" url: "${{ item.url }}" columns: [rank, title, score, author, comments, url] ``` ### 2. TypeScript escape hatch (OAuth dance) ```typescript // src/adapters/notion/search.ts import { cli } from "../../registry.js"; cli({ site: "notion", name: "search", description: "Search Notion workspace (requires OAuth)", capabilities: ["fetch"], minimum_capability: "http.fetch", trust: "public", confidentiality: "private", // accesses user workspace quarantine: false, args: [{ name: "query", required: true, positional: true }], func: async (_page, { query }) => { const token = await ensureNotionOAuthToken(); const res = await fetch("https://api.notion.com/v1/search", { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", "Notion-Version": "2022-06-28", }, body: JSON.stringify({ query, page_size: 20 }), }); const json = (await res.json()) as { results: unknown[] }; return json.results; }, }); ``` ### 3. YAML with intercept (browser capture) ```yaml # src/adapters/twitter/timeline.yaml site: twitter name: timeline description: "Home timeline via XHR intercept" type: browser transport: cdp-browser strategy: intercept capabilities: [navigate, intercept, select, map, limit] minimum_capability: cdp-browser.intercept trust: public confidentiality: private # user's timeline quarantine: false args: - { name: limit, type: int, default: 20 } pipeline: - navigate: url: "https://twitter.com/home" - intercept: pattern: "/graphql/.*/HomeTimeline" wait: 8000 - select: "data.home.home_timeline_urt.instructions[0].entries" - filter: "${{ item.entryId startsWith 'tweet-' }}" - map: id: "${{ item.content.itemContent.tweet_results.result.rest_id }}" text: "${{ item.content.itemContent.tweet_results.result.legacy.full_text }}" author: "${{ item.content.itemContent.tweet_results.result.core.user_results.result.legacy.screen_name }}" - limit: "${{ args.limit }}" columns: [id, author, text] ``` ### 4. YAML, quarantined (example of the CI gate) ```yaml # src/adapters/example/broken.yaml site: example name: broken description: "Endpoint retired 2026-03-01; pending repair" type: web-api transport: http strategy: public capabilities: [fetch, map] minimum_capability: http.fetch trust: public confidentiality: public quarantine: true quarantineReason: "HTTP 404 since upstream deprecated /v1/feed; needs /v2 port" pipeline: - fetch: url: "https://example.com/api/v1/feed" - map: id: "${{ item.id }}" title: "${{ item.title }}" columns: [id, title] ``` Quarantined commands show up in `unicli list` with a `[quarantined]` tag, are skipped by `unicli test`, and emit an informative error envelope when invoked directly. The `quarantineReason` is free-form text shown in `unicli doctor`. ### 5. YAML, Visual pipeline (computer-use agent transport) ```yaml # src/adapters/figma/click-through.yaml site: figma name: click-through description: "Click a canvas element by natural-language description" type: browser transport: visual strategy: ui capabilities: [visual_snapshot, visual_click, visual_wait, visual_ask, assert] minimum_capability: visual.snapshot trust: public confidentiality: internal quarantine: false args: - { name: target, type: string, required: true, positional: true } - { name: backend, type: string, default: "anthropic" } pipeline: - visual_backend: name: "${{ args.backend }}" - visual_snapshot: {} - visual_ask: prompt: "Find the UI element matching: ${{ args.target }}" returns: { ref: string } - visual_click: ref: "${{ vars.ref }}" - visual_wait: for: "idle" timeout: 3000 - assert: url_contains: "/edited" columns: [ok, url] ``` Visual commands are expensive because screenshot and LLM inference cost scales with backend complexity. Do not default to Visual when a `cdp-browser` adapter is feasible; the dispatcher will warn if a Visual command could have been expressed as intercept. --- ## Troubleshooting | Symptom | Likely cause | Fix | | --------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | `Unknown step: ...` at load time | Step name typo or step not registered | Check `src/engine/steps/` for supported names. | | `Adapter schema v2 violation: missing minimum_capability` | Pre-v2 YAML not migrated | Run `unicli migrate schema-v2 src/adapters/SITE/CMD.yaml`. | | `Forbidden: step X not in capabilities` | Pipeline uses a step not declared in `capabilities` | Add the step name to `capabilities`, or drop the step. | | `Strategy 'legacy-xyz' unknown` | Typo or dropped strategy | Consult the Strategy migration table; `legacy-xyz` is probably replaced by a named transport. | | `HTTP 403 Forbidden` on cookie strategy | Cookie file stale | `unicli auth setup SITE` to re-authenticate; run `unicli repair SITE/CMD` for directed patch suggestions. | | `Interception timed out after 8000ms` | Selector/URL pattern changed upstream | Inspect page network panel, update the `pattern` in `intercept` step, re-run. | | `visual_backend: remote not configured` | Visual backend endpoint or API key is missing | Set `VISUAL_BACKEND_ENDPOINT` and `VISUAL_BACKEND_API_KEY`, or disable visual fallback. | | `quarantine: true` but command still tries to run | You called the command directly; quarantine only affects CI + `unicli test` | Remove `quarantine` once repaired, or run `unicli repair SITE/CMD` to auto-patch + lift the flag. | | `trust: user` adapter refuses to run | CI safety gate rejects user-trust adapters when `UNICLI_TRUST_FLOOR=public` | Set `trust: public` and get the file reviewed, or run with `UNICLI_TRUST_FLOOR=user` locally. | For anything not on this list, `unicli doctor` prints the relevant diagnostics. If that does not resolve the issue, open an issue with the full stderr envelope — the `adapter_path` / `step` / `action` / `suggestion` fields are what we need to help. --- ## See also - `docs/reference/pipeline.md` — full step catalog with examples. - `src/core/schema-v2.ts` — the authoritative Zod schema. - `src/adapters/` — committed adapters to read as working examples. _Document version: v2. Last updated 2026-04-25._ --- # Page: Pipeline Steps Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/pipeline Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/pipeline.md # Pipeline Steps - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/pipeline - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/pipeline.md - Section: Reference - Parent: Reference (/reference/) Uni-CLI adapters execute a sequence of pipeline steps. Each step performs one action: fetch data, transform it, interact with a browser, or control execution flow. The current registry has 103 step names; the table below lists the common author-facing families. ## Overview | Category | Common steps | | --------- | ------------------------------------------------------------------------------ | | API | fetch, fetch_text, parse_rss, html_to_md | | Transform | select, map, filter, sort, limit | | Desktop | exec, write_temp | | Browser | navigate, evaluate, click, type, wait, intercept, press, scroll, snapshot, tap | | Media | download | | Service | websocket | | Control | set, if, append, each, parallel, rate_limit | --- ## API Steps ### fetch HTTP request that returns parsed JSON. Supports GET, POST, PUT, DELETE, PATCH with automatic cookie injection, retry, and backoff. ```yaml - fetch: url: "https://api.example.com/v1/posts" method: GET # default params: page: 1 limit: 20 headers: Accept: "application/json" retry: 3 # max retries backoff: exponential # linear | exponential ``` POST with a JSON body: ```yaml - fetch: url: "https://api.example.com/v1/search" method: POST body: query: "${{ args.query }}" filters: type: "article" ``` Template expressions (`${{ ... }}`) are evaluated at runtime. They can reference `args`, `item`, `data`, and `steps`. ### fetch_text HTTP request that returns raw text instead of parsed JSON. Useful for HTML pages, RSS feeds, plain text APIs. ```yaml - fetch_text: url: "https://example.com/feed.xml" ``` The response body is stored as a string in `ctx.data`. ### parse_rss Parses RSS or Atom XML feed into an array of items. Typically follows a `fetch_text` step. ```yaml - fetch_text: url: "https://example.com/feed.xml" - parse_rss: fields: [title, link, pubDate, description] ``` Each item gets normalized fields: `title`, `link`, `pubDate`, `description`, `content`. ### html_to_md Converts HTML content in `ctx.data` to Markdown using Turndown. Useful after `fetch_text` on web pages. ```yaml - fetch_text: url: "https://example.com/article/123" - html_to_md: ``` No configuration needed. The entire `ctx.data` string is converted. --- ## Transform Steps ### select Navigate into a JSON path. Replaces `ctx.data` with the value at the given path. ```yaml - select: "data.items" ``` Supports dot notation for nested objects: ```yaml - select: "response.data.articles[0].content" ``` ### map Transform each item in an array. The result is a new array with only the mapped fields. ```yaml - map: title: "${{ item.title }}" author: "${{ item.user.name }}" score: "${{ item.votes }}" url: "https://example.com/post/${{ item.id }}" ``` Template expressions inside `map` have access to `item` (current element), `index`, `data` (full array), and `args`. ### filter Keep items that match a condition. The expression is evaluated for each item. ```yaml - filter: "item.score > 100" ``` Supports standard comparison operators: ```yaml - filter: "item.type == 'article' && item.published == true" ``` ### sort Sort an array by a field. Ascending by default. ```yaml - sort: by: "score" order: desc # asc | desc ``` ### limit Cap the number of results. Accepts a number directly or as a config object. ```yaml - limit: 20 ``` Or with offset: ```yaml - limit: count: 20 offset: 10 ``` --- ## Desktop Steps ### exec Run a subprocess command. Captures stdout and optionally parses it as JSON. ```yaml - exec: command: "ffprobe" args: [ "-v", "quiet", "-print_format", "json", "-show_format", "${{ args.file }}", ] parse: json # parse stdout as JSON ``` With environment variables: ```yaml - exec: command: "blender" args: ["--background", "--python", "${{ steps.write_temp.path }}"] env: BLENDER_USER_SCRIPTS: "/path/to/scripts" ``` With stdin: ```yaml - exec: command: "jq" args: [".data.items"] stdin: "${{ data }}" ``` With file output (read result from a file instead of stdout): ```yaml - exec: command: "magick" args: ["convert", "${{ args.input }}", "-resize", "800x", "/tmp/out.png"] output_file: "/tmp/out.png" ``` ### write_temp Create a temporary file with the given content. Returns the file path in `steps.write_temp.path`. ```yaml - write_temp: ext: ".py" content: | import bpy bpy.ops.render.render(write_still=True) print("done") - exec: command: "blender" args: ["--background", "--python", "${{ steps.write_temp.path }}"] ``` Useful for tools that accept script files (Blender Python, GIMP Script-Fu, Inkscape actions). --- ## Browser Steps All browser steps require a running Chrome instance (via `unicli browser start` or the daemon). ### navigate Navigate Chrome to a URL. Waits for the page to load. ```yaml - navigate: url: "https://example.com/page" waitUntil: networkidle # load | domcontentloaded | networkidle settleMs: 2000 # additional wait after load event ``` Short form: ```yaml - navigate: "https://example.com/page" ``` ### evaluate Execute JavaScript in the page context. Returns the evaluation result. ```yaml - evaluate: "document.title" ``` Multi-line scripts: ```yaml - evaluate: expression: | const items = document.querySelectorAll('.post'); return Array.from(items).map(el => ({ title: el.querySelector('h2').textContent, url: el.querySelector('a').href })); ``` ### click Click an element by CSS selector. ```yaml - click: "#submit-button" ``` With options: ```yaml - click: selector: ".menu-item:nth-child(3)" ``` ### type Type text into an input element. ```yaml - type: selector: "#search-input" text: "${{ args.query }}" submit: true # press Enter after typing ``` ### wait Wait for a condition before continuing. Accepts a time (milliseconds) or a CSS selector. ```yaml # Wait 3 seconds - wait: 3000 # Wait for an element to appear - wait: "#results-container" # Wait with timeout - wait: selector: ".loaded" timeout: 10000 ``` ### intercept Capture network requests made by the page. Uni-CLI intercepts both `fetch()` and `XMLHttpRequest` calls using a stealthy dual interceptor that avoids detection. ```yaml - intercept: pattern: "**/api/v1/feed" trigger: "scroll:down" # action that triggers the request timeout: 10000 # max wait for matching request select: "data.items" # extract from response JSON ``` Trigger types: | Trigger | Action | | ---------------- | ----------------------------------- | | `navigate:URL` | Navigate to URL and capture | | `scroll:down` | Scroll down to trigger lazy loading | | `click:SELECTOR` | Click element to trigger request | | `wait:MS` | Wait passively for the request | ### press Press a keyboard key with optional modifiers. ```yaml - press: "Enter" ``` With modifiers: ```yaml - press: key: "a" modifiers: ["Meta"] # Cmd+A on macOS ``` ### scroll Scroll the page in a direction, to a specific element, or auto-scroll to load all content. ```yaml # Scroll direction - scroll: "down" # down | up | bottom | top # Auto-scroll (load all lazy content) - scroll: auto: true maxScrolls: 20 delay: 500 ``` ### snapshot Generate a DOM accessibility tree snapshot. Returns a text representation of the page structure with interactive element references. ```yaml - snapshot: interactive: true # include ref numbers for interactive elements compact: true # minimal output ``` The snapshot output includes `[ref=N]` markers on interactive elements. These refs can be used with the `operate` command for precise interaction. ### tap Vue Store Action Bridge. Triggers a Pinia or Vuex store action and captures the resulting network request. ```yaml - tap: store: "useMainStore" # Pinia store name action: "fetchPosts" # action to call args: [{ page: 1 }] # action arguments capture: "**/api/posts" # network pattern to capture select: "data.list" # extract from response ``` This is useful for Vue-based SPAs where the data loading is triggered by store actions rather than direct API calls. --- ## Media Steps ### download Download files via HTTP or yt-dlp. Supports batch downloads, skip-existing, and progress tracking. ```yaml - download: url: "${{ item.video_url }}" dir: "~/Downloads/videos" filename: "${{ item.title }}" skip_existing: true ``` Batch download from an array: ```yaml - download: field: "url" # field containing the URL in each item dir: "~/Downloads/images" type: image ``` yt-dlp integration (auto-detected for video platforms): ```yaml - download: url: "${{ item.url }}" dir: "~/Downloads" type: video # uses yt-dlp when available ``` Each item in the result gets a `_download` field with status, path, size, and duration. --- ## Service Steps ### websocket Connect to a WebSocket server, send a message, and wait for a matching response. Supports OBS WebSocket authentication. ```yaml - websocket: url: "ws://localhost:4455" auth: obs # OBS WebSocket auth handshake send: op: 6 d: requestType: "GetSceneList" requestId: "1" receive: match: { "d.requestId": "1" } timeout: 5000 ``` Without auth: ```yaml - websocket: url: "ws://localhost:8080/events" send: { type: "subscribe", channel: "updates" } receive: match: { type: "data" } ``` --- ## Control Steps ### set Set a variable in the pipeline context. Useful for computed values or constants. ```yaml - set: base_url: "https://api.example.com" page_size: 20 ``` Variables are accessible via `${{ vars.base_url }}` in subsequent steps. ### if Conditional branching. Execute different pipeline branches based on a condition. ```yaml - if: "args.format == 'video'" then: - fetch: url: "https://api.example.com/videos" - select: "data.videos" else: - fetch: url: "https://api.example.com/articles" - select: "data.articles" ``` ### append Append the current `ctx.data` to an accumulator. Useful in loops for collecting results. ```yaml - append: "results" ``` The accumulated data is available at `${{ vars.results }}`. ### each Iterate over an array, executing a sub-pipeline for each item. Supports parallel execution. ```yaml - each: parallel: 5 # max concurrent pipeline: - fetch: url: "https://api.example.com/item/${{ item.id }}" - select: "data" ``` Sequential (default): ```yaml - each: pipeline: - fetch: url: "https://api.example.com/item/${{ item }}" ``` ### parallel Execute multiple pipeline branches concurrently and merge results. ```yaml - parallel: - pipeline: - fetch: { url: "https://api.example.com/hot" } - select: "data.items" - pipeline: - fetch: { url: "https://api.example.com/new" } - select: "data.items" merge: concat # concat | zip | object ``` ### rate_limit Pause execution to respect rate limits. Blocks until a token is available. ```yaml - rate_limit: domain: "api.example.com" rpm: 30 # requests per minute (default: 60) ``` Place this step before `fetch` calls to rate-limited APIs. The rate limiter is shared across all adapters for the same domain. --- ## Template Expressions All step configurations support template expressions with the syntax `${{ expression }}`. ### Available Variables | Variable | Description | Available In | | -------- | ----------------------------------------- | -------------------- | | `args` | Command-line arguments | All steps | | `data` | Current pipeline data | All steps | | `item` | Current item (in `map`, `filter`, `each`) | Iteration steps | | `index` | Current iteration index | `map`, `each` | | `steps` | Results from named steps | After the named step | | `vars` | Variables set with `set` | After `set` | | `env` | Environment variables | All steps | ### Filters Template expressions support pipe filters: ```yaml - map: title: "${{ item.title | truncate:50 }}" date: "${{ item.created_at | date:'YYYY-MM-DD' }}" slug: "${{ item.title | slugify }}" ``` --- # Page: Exit Codes Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/exit-codes Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/exit-codes.md # Exit Codes - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/exit-codes - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/exit-codes.md - Section: Reference - Parent: Reference (/reference/) Uni-CLI uses exit codes from `sysexits.h` — the UNIX standard for machine-parseable process exit status. Every exit code tells an AI agent exactly what kind of failure occurred and what to do next. ## Code Reference | Code | Constant | Meaning | Agent Response | | ---- | --------------------- | ----------------------------------- | ---------------------------------------------- | | 0 | `SUCCESS` | Command succeeded | Use the data from stdout | | 1 | `GENERIC_ERROR` | Unclassified error | Read stderr JSON for details | | 2 | `USAGE_ERROR` | Bad arguments or syntax | Fix the command invocation | | 66 | `EMPTY_RESULT` | No data returned | Try different parameters or query | | 69 | `SERVICE_UNAVAILABLE` | Target site is down | Retry later | | 75 | `TEMP_FAILURE` | Temporary failure | Retry with exponential backoff | | 77 | `AUTH_REQUIRED` | Authentication or permission needed | Run `unicli auth setup SITE` or inspect policy | | 78 | `CONFIG_ERROR` | Adapter misconfigured | Read and fix the YAML adapter | ## Code 0 — Success The command completed and produced output. Data is on stdout in the selected envelope format. ```bash unicli hackernews top echo $? # 0 ``` ## Code 1 — Generic Error An error that does not fit other categories. Check stderr for a structured error envelope: ```bash unicli example broken 2>/tmp/err.json echo $? # 1 cat /tmp/err.json ``` ```json { "error": "unexpected_response", "adapter_path": "/path/to/adapter.yml", "step": 0, "action": "fetch", "message": "Expected JSON, got HTML" } ``` ## Code 2 — Usage Error The command was invoked incorrectly — missing required arguments, unknown flags, or invalid syntax. ```bash unicli hackernews # Error: missing command. Available: top, new, ask, show, jobs, ... echo $? # 2 ``` Agent action: fix the command syntax. Run `unicli list SITE` to see available commands and arguments. ## Code 66 — Empty Result The command executed successfully against the API, but the result set is empty. This is not an error — the query simply matched nothing. ```bash unicli reddit search --subreddit "tinysub" --query "xyzzy" echo $? # 66 ``` Agent action: try broader search terms, different parameters, or a different time range. The adapter and API are working correctly. ## Code 69 — Service Unavailable The target service is unreachable. The site may be down, blocked, or experiencing an outage. ```bash unicli example fetch-data echo $? # 69 ``` Agent action: retry after a delay. If the failure persists, check if the site is globally down or if the network is restricted. ## Code 75 — Temporary Failure A transient error — rate limiting, temporary server error, or network glitch. The built-in retry mechanism has already attempted retries and exhausted them. ```bash unicli twitter timeline echo $? # 75 ``` Agent action: wait and retry the entire command. Consider adding a `rate_limit` step to the adapter if rate limiting is the recurring cause. ## Code 77 — Auth Or Permission Required The command needs authentication or was stopped by local permission policy. Authentication failures usually need fresh cookies. Permission failures usually name the matching deny rule in the error envelope. ```bash unicli bilibili feed echo $? # 77 ``` Agent action: ```bash unicli auth setup bilibili # Interactive: opens Chrome login unicli auth check bilibili # Verify cookies are valid unicli bilibili feed # Retry ``` For `permission_denied`, inspect `error.suggestion` and the local `~/.unicli/permission-rules.json` file. ## Code 78 — Config Error The adapter YAML is invalid or misconfigured. This typically means a selector changed, a URL is wrong, or the pipeline has a structural error. ```bash unicli example broken-adapter echo $? # 78 ``` Agent action: read the adapter YAML at the path in the stderr error JSON, fix the configuration, and retry. See the [Self-Repair guide](/guide/self-repair) for the full workflow. ## Programmatic Handling ### Shell Script ```bash unicli bilibili feed --json case $? in 0) echo "Success" ;; 66) echo "No results" ;; 77) unicli auth setup bilibili ;; 75) sleep 10 && unicli bilibili feed --json ;; *) echo "Unexpected error" ;; esac ``` ### AI Agent (pseudocode) ``` result = run("unicli bilibili feed --json") if result.exit_code == 0: return parse_json(result.stdout) if result.exit_code == 77: run("unicli auth setup bilibili") return retry() if result.exit_code == 78: error = parse_json(result.stderr) adapter = read_file(error.adapter_path) fix = apply_suggestion(adapter, error.suggestion) write_file(error.adapter_path, fix) return retry() if result.exit_code in [69, 75]: wait(exponential_backoff) return retry() ``` ## Source Definition Exit codes are defined in `src/types.ts`: ```typescript export const ExitCode = { SUCCESS: 0, GENERIC_ERROR: 1, USAGE_ERROR: 2, EMPTY_RESULT: 66, SERVICE_UNAVAILABLE: 69, TEMP_FAILURE: 75, AUTH_REQUIRED: 77, CONFIG_ERROR: 78, } as const; ``` These values follow the BSD `sysexits.h` convention, ensuring compatibility with UNIX toolchains and CI/CD systems that interpret exit codes programmatically. --- # Page: Maintenance Tools Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/maintenance Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/maintenance.md # Maintenance Tools - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/maintenance - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/maintenance.md - Section: Reference - Parent: Reference (/reference/) This page groups the small maintenance surfaces that used to be split across separate docs pages. Use it when verifying agent context quality, adapter regressions, or generated skill exports. ## Context Lint `npm run lint:context` runs `scripts/lint-context.sh` against agent-facing context such as `AGENTS.md`, local skills, workflows, and docs. It catches stale paths, missing verification instructions, and weak operational context before an agent relies on it. Resolution order: 1. `agent-lint` on `PATH`. 2. A vendored local build, when present. 3. Soft skip with a warning. The script does not fetch from the network. Commands: ```bash npm run lint:context UNICLI_LINT_THRESHOLD=80 npm run lint:context UNICLI_LINT_DISABLE=1 npm run verify ``` Threshold checks require `jq`. Without it, the script prints the raw output and exits 0. ## Eval Harness `unicli eval` runs YAML-defined regression suites against adapters and reports `SCORE=N/M`. User-local evals live under `~/.unicli/evals/`. Commands: ```bash unicli eval list unicli eval run smoke/hackernews unicli eval run --all smoke/ unicli eval ci --since 7d unicli eval run smoke/hackernews --json ``` Eval file shape: ```yaml name: hackernews-smoke adapter: hackernews description: Hacker News public-API smoke test cases: - command: top args: limit: 5 judges: - { type: arrayMinLength, min: 5 } - { type: nonEmpty } ``` Judges: | Type | Fields | Passes when | | ---------------- | ----------------------------- | ------------------------------------------ | | `exitCode` | `equals: 0` | The CLI exit code matches. | | `nonEmpty` | none | Raw output is non-whitespace. | | `matchesPattern` | `pattern: "regex"` | Raw output matches the regex. | | `contains` | `field?: "json.path", value:` | The resolved value contains the substring. | | `arrayMinLength` | `path?: "json.path", min:` | The resolved value is an array of `min`+. | Field paths use dotted syntax with array subscripts: ```text data.items[0].title results[3].author ``` ## Skill Export `unicli skills export` emits one `SKILL.md`-compatible file per adapter command. Use it when an agent runtime can ingest local skills more cheaply than it can call discovery for every task. Commands: ```bash unicli skills export unicli skills export --out /tmp/unicli-skills unicli skills publish unicli skills publish --to ~/.cursor/skills/uni-cli/ unicli skills catalog unicli skills catalog --out /tmp/catalog.json ``` Generated skill shape: ````markdown --- name: hackernews-top description: Hacker News top stories when_to_use: When you need the current top items from hackernews. command: unicli hackernews top source: unicli --- ## What it does Hacker News top stories. ## How to call it ```bash unicli hackernews top --limit 20 ``` ```` Use `-f json` when the caller needs JSON. Errors use the normal v2 envelope and include the failing adapter path, step, and suggestion. `unicli skills catalog` writes `docs/adapters-catalog.json` or a custom output path. Agents can ingest the catalog once and route directly without repeated discovery calls. ## Repo Skills Committed skills live under `skills//SKILL.md`. The loader checks repo skills first, then `$HOME/.unicli/skills`, then the XDG data directory. When a skill declares `depends-on`, dependency resolution loads those skills before the requesting skill. The core `unicli` skill depends on `talk-normal`, so documentation and user-facing copy should load the concise writing rules before drafting text. --- # Page: Plugin Authoring Canonical: https://olo-dot-io.github.io/Uni-CLI/PLUGIN Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/PLUGIN.md # Plugin Authoring - Canonical: https://olo-dot-io.github.io/Uni-CLI/PLUGIN - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/PLUGIN.md - Section: Reference - Parent: Reference (/reference/) This document is the stability contract for `@zenalexa/unicli` subpath imports and describes the supported ways to extend Uni-CLI from a third-party package. Plugins let you register custom pipeline steps, transports, and adapters without forking the project. The surface is a small, versioned set of subpath imports — pick the ones you need, import them, and avoid the non-exported implementation details. --- ## 1. Stability contract Uni-CLI exposes 24 subpaths from `package.json` `exports`. Each subpath is labelled **Stable**, **Beta**, or **Experimental**. The label governs how quickly we may break the API. | Subpath | Source | Status | | ---------------------------------------- | --------------------------------------- | ------------ | | `@zenalexa/unicli` | `src/main.ts` | Stable | | `@zenalexa/unicli/registry` | `src/registry.ts` | Stable | | `@zenalexa/unicli/errors` | `src/errors.ts` | Stable | | `@zenalexa/unicli/types` | `src/types.ts` | Stable | | `@zenalexa/unicli/output` | `src/output/formatter.ts` | Stable | | `@zenalexa/unicli/engine` | `src/engine/executor.ts` | Stable | | `@zenalexa/unicli/engine/registry` | `src/engine/step-registry.ts` | Stable | | `@zenalexa/unicli/transport` | `src/transport/bus.ts` | Stable | | `@zenalexa/unicli/transport/http` | `src/transport/adapters/http.ts` | Stable | | `@zenalexa/unicli/protocol/mcp` | `src/mcp/schema.ts` | Stable | | `@zenalexa/unicli/protocol/acp` | `src/protocol/acp.ts` | Stable | | `@zenalexa/unicli/pipeline` | alias of `engine` | Stable | | `@zenalexa/unicli/download` | `src/engine/download.ts` | Stable | | `@zenalexa/unicli/engine/steps` | `src/engine/steps/index.ts` | Beta | | `@zenalexa/unicli/transport/visual` | `src/transport/adapters/visual.ts` | Beta | | `@zenalexa/unicli/transport/desktop-ax` | `src/transport/adapters/desktop-ax.ts` | Beta | | `@zenalexa/unicli/transport/subprocess` | `src/transport/adapters/subprocess.ts` | Beta | | `@zenalexa/unicli/transport/cdp-browser` | `src/transport/adapters/cdp-browser.ts` | Beta | | `@zenalexa/unicli/protocol/skill` | `src/protocol/skill.ts` | Beta | | `@zenalexa/unicli/registry-v2` | `src/core/registry.ts` | Experimental | | `@zenalexa/unicli/browser/cdp` | `src/browser/cdp-client.ts` | Experimental | | `@zenalexa/unicli/browser/page` | `src/browser/page.ts` | Experimental | | `@zenalexa/unicli/browser/daemon` | `src/browser/daemon-client.ts` | Experimental | | `@zenalexa/unicli/browser/utils` | `src/browser/dom-helpers.ts` | Experimental | **Stable** — Breaking changes require a major bump and a deprecation warning for at least one full release prior. **Beta** — Shape of the module is likely right, but concrete types, field names, and handler signatures can shift in any minor release. Safe to depend on; pin to an exact minor to avoid surprise upgrades. **Experimental** — Low-level modules we export so the plugin ecosystem can prototype. May break in any release, including patch releases. Use at your own risk and prefer stable alternatives where they exist. --- ## 2. Versioning policy Uni-CLI follows Semantic Versioning (`MAJOR.MINOR.PATCH`). Applied to exports: - **Stable subpath, breaking change** → requires a `MAJOR` bump, a deprecation warning emitted at least one `MINOR` prior, and a changelog entry under "Breaking changes". - **Beta subpath, breaking change** → allowed in any `MINOR`. A changelog entry is still required. - **Experimental subpath, breaking change** → allowed in any release, including `PATCH`. No changelog entry required (but encouraged). - **Adding a new subpath** → `MINOR` bump, never `PATCH`. - **Removing a subpath** → only during a `MAJOR` bump with a deprecation window. The CI gate `scripts/check-exports-count.ts` enforces a floor of 20 subpaths so we never silently amputate the plugin surface. --- ## 3. Writing a plugin The simplest plugin registers a custom pipeline step and ships as an ESM side-effect import. Consumers add one import to their YAML runner host (or to a wrapper script) and the step becomes callable. ```ts // my-plugin/src/index.ts import { registerStep } from "@zenalexa/unicli/engine/registry"; registerStep("reverse", async (ctx, _config) => { return { ...ctx, data: Array.isArray(ctx.data) ? [...ctx.data].reverse() : ctx.data, }; }); ``` Then in any YAML adapter: ```yaml site: example name: demo type: web-api strategy: public pipeline: - fetch: { url: "https://example.com/api/items" } - select: { path: "data" } - reverse: {} columns: [title] ``` See `examples/plugin-example/` in the repository for a complete working template including `package.json`, `tsconfig.json`, and a README. --- ## 4. Loading plugins Uni-CLI does not auto-discover third-party plugins. You load them via Node's preload flag: ```bash node --import @zenalexa/my-plugin $(which unicli) example demo ``` Or for a script-only host, pure ESM side-effect import works: ```ts import "@zenalexa/my-plugin"; import { runPipeline } from "@zenalexa/unicli/engine"; await runPipeline([{ fetch: { url: "https://example.com" } }, { reverse: {} }]); ``` A first-class `--plugin` CLI flag is tracked for a future minor release. Until then, preload-import is the supported pattern. --- ## 5. Plugin-side browser daemon spawn pattern Browser-aware plugins should reuse the Uni-CLI daemon contract instead of opening their own ad hoc Chrome bridge. The supported pattern is: 1. Allocate a daemon port per profile or workspace. 2. Start the browser daemon from the plugin host process or dashboard. 3. Export `UNICLI_DAEMON_PORT=` before invoking Uni-CLI commands. 4. Use `@zenalexa/unicli/browser/daemon` for `fetchDaemonStatus`, `sendCommand`, `listSessions`, or `bindCurrentTab` when the plugin needs direct daemon access. CLI users can route a single command to a non-default daemon with: ```bash unicli browser --daemon-port 19826 status unicli browser --daemon-port 19826 upload 12 ./fixture.png ``` Plugins that still need legacy daemon compatibility may set `UNICLI_COMPAT_DAEMON_PORT`; Uni-CLI will honor it when `UNICLI_DAEMON_PORT` is not set. New plugins should prefer the Uni-CLI environment variable and the `X-Unicli` daemon header. The daemon protocol is intentionally isolated from plugin loading: plugins may spawn and supervise the daemon, but they must not open sockets or launch Chrome during module import. Perform those actions from an explicit command, dashboard action, or worker process. --- ## 6. Allowed operations per subpath One-line summary of what a plugin can legitimately do with each subpath. - `registry` — register v1 adapters via `cli({...})`. - `registry-v2` — register v2 adapters via the schema-typed API (experimental). - `errors` — catch `PipelineError`, `NoTransportForStepError`; construct envelope errors. - `types` — reuse `PipelineStep`, `AdapterType`, `Strategy`, `ExitCode` etc. in plugin types. - `output` — format plugin-produced rows via the shared `formatter` (table/json/yaml/csv/md). - `engine` — call `runPipeline` from external hosts; catch `PipelineError`. - `engine/registry` — `registerStep`, `getStep`, `listSteps`; this is the primary extension point. - `engine/steps` — reference built-in step handlers (beta — handler signatures may move). - `transport` — register custom `TransportAdapter` instances on the shared bus. - `transport/http` — compose on top of the HTTP transport (retries, cookies, CSRF). - `transport/cdp-browser` — access CDP-backed browser transport for custom steps. - `transport/subprocess` — spawn helper binaries under the subprocess transport. - `transport/desktop-ax` — drive native UI via the macOS AX / Windows UIA bridge. - `transport/visual` — access the Computer-Use Agent transport surface. - `browser/cdp` — low-level raw CDP client (experimental — prefer `browser/page`). - `browser/page` — high-level `BrowserPage` API (navigate, click, evaluate, snapshot). - `browser/daemon` — talk to the standalone daemon HTTP+WS server. - `browser/utils` — shared DOM helpers for snapshot normalisation and ref resolution. - `protocol/mcp` — MCP schema builders (`buildInputSchema`, `buildToolName`, etc.). - `protocol/acp` — embed an ACP server that reuses the Uni-CLI pipeline runner. - `protocol/skill` — load and validate SKILL.md packs. - `download` — enqueue downloads through the shared `download` step runtime. - `pipeline` — alias of `engine`; prefer whichever name reads better in your codebase. --- ## 7. Forbidden These are not supported. A plugin that relies on any of them will break without notice: - **Deep imports into non-exported paths.** `@zenalexa/unicli/dist/engine/runtime.js` or any path not listed in `package.json` `exports` is private. - **Importing symbols prefixed with `_`.** These are test-only or transitional helpers (e.g. `_resetTransportBusForTests`) and can change or disappear in any release, including patch releases. Calling the public `getBus().register(...)` API is the supported way to extend the transport surface. - **Monkeypatching exports.** Rewriting `PipelineError.prototype` or overwriting an existing step via a direct `Map.set` on a non-exported registry is unsupported — call `registerStep` instead, which performs the right validation. - **Depending on non-exported types that leak through public modules.** If a type is only visible because TypeScript structurally surfaces it, treat it as private. Import only from named, documented type exports. - **Side effects beyond registration.** A plugin must not open sockets, spawn processes, or write files at import time. Register handlers; let the host CLI invoke them. If you need something in the Forbidden list, open an issue describing the use case. Most requests resolve with a new stable export, not a private hook. --- # Page: Release Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/release Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/release.md # Release - Canonical: https://olo-dot-io.github.io/Uni-CLI/reference/release - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/reference/release.md - Section: Reference - Parent: Reference (/reference/) This page is the public release policy and operator reference for Uni-CLI. Releases are maintainer-gated. There is no promised calendar cadence: the version line depends on community feedback, development substance, verification results, and the maintainer's call on whether the next shipment is patch, minor, major, or no release yet. ## Authority Only the maintainer decides when a release is cut. Automation prepares and verifies a candidate; it does not decide that a release should exist. | Path | Workflow | Behavior | | ----------------- | --------------------------------------------------- | --------------------------------------------------------------------------- | | Candidate prepare | local maintainer commit on `main` | Apply version metadata, changelog, docs, generated assets, and tests. | | npm publish | `.github/workflows/release.yml` on pushed `v*` tags | Check out the tag, verify the package, publish to npm with provenance. | | Manual dispatch | `.github/workflows/release.yml` with `tag=vX.Y.Z` | Re-run the same GitHub publish path for an existing tag if tag push missed. | If the maintainer has not explicitly asked to release, development stays under `[Unreleased]` in `CHANGELOG.md` plus `.changeset/*.md` files. ## Versioning Uni-CLI follows semver. The `0.225.1` line is a patch release candidate because it repairs the site-availability and browser-substrate verification path without breaking the CLI/package shape. The `0.225.0` line introduced the universal computer-control platform model; `0.225.1` makes that model operationally auditable by separating real adapter failures from auth, platform, browser, local-daemon, write/destructive, quarantined, and caller-input-required paths. | Change | Version bump | | ---------------------------------------------------------------------------------------- | ------------ | | Adapter fixes, docs, tests, small command additions | Patch | | Product-frame rewrite, new transport, new protocol surface, broad output behavior change | Minor | | Explicit stable-major compatibility contract or breaking behavior | Major | Do not bump `package.json`, run `changeset version`, tag, publish, or create a GitHub Release until the maintainer explicitly says to release. Before any release, the macOS dynamic discovery work from `codex/macos-dynamic-actions` must already be audited, reviewed, and merged to `main`. `npm run verify:release-mainline`, `npm run release`, and `npm run release:check` enforce this by requiring release commands to run from `main`, requiring commit `33bafa6087bf81c9b9df5cc0e996e79f6e28f030` to be an ancestor of `HEAD`, and checking that the first-class `macos app-actions` and `macos automation-smoke` manifest entries are present before publish. ## Historical Release Audit The public git/tag history starts in 2026 with the `0.200.x` line. For the `0.225.1` release, the release was checked against `CHANGELOG.md`, local tags, npm registry state, release automation, adapter health, real E2E workflows, and the current site-availability sweep. Release facts: - npm registry state before tagging: `@zenalexa/unicli@latest` is `0.225.0`; - release tag target: `v0.225.1`; - release metadata passes `npm run release:check -- --strict-codename`; - site availability classifies 313 sites and 1784 adapter commands with `fail=0`; - representative safe site probes report `ok=64`, `environment_skip=12`, and `no_auto_probe=237`; - adapter health reports `ok=160`, `fail=0`, `skip=1624`, and `skip_env_missing=64`; - real E2E reports 43 passed workflows, 0 failed workflows, and 1 skipped workflow for an arXiv rate limit; - built-CLI social smoke passes for Twitter/X, Xiaohongshu, Reddit, YouTube, Bilibili, and Weibo. | Release line | Historical role | Audit lesson for `0.225.1` | | ------------ | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `0.200.0` | First Vostok public adapter platform with build manifest and self-repair architecture. | A release must expose a machine-readable surface, not just prose. | | `0.208.0` | Skills export, MCP gateway, eval catalog, usage ledger, operate/observe, and documented 4-reviewer hardening. | Review findings must be explicit and fixed before tag, especially security and release wiring. | | `0.213.0` | GA for engine rigor, split executor/runtime/steps, schema-v2 adapters, and v2 `AgentEnvelope`. | Stable behavior contracts outrank marketing claims. | | `0.217.0` | Execution-substrate framing with operation policy, run recording, browser evidence, and agent backend matrix. | Product framing can become too small as real control surfaces expand. | | `0.218.0` | Cross-platform browser cookie import and auth diagnostics. | Auth and platform boundaries must be explicit; unsupported paths must fail honestly. | | `0.221.0` | Patent and scholarly verticals with typed records and source routing. | Vertical breadth matters only when records, provenance, and tests stay coherent. | | `0.222.0` | Local computer-use and compute capture entered the release surface. | Desktop/computer control is a core substrate, not a sidecar demo. | | `0.224.0` | Callable architecture audit/tree and live registry-backed search caching. | Architecture audit must not omit core control commands or reduce the product to adapter lifecycle. | | `0.225.0` | Universal computer-control platform framing with intent, policy, action substrates, evidence, delivery, repair. | Product claims need live health gates, not catalog counts alone. | `0.225.1` is a patch release because it hardens availability diagnostics, browser-substrate repair, and real workflow verification while preserving the public command/package contract. ## Changesets Every PR that touches production source should add one changeset: ```bash npm run changeset ``` The release candidate workflow runs: ```bash npx changeset version npm run verify ``` The repository also verifies that source changes did not slip through without a changeset: ```bash npm run verify:changesets ``` ## Release Labels Every tagged release must carry a final spaceflight label: ```text Program · Astronaut ``` Examples: `Vostok · Gagarin`, `Mercury · Glenn`, `Apollo · Lovell`. Current program map: | Version range | Program | | ------------- | ------- | | `0.1xx` | Sputnik | | `0.200-0.213` | Vostok | | `0.216+` | Apollo | Rules: - Development notes may say `Astronaut TBD`. - Release headings, README footers, tags, and GitHub Releases must never use `TBD`, `TODO`, `Unreleased`, or `Next`. - The release label must be chosen before `npm run release`, `npm version`, tagging, npm publish, or GitHub Release creation. - Use the exact middle-dot separator: `Program · Astronaut`. Automation enforces this: ```bash RELEASE_CODENAME="Vostok · Gagarin" npm run release npm run release:check -- --strict-codename ``` For the 0.225 line, the release label format is unchanged. The current release candidate label is `Apollo · Conrad`. ## Substantive Commits Release automation filters out bot-only dependency and CI maintenance commits: - `chore(deps)` - `chore(deps-dev)` - `chore(ci)` - `build(deps)` - `build(deps-dev)` Everything else counts as substantive: `feat`, `fix`, `refactor`, `perf`, `docs`, `test`, `build`, `style`, `revert`, and untyped commits. The filter is intentionally generous because silently skipping real work is worse than requiring a maintainer decision. ## Publishing The publish workflow publishes `@zenalexa/unicli` from `.github/workflows/release.yml` when a `v*` tag is pushed. Local machines should not be treated as the npm publishing authority. A local `npm whoami` failure is not a release blocker if the candidate commit and tag can be pushed to GitHub: the real publish step runs in GitHub Actions through Trusted Publishers or the `NPM_TOKEN` fallback in the `npm-publish` environment. Release authority is scoped to the publish job: - `contents: write` creates the GitHub Release. - `id-token: write` enables npm Trusted Publishers and provenance. - The job runs in the `npm-publish` environment. Stable versions publish to `latest`. Prereleases publish to the channel named by the semver prerelease prefix, for example `0.216.0-beta.2` publishes with `--tag beta`. ## Trusted Publishers npm Trusted Publishers should be configured with this exact tuple: | Field | Value | | ------------------------------- | ------------- | | GitHub organization or username | `olo-dot-io` | | Repository name | `Uni-CLI` | | Workflow filename | `release.yml` | | Environment name | `npm-publish` | The package owner configures this once at: ```text https://www.npmjs.com/package/@zenalexa/unicli ``` After two successful OIDC publishes, delete the fallback `NPM_TOKEN` from the `npm-publish` GitHub environment. A broken binding should then fail fast with a 401 instead of silently falling back to a long-lived token. ## Manual Release To ship a release: 1. Confirm the intended version bump and release label. 2. Confirm `codex/macos-dynamic-actions` is merged to `main` with `npm run verify:release-mainline`. 3. For a product-frame release, update the historical release audit section on this page before tagging. 4. Run `npm run verify`, `npm run release:check -- --strict-codename`, `npm publish --dry-run`, and `npm run docs:check-public`. 5. Commit the release candidate to `main`. 6. Push `main`. 7. Create the release tag with `git tag vX.Y.Z`. 8. Push the tag with `git push origin vX.Y.Z`. 9. Watch **Actions → Release**. The workflow checks out the tag, verifies the package surface, publishes to npm with provenance, and creates the GitHub Release. If the tag already exists and the push event did not run or was cancelled, re-run the same publish path instead of publishing locally: ```bash gh workflow run release.yml --ref main -f tag=vX.Y.Z gh run watch --repo olo-dot-io/Uni-CLI ``` The dispatch path requires the tag to exist. It checks out that tag and fails if the tag does not match `package.json`'s `vX.Y.Z`, preventing an accidental publish from the wrong branch head. ## Local Auth Failure SOP Use this branch when the maintainer-approved release is ready but the local npm or GitHub session is unreliable: 1. Treat `npm publish --dry-run` as the local npm check. Do not run a real local `npm publish`. 2. Confirm `npm view @zenalexa/unicli version` before and after the GitHub run. 3. If `npm whoami` returns `E401`, continue with GitHub Actions; the local npm session is not used by the release workflow. 4. If `gh auth status` is healthy, push `main` and `vX.Y.Z`, or dispatch `release.yml` for an existing tag. 5. If `gh` is unhealthy but `git push` still works, push the tag with Git and use the GitHub Actions web UI to monitor or re-run **Release**. 6. If neither `gh` nor `git push` works, stop after local verification and hand off the exact commit SHA, tag name, dry-run shasum, and failed auth command. Do not publish from an unverified local workaround. ## Cancel A Release Before npm publish completes: ```bash git tag -d vX.Y.Z git push origin --delete vX.Y.Z git revert RELEASE_COMMIT_SHA --no-edit git push origin main ``` Then cancel the in-flight `release.yml` run from the Actions UI. After npm publish completes, prefer deprecation over unpublish: ```bash npm deprecate @zenalexa/unicli@X.Y.Z "see vX.Y.Z+1 for fix" ``` Then ship `vX.Y.Z+1` with the fix and document the reason in `CHANGELOG.md`. ## Escalation Open a tracking issue when release automation blocks a maintainer-approved release candidate. Include: - failing workflow link; - intended version and release label; - exact verify command that failed; - whether the blocker is changesets, tests, npm Trusted Publishers, or GitHub Actions availability. --- # Page: Architecture Canonical: https://olo-dot-io.github.io/Uni-CLI/ARCHITECTURE Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ARCHITECTURE.md # Architecture - Canonical: https://olo-dot-io.github.io/Uni-CLI/ARCHITECTURE - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ARCHITECTURE.md - Section: Explanation Uni-CLI is the universal computer-control platform for agents. The stable product primitive is not a browser session, a sandbox, a protocol server, a visual cursor, or a generated tool list. It is an operation that lets an agent control real software through a governed, observable, repairable path. The current generated operation catalog is the source of truth: **317 sites**, **1772 commands**, **1222 adapters**, **103 pipeline steps**, and **9183 tests** in v0.225.2. ## Computer-Control Thesis Vehicle assistants work because the car exposes a bounded control layer above navigation, media, climate, and driving assistance. General computers have the same shape at larger scale. Browser state, desktop apps, local tools, files, operating-system services, accessibility trees, screenshots, protocol servers, and website-specific paths are the environment. Uni-CLI is the hand agents use to control that environment. Adjacent projects usually own one concrete technical function: browser automation, a computer-use sandbox, natural-language local execution, an MCP server, or a per-application wrapper. Uni-CLI treats those as substrates. The platform boundary is larger: agent intent enters once, the system selects a controllable boundary, policy gates the effect, real software is acted on, evidence returns, failure is diagnosed, and the path is repaired or rerouted until the result is delivered. The computer-control loop is: 1. Accept human or agent intent without preloading a giant tool list. 2. Select the smallest operation boundary that can act on the target software. 3. Govern the operation through permission profile, risk, capability scope, and local policy. 4. Act through the selected substrate: API, browser, desktop, subprocess, protocol, visual, or app-specific wrapper. 5. Observe result data, context, retryability, timing, and evidence through one envelope. 6. Diagnose failure into auth, policy, missing context, upstream drift, environment trouble, or adapter defect. 7. Repair or reroute through a bounded verification command and alternatives. 8. Deliver the objective state, then expose the same operation through CLI, MCP, ACP, docs, skills, CI, and scripts. That loop is the product. The command lifecycle, YAML format, MCP gateway, browser automation, computer-use actions, and self-repair tools are internal machinery or substrates below it. ## Priority Model These roots define product semantics and must stay shared by every runtime surface. | Priority | Layer | Contract | | -------- | -------------------------- | ------------------------------------------------------------------------------------------ | | P0 | Computer-control platform | Intent, selection, governance, action, observation, diagnosis, repair/reroute, delivery | | P0 | Operation contract | Args, output, auth posture, effect, safety, capability, source path, and repair path | | P0 | Control kernel | Validate, harden, authorize, invoke a substrate, observe, and envelope | | P0 | Action substrates | HTTP, browser CDP, desktop accessibility, subprocess, visual fallback, protocols, wrappers | | P0 | Evidence and delivery loop | AgentEnvelope v2, run traces, post-state evidence, objective gates, trajectory, repair | | P1 | Discovery | `search`, `list`, `describe`, `do`, generated catalog, docs index | | P1 | Governance | Permission profiles, deny rules, approvals, effect/risk/capability metadata | | P1 | Authoring | YAML first, TypeScript escape hatch, schema-v2 lint, repair verification | | P1 | Runtime exposure | Native CLI, JSON stream, MCP, ACP, streamable HTTP, agent packs, skills export | | P2 | Broad coverage | Hundreds of site commands, vertical meta-commands, external CLI hub | | P2 | Public docs UI | Homepage, operation catalog, architecture, compute evidence demo | ## Substrate Boundary Substrate plurality is a strength only while it remains below the platform boundary. - Browser UI automation is one action substrate, not the architecture. - Computer-use sandboxing is one environment substrate, not the product category. - MCP is an exposure and protocol substrate; expanded MCP mode is opt-in. - Natural-language local execution is a useful substrate when typed command contracts and policy still hold. - Visual control is valid only when it can see, act, and verify post-state evidence. - External CLI passthrough is a bridge to mature tools, not a replacement for operation contracts. - Generated public files under `docs/public/` are build artifacts, not hand-edited architecture sources. ## Capability Matrix And Workflow Readiness `unicli architecture audit -f json` emits two catalog-derived views that keep the vehicle-assistant analogy honest without pretending every path has already passed live smoke. The `capability_matrix` groups live registry commands by the real control surface they touch: - `web`: HTTP, RSS, public/cookie/header web paths, and web target surfaces. - `browser`: CDP, browser refs, browser evidence, and browser-backed adapters. - `desktop`: installed app, accessibility, local UI, and desktop target surfaces. - `system`: operating-system state, macOS commands, local services, and system target surfaces. - `protocol`: MCP, ACP, delivery/runs/architecture control services, and service/protocol boundaries. - `bridge`: passthrough to mature external CLIs such as `gh`, `yt-dlp`, or cloud CLIs. Rows include command counts, adapter/core split, write-sensitive count, local computer-use count, source-path coverage, and representative commands. A command can appear in more than one row when it genuinely crosses surfaces, for example a browser-backed web adapter or a macOS command that controls both desktop and system state. The `workflow_readiness` table tracks the real user workflows implied by the vehicle assistant comparison: - play or inspect media; - search video platforms; - operate browser tabs; - operate installed apps; - read and write productivity state; - open or navigate to a destination. Readiness is intentionally conservative: - `cataloged` means operation contracts exist in the live catalog, with at least one action-capable command when the workflow requires action. - `partial` means the catalog has related read/discovery paths but lacks the action shape needed to claim the workflow. - `gap` means the live catalog has no matching operation path. No workflow row claims live success. Each row carries `required_next_evidence` so Step 5 capability work can turn cataloged intent into behavior evidence: run the command, capture the envelope, verify post-state, record auth/policy posture, and only then promote a capability claim. ## System Tree ```text Uni-CLI |-- Computer-control platform | |-- Intent: src/discovery/search.ts, src/commands/do.ts | |-- Select: src/core/command-contract.ts, src/registry.ts | |-- Govern: src/engine/permission-runtime.ts | |-- Act: src/engine/kernel/*, src/engine/executor.ts | |-- Observe: src/output/*, src/engine/session/* | |-- Diagnose: src/engine/delivery/*, src/output/error-map.ts | |-- Repair/reroute: src/commands/repair.ts, src/engine/repair/* | `-- Deliver/expose: src/commands/delivery.ts, src/commands/agents.ts | |-- Operation catalog | |-- Runtime registry: src/registry.ts | |-- Core catalog: src/discovery/core-catalog.ts | |-- Adapter catalog: src/adapters//.yaml or .ts | |-- Schema v2: src/core/schema-v2.ts | |-- Aliases and categories: src/discovery/aliases.ts | `-- Generated manifests: registry.json, stats.json, server.json | |-- Control kernel | |-- Compile and cache: src/engine/kernel/compile.ts | |-- Input stages: src/engine/kernel/stages.ts | |-- Execution: src/engine/kernel/execute.ts | |-- Compatibility export: src/engine/invoke.ts | |-- Args and hardening: src/engine/args.ts, src/engine/harden.ts | |-- Policy runtime: src/engine/permission-runtime.ts | `-- Output envelope: src/output/* | |-- Action substrates | |-- Web/API: src/engine/steps/fetch*.ts, src/engine/steps/parse*.ts | |-- Browser/CDP: src/browser/*, src/transport/adapters/cdp-browser.ts | |-- Desktop/OS: src/commands/compute.ts, src/compute/*, src/transport/adapters/desktop-*.ts | |-- Local tools/files: src/hub/*, src/engine/steps/exec*.ts, src/adapters/pdf/* | |-- Protocols: src/mcp/*, src/commands/acp.ts, src/protocol/* | `-- Visual fallback: src/transport/adapters/visual.ts, src/compute/visual-timeline.ts | |-- Evidence, delivery, and repair | |-- Run recording: src/engine/session/* | |-- Replay and compare: src/commands/runs.ts, src/engine/session/replay.ts | |-- Objective state: src/engine/delivery/* | |-- Operator CLI: src/commands/delivery.ts | |-- Adapter repair: src/commands/repair.ts, src/engine/repair/* | `-- Eval and probes: src/commands/eval.ts, tests/integration/* | |-- Runtime exposure | |-- Native CLI: src/cli.ts, src/main.ts, src/commands/* | |-- MCP: src/mcp/*, src/mcp/profiles/computer-use.ts | |-- ACP: src/commands/acp.ts, src/protocol/* | |-- Streamable HTTP: src/mcp/streamable-http/* | |-- Agent packs and skills: src/commands/agents.ts, scripts/build-agents.ts | `-- Public docs: docs/, docs/.vitepress/theme/* | |-- Authoring and repair machinery | |-- Loader: src/discovery/loader.ts | |-- YAML pipeline executor: src/engine/executor.ts | |-- Step registry: src/engine/step-registry.ts | |-- Built-in steps: src/engine/steps/* | |-- Health, lint, migrate, generate: src/commands/{health,lint,migrate*,generate}.ts | |-- User adapters: ~/.unicli/adapters | `-- Plugins and custom steps: src/plugin/* | `-- Verification and release |-- Unit tests: tests/unit/* |-- Adapter tests: tests/adapter/* |-- Integration tests: tests/integration/* |-- Perf tests: tests/perf/* |-- Build and stats scripts: scripts/* |-- Boundary guard: scripts/boundary-guard.ts `-- Full release gate: npm run verify ``` ## Runtime Flow ```mermaid flowchart TD user["Human or agent intent"] --> discover["search / list / describe / do"] discover --> contract["OperationContract"] contract --> policy["permission and risk policy"] policy --> kernel["control kernel"] kernel --> substrate["HTTP / CDP / accessibility / subprocess / visual / protocol"] substrate --> envelope["AgentEnvelope v2"] envelope --> evidence["run evidence + post-state"] evidence --> delivery["delivery assessment"] delivery --> done["deliver"] delivery --> repair["repair or reroute"] repair --> contract ``` The invariant is that CLI, MCP, ACP, HTTP, docs, and skills must not implement their own semantics. They resolve inputs, call the same control kernel, and render the same envelope. ## Internal Command Lifecycle The command lifecycle is internal authoring and maintenance machinery. It keeps operations inspectable and repairable, but it is below the product boundary. The public product loop remains intent -> select -> govern -> act -> observe -> diagnose -> repair/reroute -> deliver -> expose. ### 1. Create YAML is the default authoring unit because it is cheap for agents to inspect, patch, and verify. Creation paths: - `unicli init` scaffolds adapters. - `unicli record`, `explore`, `synthesize`, and `generate` discover candidate browser/API paths. - TypeScript adapters use `cli()` only when a finite YAML pipeline is the wrong tool. - Plugins and user adapters register into the same runtime registry. Creation requirements: - Declare args, output columns, target surface, capability needs, auth strategy, trust/confidentiality metadata, and repair source path. - Prefer one command per reusable user operation. - Put site-specific complexity in the adapter, not in the protocol wrappers. - Add or update tests when the command is first-class, write-capable, or used by a vertical meta-command. ### 2. Discover Discovery is a first-class runtime, not only documentation. Discovery surfaces: - `unicli search ""` for natural-language routing. - `unicli list` for inventory and filtering. - `unicli describe ` for contracts. - `unicli do ""` for a best-fit execution plan. - Public docs catalog and generated `llms.txt`. - MCP meta-tools: `unicli_search`, `unicli_list`, `unicli_run`, `unicli_explore`. Discovery must optimize for a large operation catalog by keeping the default resident surface small. The agent should search or describe before loading the full registry. ### 3. Invoke Invocation goes through the same kernel regardless of wrapper: 1. Resolve site and command from the registry. 2. Resolve args from stdin JSON, `--args-file`, flags, positionals, and defaults. 3. Validate against the adapter input schema. 4. Harden paths, selectors, IDs, shell-sensitive values, and URLs. 5. Evaluate permission profile, deny rules, approval memory, and operation risk. 6. Execute YAML pipeline or TypeScript function. 7. Normalize result into `AgentEnvelope v2`. 8. Record usage and optional run trace. This path protects the product from drift between CLI, MCP, ACP, and docs. ### 4. Observe Observation is what turns a tool call into evidence. - Every result has command context, duration, surface, data, error, retryability, and next actions. - An empty successful observation is still a successful observation: adapters that legitimately return `[]` keep `ok: true` and exit `0`. Absence becomes exit `66` only when the command emits an explicit `empty_result` error, such as no discovery match or a domain-specific not-found condition. - Browser actions can attach pre/post evidence, target identity, movement data, and stale-reference diagnostics. - Computer-use actions can attach `visual_action`, target point, overlay status, dispatch result, and post-action capture. - `--record` writes append-only local traces under the run store. - Replay, compare, eval, and delivery consume these traces rather than inventing a parallel audit model. ### 5. Repair Repair is bounded by source path and verification command. Failure envelopes must expose: - error code and message; - `adapter_path`; - failing step or boundary; - suggestion; - retryability; - alternatives; - relevant auth, policy, or platform gap. Repair flow: 1. Reproduce the failure. 2. Read the named adapter or runtime boundary. 3. Patch the real source, not the symptom. 4. Re-run the same failing command or adapter test. 5. Broaden to the nearest adjacent suite. 6. Record the result in progress, findings, or the run trace. ### 6. Publish Release builds regenerate manifests, docs, stats, agents assets, and public indices. Written counts are secondary to generated artifacts. `unicli list`, `stats.json`, `registry.json`, and build outputs are more authoritative than hand-maintained tables. ## Local Computer Use Local Computer Use is a P0 substrate because agents must operate installed software, not only web pages. It is essential, but it is still below the computer-control platform boundary. The preferred execution order is: 1. Stable app API, file format, local CLI, or service endpoint. 2. Electron/CDP or application debug protocol. 3. Native accessibility tree with semantic refs. 4. Scoped background input to a known app/window/ref. 5. Visual planning plus action verification. Visual control is not a decorative cursor. It is valid only when the evidence packet proves what target was resolved, what overlay plan was rendered, which transport dispatched the action, and what post-state was observed. Current compute surface: - `compute apps`, `windows`, `snapshot`, `capture`, `find`; - `compute click`, `type`, `press`, `scroll`, `launch`, `screenshot`; - `compute attach`, `eval`, `wait`, `observe`, `assert`; - `doctor compute` for transport and overlay availability; - MCP `computer-use` profile for agent callers. ## Public Front-End The docs front-end is not a marketing landing page. It is an operator console and learning surface for the computer-control loop. First viewport priorities: 1. State the product: universal computer-control platform for agents. 2. Show the smallest real command path. 3. Expose catalog scale without making command count the main claim. 4. Send users to install, catalog, repair, and agent integration routes. 5. Show Local Computer Use as a first-class substrate, including evidence. The public UI should keep these components honest: - `HomePage.vue`: positioning, install path, capability overview. - `CommandLifecycleIsland.vue`: discover -> execute -> evidence -> repair loop. - `ComputeCursorDemo.vue`: visual replay backed by a checked-in `visual_action` fixture, not a detached animation. - `SiteCatalog.vue` and `SiteStats.vue`: generated catalog inspection. - `llms.txt` and `docs/public/markdown/*`: agent-readable mirrors generated by build scripts. ## Removal And Consolidation Targets These are architecture cleanup targets, not immediate deletions without tests. | Target | Why | Safe direction | | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------ | | Wrapper-specific semantics | Causes CLI/MCP/ACP drift | Move behavior into CommandContract and kernel stages | | Regex-based TS adapter stub extraction | Fragile metadata discovery | Prefer explicit registration metadata or generated contracts | | Internal imports from `src/engine/invoke.ts` | Compatibility shim hides owner modules | New code imports kernel modules directly | | Hand-maintained counts in docs | Drift from generated artifacts | Use stats replacement scripts only | | Expanded MCP as default | Too much resident context | Keep compact/deferred profile first | | Visual-first control language | Encourages brittle automation | Require structured substrate before visual fallback | | Adapter health theater | Passing load is not working behavior | Health gates must run real owned runner/probe surfaces | | Generated public docs edits | Source of truth is upstream docs files | Edit `docs/` sources, regenerate `docs/public/` | ## Design Options For The Rebuild ### Option A: Rewrite Everything Around One Autonomous Orchestrator This creates a conceptually clean root, but the blast radius is too large. It would touch registry, adapters, browser, compute, repair, delivery, docs, protocols, and persistence at once. ### Option B: Keep Adding Commands And Adapters This preserves momentum but leaves architecture pressure unresolved. Breadth without a stricter operation model makes discovery, verification, and repair harder. ### Option C: Rebuild Around The Computer-Control Platform This keeps the existing broad catalog and runtime, but makes intent -> select -> govern -> act -> observe -> diagnose -> repair/reroute -> deliver -> expose the explicit architecture spine. Command lifecycle remains the internal authoring cycle below that product model. Chosen direction: **Option C**. It matches the current code shape and gives the team a safe path to remove drift without freezing feature work. ## Optimization Roadmap ### Step 1: Freeze The Computer-Control Model - Treat operation contracts as the metadata source for docs, MCP, ACP, agent packs, repair, and benchmarks. - Add parity tests whenever a wrapper gains behavior. - Keep default MCP compact and search-driven. - Keep `architecture tree` and `architecture audit` aligned with the computer-control stages. ### Step 2: Mature Local Computer Control As A Substrate - Keep `compute` independent from website adapter assumptions. - Preserve the action evidence contract across CLI and MCP. - Run native smokes on each platform before claiming cross-OS support. - Keep visual overlay optional until platform labs prove it reliable. ### Step 3: Normalize Adapter Authoring - Prefer YAML for finite operations. - Require `schema-v2` metadata and command contracts. - Replace fragile metadata scraping with explicit contracts. - Gate first-class adapters with real runner, fixture, or live smoke evidence. ### Step 4: Collapse Drift Between Surfaces - CLI, MCP, ACP, HTTP, docs, and skills read the same contract projection. - Remove wrapper-only descriptions, safety hints, and schema copies. - Keep generated public docs and agent assets reproducible from source. ### Step 5: Close The Delivery Loop - Treat `delivery` as the objective-level loop above individual invocations. - Route adapter repair through delivery when the failure is repairable. - Keep auth, policy, environment, upstream, and missing-context states explicit. - Record trajectories, not just final green commands. ### Step 6: Raise The Public Front-End Bar - Use the docs UI to teach the computer-control loop, not just list features. - Keep Local Computer Use visible as a first-class substrate. - Use real fixtures for demos and catalog data. - Verify docs build and at least one browser screenshot after visual changes. ## Verification Ladder Use the smallest credible ladder for the claim under change: | Claim | Minimum evidence | | ---------------------------------- | --------------------------------------------------------------------- | | Pure contract or metadata function | Unit test plus typecheck | | CLI/MCP/ACP parity | Wire parity test over the same command | | Adapter behavior | `unicli test ` or adapter runner with real owned code | | Browser/session behavior | Browser evidence test or live daemon smoke | | Local computer-use behavior | `doctor compute`, snapshot/find/action smoke, post-capture evidence | | Real CLI workflow matrix | `npm run e2e:real` | | Public docs UI | `npm run docs:build` plus screenshot/visual inspection for UI changes | | Release readiness | `npm run verify` | ## Done Definition A system change is done only when: - the changed behavior has a falsifiable claim; - the relevant source files and tests were observed before editing; - a failing or proving experiment was run; - root cause and design choice were recorded; - implementation changed the real boundary; - original and adjacent verification passed; - docs, progress, and generated surfaces were updated when their truth changed; - hack-risk is explicitly reported. For this repository, the normal local gate remains: ```bash npm run typecheck && npm run lint && npm test ``` The full release gate remains: ```bash npm run verify ``` --- # Page: Benchmarks Canonical: https://olo-dot-io.github.io/Uni-CLI/BENCHMARK Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/BENCHMARK.md # Benchmarks - Canonical: https://olo-dot-io.github.io/Uni-CLI/BENCHMARK - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/BENCHMARK.md - Section: Explanation - Parent: Explanation (/ARCHITECTURE) > Honest measurement of the context budget behind `unicli SITE CMD`. > Numbers in the "Results" section below are produced by `npm run bench` > and are reproducible in CI fixture mode and on a dev machine in live mode. ## Why This File Exists Agent-native infrastructure should publish real cost numbers. Uni-CLI measures both the command invocation and the response body so public claims stay tied to the current code, fixtures, and output contract. The current fixture bench measures v2 `AgentEnvelope` response bodies at **357-415 tokens** for representative `--limit 5` list-style calls. Total invocation-plus-response budgets land at **364-423 tokens** in the same suite. `unicli list` is much larger because it intentionally emits the full 235-site / 1450-command catalog. This file ships real numbers or says `TODO:` -- nothing in between. ## How We Measure 1. Build the CLI (`npm run build`) so `dist/main.js` is current. 2. Run each `(site, command)` pair at fixed inputs (default args, `--limit 5` unless noted). Capture stdout as JSON. 3. Tokenise the piped `stdout` via an `o200k_base` heuristic approximator (`bench/tokens.ts`). The heuristic matches real `tiktoken` counts within roughly 6-8% on English and compact JSON; rounding to tens of tokens is honest at this precision. 4. Record p50 and p95 across the configured number of iterations (`BENCH_RUNS`, default 50) of in-process tokenisation in fixture mode, or subprocess wall-clock in live mode. 5. Also capture the invocation-string token count so the agent-side command cost is visible. The harness lives under `bench/` and is wired into `npm run bench`. | Mode | Command | Network | Use | | ------- | ------------------------------------- | ------- | ----------------------------------------------------------- | | live | `npm run bench` | yes | Dev-machine sanity check, refreshes fixtures. | | fixture | `BENCH_FIXTURES_ONLY=1 npm run bench` | no | CI and reproducible reports. Reads `bench/fixtures/*.json`. | Fixture files are committed under `bench/fixtures/` alongside the scripts. Legacy fixture payloads are normalized into the current v2 `AgentEnvelope` shape before token counting, so the benchmark tracks the current public output contract even when source fixtures predate the envelope migration. ## Results > Generated 2026-04-30T12:50:15.804Z on Node v22.22.2 / darwin-arm64. > Mode: **fixture** (20 iterations per case). > Reproduce with `npm run bench` (local live mode) or `BENCH_FIXTURES_ONLY=1 npm run bench` (CI-deterministic fixture mode). ### Cold start: `unicli list` | metric | value | | --------------- | ------ | | wall p50 | 47 ms | | wall p95 | 82 ms | | response tokens | 73370 | | response chars | 264131 | | sites listed | 235 | | commands listed | 1450 | ### Adapter call: p50/p95 response tokens | category | command | invocation tokens | response p50 tokens | response p95 tokens | wall p50 ms | wall p95 ms | mode | | --------- | ---------------------------------------- | ----------------: | ------------------: | ------------------: | ----------: | ----------: | ------- | | news | `unicli hackernews top --limit 5` | 9 | 404 | 404 | 0.005 | 0.08 | fixture | | social | `unicli reddit hot --limit 5` | 8 | 415 | 415 | 0.005 | 0.016 | fixture | | social-cn | `unicli 36kr hot --limit 5` | 7 | 357 | 357 | 0.003 | 0.004 | fixture | | dev | `unicli github-trending daily --limit 5` | 11 | 400 | 400 | 0.005 | 0.006 | fixture | ### Public call budget | metric | value | | ---------------------------------- | -------------- | | Smallest total call budget | 364 tokens | | Largest total call budget | 423 tokens | | Median total call budget | 412 tokens | | Representative response token span | 357-415 tokens | ## Public Budget The public operating target is straightforward: - common list-style calls should stay under **600 total tokens** at `--limit 5`; - failure envelopes should stay compact enough for an agent to repair without loading unrelated documentation; - full-catalog output should remain explicit, not automatic. The current fixture suite clears that bar. If a future command class needs a larger payload, it should expose pagination, `--limit`, or `--compact`. ## Reproducibility The `bench/` directory is self-contained: - `bench/tokens.ts` — token estimator (no native deps). - `bench/cold-start.ts` — `unicli list` cold-start runner. - `bench/adapter-call.ts` — per-command p50/p95 runner (live or fixture mode). - `bench/report.ts` — orchestrator, writes `bench/results.json` and patches this file between `` and ``. - `bench/fixtures/` — captured JSON responses (rerun `npm run bench` in live mode to refresh; commit the diff if upstream shape changes). `npm run bench` is **not** part of `npm run verify` because it prefers network. CI runs it only in fixture mode, on an explicit workflow dispatch or a scheduled maintenance check. --- _Last reviewed: 2026-04-28._ --- # Page: Roadmap Canonical: https://olo-dot-io.github.io/Uni-CLI/ROADMAP Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ROADMAP.md # Roadmap - Canonical: https://olo-dot-io.github.io/Uni-CLI/ROADMAP - Markdown: https://olo-dot-io.github.io/Uni-CLI/markdown/ROADMAP.md - Section: Explanation - Parent: Explanation (/ARCHITECTURE) > Current: v0.225.2 — Apollo · Gordon. 317 sites, 1772 commands, 103 pipeline steps. This file tracks current engineering direction for the agent control plane for real software: a universal agent-to-computer control platform. Historical release notes live in `CHANGELOG.md`; they do not belong in the roadmap. ## Shipped | Area | Status | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | Operation catalog | Web, browser, desktop, macOS, bridge, local-tool, and protocol operations are discoverable through `list`, `search`, and `do`. | | v2 output envelope | Normal command surfaces return structured success and error envelopes. | | Operation policy | `open`, `confirm`, and `locked` profiles expose effect/risk/capability/resource scope, plus private remembered approvals. | | Run recording | `--record` and `UNICLI_RECORD_RUN=1` write append-only run traces that agents can list, show, probe, replay, and compare. | | Browser evidence | Browser operator actions can emit pre/post evidence, movement dimensions, stale-ref details, and watchdog results. | | Local computer control | `compute` exposes app discovery, snapshots, refs, clicks, typing, keys, scrolling, app launch, screenshots, and assertions. | | Runtime exposure | Native CLI, JSON stream, MCP, ACP, HTTP API, OpenAI-compatible, and bridge routes are modeled explicitly. | | Self-repair and delivery | Errors carry adapter path, step, retryability, suggestion, alternatives; delivery commands assess objectives and trajectories. | | Docs site | VitePress landing page, guide/reference split, local search, and GitHub Pages deployment workflow are available. | ## Next Priorities 1. **Computer-control root model** - Keep public docs, architecture tree, command descriptions, and agent surfaces aligned around agent-to-computer control over real software. - Treat browser automation, computer-use sandboxes, MCP, natural-language local execution, and per-site wrappers as substrates below Uni-CLI, not as competing product identities. - Make `architecture tree` and `architecture audit` the executable check that catches regressions back into catalog/lifecycle-first framing. - Use `capability_matrix` and `workflow_readiness` from `architecture audit` to separate cataloged coverage from behavior that still needs live evidence. 2. **Operation-contract parity** - Project adapter commands and core Commander commands into the same operation-contract shape. - Keep argument schemas identical across `search`, `describe`, `--dry-run`, direct CLI, MCP, ACP, generated agent configs, and docs. - Add regression tests when a generated command family gets new arguments or a core command becomes externally callable. 3. **Control-kernel hardening** - Keep run traces append-only, local, and private by default. - Let agents probe replayability before repeating a command, then compare the replay trace against the original. - Extend evidence coverage across transport classes without making opaque browser screenshots the only proof. - Keep result envelopes, permission evaluations, and browser action evidence queryable enough for reviews and repair tasks. 4. **Operation policy coverage** - Keep adapters open by default. - Expand effect/risk/capability-scope inference where commands still lack enough metadata. - Use `--yes --remember-approval` when a team wants repeat approval for the same command capability scope without storing raw args. 5. **Substrate bus** - Make HTTP, CDP, accessibility, subprocess, service, and Visual dispatch share one invocation kernel and one evidence model. - Keep ACP/MCP/HTTP as wrappers over the same operation contracts rather than separate behavior definitions. - Surface unavailable transports as structured errors with install/setup suggestions. 6. **Desktop and Visual stack** - Build repeatable control paths for WeChat, WeCom, DingTalk, Lark, Mail, Notes, Word, PowerPoint, Excel, and common Electron apps. - Prefer app APIs, CDP, and accessibility before Visual. - For partial accessibility shells, add screenshot planning, background action primitives, and post-action verification before marking commands live. 7. **Delivery loop alignment** - Support parallel/background agent workflows with isolated worktrees, compact command discovery, and reviewable evidence. - Keep Uni-CLI command execution independent from any single agent loop or editor protocol. - Feed adapter failures back into repair tasks that can be run by coding agents. 8. **Continuous trend intake** - Periodically review agent-loop, computer-use, editor-agent, and desktop automation trends through a private research process. - Convert durable insights into architecture or roadmap updates, not prompt lore. - Keep source-specific attribution internal and keep public docs at the capability level. - Keep code decisions grounded in local tests, diffs, and runtime evidence. 9. **Adapter authoring loop** - Keep browser `analyze`, `init`, `verify`, fixtures, field maps, and site memory as first-class authoring artifacts. - Store reusable site notes under `~/.unicli/sites/SITE/`. - Make repair output directly reusable by coding agents without extra prose. 10. **Browser network detail** - Preserve request/response detail, cache hits, filters, and timing in browser capture commands. - Make captured network evidence usable as adapter fixtures. 11. **Backend honesty** - Keep ACP as compatibility. - Prefer native CLI, JSON stream, and MCP when a backend exposes them. - Do not mark Visual as live unless a configured backend performs real actions. 12. **Docs as product surface** - README stays install-first and capability-first. - Public docs should explain the computer-control loop, operation contracts, action substrates, repair paths, and integration routes. - Keep the public entry path short, current, and directly useful. 13. **Workflow evidence closure** - Start from vehicle-assistant workflows: media, video search, browser tabs, installed apps, productivity state, and open/navigate destinations. - Promote a workflow from cataloged to claimed only after command execution, post-state evidence, and auth/policy posture have been recorded. - Do not add commands for coverage optics; new commands need a runner, fixture, live smoke, or platform doctor evidence. ## Non-Goals - No winner-take-all backend policy. - No hidden success when an adapter failed. - No theory-first README and no catalog-first identity. - No new protocol shim unless it reduces latency, preserves session semantics, or unlocks a real client. - No positioning as only a browser library, MCP wrapper, computer-use sandbox, natural-language shell, scraper, or per-site wrapper collection. ## Verify For public positioning and docs changes: ```bash npm run docs:build npm run docs:check-public ``` For release readiness: ```bash npm run build npm run release:check npm run verify ```