npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

xcli-ai

v0.1.0

Published

Config-driven CLI proxy — a single entry point for AI agents to discover and execute commands

Readme

xcli

A config-driven CLI proxy that provides a single unified entry point for AI agents to discover and execute commands across any tool.

Why

MCP (Model Context Protocol) tools are powerful, but each one consumes context window tokens just for its description. When you need Docker, Kubernetes, GitHub, databases, and more, the tool definitions alone eat a significant chunk of your context.

CLI is inherently more AI-friendly — commands are structured, parameters are enumerable, and output is parseable. But there's a catch: there are too many tools, and the AI needs to know each one by name, its flags, and its arguments.

xcli solves this by being the one tool the AI needs to know about. Everything else is discovered progressively through YAML configs:

AI → xcli                          # What domains are available?
AI → xcli docker                   # What commands does docker have?
AI → xcli docker ps -h             # How do I use this command?
AI → xcli docker ps                # Execute it
AI → xcli docker ps -o json        # Get structured output for parsing

No MCP servers to install. No prior knowledge of whether the underlying tool is docker, kubectl, or curl. All commands are self-described in ~/.xcli/ YAML configs, loaded lazily on demand.

Install

npm install -g xcli-ai

Quick Start

1. Create a domain

A domain is a logical grouping of related commands (e.g. github, docker, kubectl).

mkdir -p ~/.xcli/github
# ~/.xcli/github/config.yaml
name: github
description: GitHub REST API operations

2. Create a command

Each command lives in its own subdirectory and is fully self-contained — no inheritance, no shared state.

mkdir -p ~/.xcli/github/repos
# ~/.xcli/github/repos/config.yaml
name: repos
description: List repositories for a user
type: curl
params:
  - name: user
    type: string
    description: GitHub username
    required: true
  - name: per_page
    type: number
    description: Results per page
    default: 30
curl:
  method: GET
  url: "https://api.github.com/users/{{user}}/repos?per_page={{per_page}}"
  headers:
    Accept: application/vnd.github+json
output:
  digest:
    - label: Repos
      field: $count
  columns:
    - header: Name
      field: full_name
      width: 30
    - header: Language
      field: language
      width: 14
    - header: Stars
      field: stargazers_count
      width: 8
    - header: Updated
      field: updated_at
      width: 22

3. Use it

# Raw output (default — same as running curl directly)
xcli github repos --user vuejs

# Table output (formatted using output.columns)
xcli github repos --user vuejs -o table

# Structured JSON (only digest + fields defined in output.columns)
xcli github repos --user vuejs -o json

Command Types

cli — Wrap local commands

Use {{paramName}} for raw value substitution, {{paramName_flag}} to auto-generate CLI flags:

name: pods
description: List pods in a namespace
type: cli
params:
  - name: namespace
    short: n
    type: string
    description: Kubernetes namespace
    default: default
command: kubectl get pods {{namespace_flag}}

The {{namespace_flag}} template automatically produces -n default (or -n <value> if overridden). Boolean params produce just the flag (--verbose) or nothing.

curl — Wrap HTTP APIs

Define the request declaratively — no need to write curl commands by hand:

name: issues
description: List issues for a repository
type: curl
params:
  - name: owner
    type: string
    required: true
  - name: repo
    type: string
    required: true
curl:
  method: GET
  url: "https://api.github.com/repos/{{owner}}/{{repo}}/issues"
  headers:
    Accept: application/vnd.github+json
output:
  columns:
    - header: "#"
      field: number
      width: 8
    - header: Title
      field: title
      width: 60
    - header: State
      field: state
      width: 8

Headers with unresolved template variables (e.g. empty token) are automatically skipped.

Output Modes

| Mode | Description | |------|-------------| | (default) | Raw pass-through — identical to running the underlying command directly | | -o table | Formatted table using output.columns, with output.digest shown as summary above | | -o json | Structured JSON containing only digest + fields defined in output.columns |

Example -o json output:

{
  "digest": {
    "Repos": 30
  },
  "data": [
    {
      "Name": "vuejs/core",
      "Language": "TypeScript",
      "Stars": 48000,
      "Updated": "2024-01-15T00:00:00Z"
    }
  ]
}

Config Structure

~/.xcli/
├── github/
│   ├── config.yaml          # Domain descriptor (name + description only)
│   ├── repos/
│   │   └── config.yaml      # Command definition (fully self-contained)
│   ├── issues/
│   │   └── config.yaml
│   └── repo-info/
│       └── config.yaml
├── docker/
│   ├── config.yaml
│   ├── ps/
│   │   └── config.yaml
│   └── logs/
│       └── config.yaml
└── kubectl/
    ├── config.yaml
    ├── pods/
    │   └── config.yaml
    └── describe/
        └── config.yaml

See the examples/ directory for complete working configs covering GitHub API (curl), Docker (cli), and Kubernetes (cli).

Parameter Types

| Type | Description | Example | |------|-------------|---------| | string | Text value | --name foo | | number | Numeric value | --count 42 | | boolean | Flag, no value needed | --verbose | | array | Comma-separated list | --tags a,b,c |

Optional fields: short (single-char alias), default, choices, required, placeholder, description.

Development

git clone <repo>
cd xcli
npm install

# Run in dev mode (no build step)
npm run dev -- github repos --user vuejs

# Build
npm run build

# Link globally for local testing
npm link

Project Structure

src/
├── cli.ts        # Entry point, arg parsing, Docker-style help rendering
├── config.ts     # YAML config loader with lazy/shallow loading
├── executor.ts   # Command execution engine, template substitution
├── table.ts      # Table (cli-table3) and structured JSON formatting
└── types.ts      # TypeScript type definitions

Adding a New Domain

  1. Create ~/.xcli/<domain>/config.yaml with name and description
  2. Create command subdirectories, each with its own config.yaml
  3. Run xcli <domain> to verify — no restart needed, configs are loaded on demand

License

MIT