Build CLIs that AI agents can discover, call, compose, and recover from.
A TypeScript framework for agent-native command-line tools, proven by real data and business CLIs.
Why rxcli? · Ready-made CLIs · Try it · Build a CLI · Architecture
rxcli is not another argument parser. It standardizes the boundary between a CLI and the agent, script, pipeline, or person calling it.
Most CLIs expose human-formatted text, ad-hoc errors, separate authentication code, and documentation that drifts away from the executable. That forces agents to guess: parse tables with regular expressions, infer whether a command failed, discover pagination conventions, and learn a different authentication flow for every tool.
With @renxqoo/agent-data-cli, a business package declares its commands and API calls once. The framework supplies the reusable agent-facing contract:
| Capability | What it gives you |
|---|---|
| Deterministic machine contract | JSON success envelopes, structured errors, stable sources, metadata, pagination, and categorized exit codes. |
| One CLI for agents and humans | Pipes and CI receive JSON automatically; an interactive terminal receives readable text or CJK-width-aware tables. --json and --no-json make the choice explicit. |
| Self-discovering Agent Skills | A CLI can list, read, generate, and sync its own SKILL.md documentation so agents know when and how to call it. |
| Authentication as a component | Reuse credential providers, OAuth 2.1 flows (device, authorization code + PKCE, client credentials), token refresh, generated auth commands, or plug in a business-specific scheme such as dual headers or HMAC. |
| Schema-first, type-safe commands | defineCommand infers required, optional, defaulted, and scalar argument types directly from the command's Zod schema. |
| Direct Zod structured input | Large and nested payloads use a Zod 4 schema directly for type inference, validation, discovery, redaction, dry-run, confirmation, and idempotency. |
| Composable by design | Structured stdout stays clean, diagnostics stay on stderr, and one command's envelope can become downstream pipe records. |
| Extensible without a framework fork | Eight lifecycle hooks and plugin-contributed commands cover authentication, input auditing, request transformation, retries, output shaping, and error normalization. |
The repository includes public-data, financial-data, CRM, and OAuth-backed applications. They demonstrate that the same framework works across no-auth APIs, static multi-header authentication, and interactive OAuth—not just a toy example.
In JSON mode, successful results are written to stdout:
{
"ok": true,
"source": "orders",
"data": [{ "id": "ORD-1001", "status": "paid" }],
"meta": {
"pagination": { "complete": false, "nextToken": "page-2" }
}
}Failures and diagnostics are written to stderr, with a non-zero exit code:
{
"ok": false,
"error": {
"type": "authentication",
"subtype": "no_credentials",
"message": "Login is required"
}
}| Exit code | Meaning |
|---|---|
0 |
Success |
1 |
API or server-side business error |
2 |
Invalid input |
3 |
Authentication, authorization, or configuration error |
4 |
Network failure or timeout |
5 |
Internal framework error |
6 |
Policy or risk-control rejection |
10 |
An explicit confirmation such as --yes is required |
This separation keeps shell pipelines valid and lets an agent choose recovery behavior without matching error-message text.
Each active application supports one-step setup with npx <package> install, which installs the CLI, syncs its Agent Skills, and guides credential setup when needed. Node.js 20 or newer is required.
| CLI | Install | Authentication | Why it matters |
|---|---|---|---|
rxstock |
npx @renxqoo/rxstock install |
None | A-share quotes, K-lines, financials, sectors, capital flows, and locally computed indicators, with multi-source fallback. |
rxopen |
npx @renxqoo/rxopen-cli install |
None | More than 60 public-data endpoints for news, trends, weather, prices, translation, developer tools, and media, organized into six focused skills. |
rxcordys |
npx @renxqoo/rxcordys-cli install |
Static dual headers | A full Lead-to-Cash CRM surface: leads, accounts, opportunities, contracts, payments, invoices, orders, approvals, and statistics. |
rxcli |
npx @renxqoo/cli install |
OAuth 2.1 device flow | Orders, products, invoices, and accounts through a company gateway, including registration, login, refresh, status, and logout. |
rx60s is the legacy single-skill package. New integrations should use rxopen, whose domain-oriented skill structure is easier for agents to discover accurately.
rxclirequires an OAuth middleware layer. For local testing and development, deploy renxqoo/auth-proxy and follow the CRM testing guide.
The public-data packages require no account, making them the quickest way to see the contract in action.
# Financial data with multi-source fallback
npx @renxqoo/rxstock quote 600519 --json
npx @renxqoo/rxstock stock diagnosis 300656 --json
npx @renxqoo/rxstock kline indicator 600519 --json
# News, weather, trends, and utilities
npx @renxqoo/rxopen-cli daily --json
npx @renxqoo/rxopen-cli life weather 杭州 --json
npx @renxqoo/rxopen-cli hot weibo --jsonAfter installation, omit --json in an interactive terminal to get human-readable output:
npx @renxqoo/rxopen-cli install
rxopen life weather 杭州Install the framework:
pnpm add @renxqoo/agent-data-cliDefine a schema and implement only the business operation:
import { defineCliApp, defineCommand } from "@renxqoo/agent-data-cli";
import { homedir } from "node:os";
import { join } from "node:path";
import * as z from "zod";
interface TodoListResponse {
items: Array<{ id: string; title: string; completed: boolean }>;
}
const list = defineCommand({
name: "list",
description: "List todos",
args: {
schema: z.object({
limit: z.coerce.number().min(1).max(100).default(20),
}),
},
async run(ctx, args) {
const response = await ctx.get<TodoListResponse>("/todos", {
limit: args.limit,
});
return {
data: response.data.items,
meta: { count: response.data.items.length },
};
},
});
export default await defineCliApp({
name: "todos",
binName: "todos",
description: "Agent-native todo CLI",
// The app's one directory decision; plugins receive this local state via apply(services).
dir: join(homedir(), ".todos"),
baseUrl: "https://api.example.com",
commands: { list },
});That definition provides argument parsing and validation, typed request helpers, automatic JSON/human output selection, structured errors, exit codes, pipe input, help, and a stable execution pipeline. See the framework guide for a complete executable entry point and advanced APIs.
import { defineAuth, defineCliApp } from "@renxqoo/agent-data-cli";
import { homedir } from "node:os";
import { join } from "node:path";
export default await defineCliApp({
name: "todos",
description: "Authenticated todo CLI",
dir: join(homedir(), ".todos"),
plugins: [
defineAuth({
// Sync factory; async assembly runs in the plugin's apply(services).
credentialNamespace: "todos", // → config/todos.json + credentials/todos.json
baseUrl: "https://auth.example.com",
scope: "todos.read offline_access",
}),
],
commands: {},
});The plugin contributes auth login, auth status, auth logout, and auth register. It also resolves credentials, adds authorization to requests, and performs a single shared refresh when concurrent requests receive 401 responses.
For custom behavior, plugins can use:
beforeCommand → observeInput → beforeRequest → observeRequest → handleUnauthorized
→ transformOutput → observeError → handleError
Plus assembly (apply) and app-level (onAppRun / afterAppRun) hooks.
Plugins may also contribute commands through provides, which keeps cross-cutting features componentized instead of scattering them across business command files.
Skills are versioned beside the code and exposed by the CLI itself:
rxstock skills list
rxstock skills read rx-stock
rxstock skills sync
rxstock skills gen my-skill --initskills sync always writes the Agent Skills standard path at ~/.agents/skills. It also writes the detected installation paths for Claude Code, Codex, Cursor, ZCode, OpenClaw, and Pi Coding Agent. A business package can override these targets when it needs a different distribution policy.
This makes command discovery reproducible: the executable, its command schema, and the instructions an agent reads can evolve in the same release.
flowchart TB
Caller["AI agent · script · terminal user"]
Skill["SKILL.md discovery and usage guidance"]
Apps["Business CLI: commands and domain components"]
SDK["agent-data-cli: routing · auth · requests · errors · output · pipes"]
APIs["Public APIs · CRM · OAuth gateway · internal services"]
Skill -. "teaches invocation" .-> Caller
Caller --> Apps
Apps --> SDK
SDK --> APIs
APIs --> SDK
SDK --> Caller
The boundary is deliberate:
- Business packages own domain language, API endpoints, response mapping, and human presentation.
- The framework owns invocation semantics, authentication lifecycle, transport, error taxonomy, output contracts, skills, and composition.
- Plugins own reusable cross-cutting components such as authentication, auditing, policies, and retries.
This keeps commands shallow and testable while concentrating complex behavior in reusable framework modules.
| Path | Purpose |
|---|---|
packages/cli-sdk |
@renxqoo/agent-data-cli, the framework package |
apps/a-stock |
rxstock, A-share data and analysis |
apps/rxopen |
rxopen, domain-oriented public-data CLI |
apps/cordys-crm |
rxcordys, Cordys CRM CLI |
apps/crm |
rxcli, OAuth-backed company business CLI |
apps/60s |
Legacy rx60s package |
packages/cli-sdk/docs |
Architecture, SDK, authentication, testing, and release documentation |
The monorepo uses pnpm, TypeScript, Vitest, and oxlint. Framework changes are developed with regression tests first, then verified against the real application packages.
pnpm install
pnpm build
pnpm typecheck
pnpm test
pnpm lint
pnpm publish:dry-runEvery version PR must update CHANGELOG.md. Contribution and release expectations are documented in CONTRIBUTING.md.
To add a business CLI, follow the framework's bundled agent-cli-builder guide. It covers command decomposition, authentication choices, output design, tests, skills, and installation.
- vikiboss/60s provides the upstream public-data APIs used by
rxopenandrx60s. It is MIT-licensed and maintained by Viki. - Tencent, Eastmoney, Sina, and 10jqka public market endpoints are data sources for
rxstock.
Copyright in upstream data remains with its original source. This project provides command-line integrations and does not redistribute ownership of that data.