Skip to content

Repository files navigation

rxcli

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.

License: MIT Node pnpm

English · 中文

Why rxcli? · Ready-made CLIs · Try it · Build a CLI · Architecture


Why rxcli?

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.

The contract agents can rely on

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.

Ready-made CLIs

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.

rxcli requires an OAuth middleware layer. For local testing and development, deploy renxqoo/auth-proxy and follow the CRM testing guide.

Try it now

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 --json

After installation, omit --json in an interactive terminal to get human-readable output:

npx @renxqoo/rxopen-cli install
rxopen life weather 杭州

Build your own CLI

Install the framework:

pnpm add @renxqoo/agent-data-cli

Define 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.

Add authentication without coupling it to commands

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.

Agent Skills are part of the executable

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 --init

skills 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.

Architecture

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
Loading

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.

Repository map

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

Development and release quality

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-run

Every 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.

Data attribution

  • vikiboss/60s provides the upstream public-data APIs used by rxopen and rx60s. 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.

License

MIT © renxqoo

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages