The fastest way to turn JavaScript into a CLI — for humans and AI.
Turn any JavaScript function into a fully working CLI. No schema. No boilerplate. Just functions.
import { cli } from "@munesoft/argx";
cli({
greet: (name = "world") => `Hello ${name}`
});node app.js greet Alice
# Hello Alice
node app.js --help
# Commands:
# greet <name>That's it. You're done.
argx is a next-generation CLI framework for Node.js and TypeScript that automatically turns your JavaScript functions into fully working command-line tools.
It infers argument names, types, and defaults directly from your function signatures — no configuration required.
cli parser nodejs · typescript cli framework · command line parser · yargs alternative · argparse alternative · build cli tools · argument parser · zero config cli · function to cli · cli builder
| Feature | argx | yargs | commander | meow |
|---|---|---|---|---|
| Zero config | ✅ | ❌ | ❌ | ❌ |
| Type inference | ✅ | ❌ | ❌ | ❌ |
| Auto help | ✅ | manual | manual | manual |
| Nested commands | ✅ | ✅ | ✅ | ❌ |
| Interactive prompts | ✅ | plugin | ❌ | ❌ |
| Async support | ✅ | ✅ | ✅ | ✅ |
| Plugin system | ✅ | ✅ | ❌ | ❌ |
| Auto docs gen | ✅ | ❌ | ❌ | ❌ |
| AI-agent friendly | ✅ | ❌ | ❌ | ❌ |
| Bundle size | tiny | large | medium | small |
npm install @munesoft/argx// app.ts
import { cli } from "@munesoft/argx";
cli({
greet: (name = "world") => `Hello ${name}`
});npx ts-node app.ts greet Alice
# Hello Aliceimport { cli } from "@munesoft/argx";
cli({
greet: (name = "world") => `Hello ${name}!`,
echo: (message: string) => message,
add: (a = 0, b = 0) => a + b,
});node app.js greet # Hello world!
node app.js greet Alice # Hello Alice!
node app.js add --a=5 --b=3 # 8argx reads your default values to infer CLI types automatically:
cli({
deploy: (
env = "dev", // string → positional
force = false, // boolean → --force flag
port = 3000, // number → --port flag
) => {
console.log(`Deploying to ${env} on port ${port}, force=${force}`);
}
});node app.js deploy prod --force --port=8080
# Deploying to prod on port 8080, force=true
node app.js deploy --help
# USAGE
# app deploy <env> [--force] [--port=<number>]cli({
user: {
create: (name: string, role = "viewer") => `Created ${name} as ${role}`,
delete: (id: string) => `Deleted ${id}`,
list: () => "Listing users...",
},
db: {
migrate: (direction = "up") => `Running migrations: ${direction}`,
seed: () => "Seeding database...",
}
});node app.js user create Alice admin
node app.js user delete u_123
node app.js db migrate down
node app.js --help # shows full command treecli({
fetch: async (url: string) => {
const res = await fetch(url);
return res.json();
},
download: async (url: string, dest = "./output") => {
// ...
}
});node app.js fetch https://api.example.com/dataPerfect for AI tools and structured input:
cli({
train: ({ dataset = "mnist", epochs = 10, lr = 0.001 }) => {
console.log(`Training on ${dataset} for ${epochs} epochs at lr=${lr}`);
}
});node app.js train --dataset=cifar --epochs=50 --lr=0.01For scripts that just need to parse flags:
import { argx } from "@munesoft/argx";
// Instant mode — parse everything
const { _, debug } = argx();
// Schema mode — with defaults and type coercion
const opts = argx({ port: 3000, debug: false, host: "localhost" });
console.log(opts.port); // number
console.log(opts.debug); // booleanZero configuration needed. argx reads your function signature at runtime:
- Parameter names → CLI argument names
- Default
"string"→ positional string arg - Default
false→--flagboolean - Default
0→--countnumber flag - Destructured
{}→ named options object
Beautiful help is always available:
node app.js --help
node app.js user --help
node app.js user create --help| Input | Result |
|---|---|
--flag |
true |
--no-flag |
false |
--key=value |
value |
-k value |
value |
--port 3000 |
"3000" |
When required arguments are missing, argx prompts the user:
node app.js deploy
# ? Enter env: dev / prod
# ? Enter name:Disable with interactive: false.
node app.js deploy --config ./deploy.jsonConfig values are merged with flags (flags take precedence).
cli({
server: (port = 3000) => {},
}, {
env: { port: "PORT" } // maps --port → $PORT
});import { cli, loggerPlugin, analyticsPlugin } from "@munesoft/argx";
cli({
deploy: (env = "dev") => {}
}, {
plugins: [
loggerPlugin(),
analyticsPlugin({ endpoint: "https://analytics.example.com" })
]
});cli({
deploy: (env = "dev") => {}
}, {
middleware: [
async (ctx, next) => {
console.log(`Running: ${ctx.command.join(" ")}`);
await next();
console.log(`Done. Result:`, ctx.result);
}
]
});node app.js docs
# ✓ Documentation written to docs/CLI.mdOr programmatically:
import { generateDocs, writeDocs } from "@munesoft/argx";
const md = generateDocs(commands, { name: "myapp", version: "1.0.0" });
writeDocs(md, "docs/CLI.md");cli(commands, { strict: true });
// Exits with code 1 on missing args or unknown commandsAny command can output JSON:
node app.js fetch https://api.example.com --jsoncli({
deploy: (env = "dev") => {}
}, {
name: "deploy-tool",
version: "2.1.0",
description: "My deployment CLI",
strict: true,
interactive: true,
});// Some commands, some schema parsing
const flags = argx({ debug: false, verbose: false });
cli({
run: (script: string) => {
if (flags.debug) console.log("[debug] running:", script);
}
});cli({
risky: async () => {
throw new Error("Something went wrong");
}
});
// ✗ Something went wrongargx is fully written in TypeScript and ships with type declarations.
import { cli, CliOptions } from "@munesoft/argx";
const options: CliOptions = {
name: "mycli",
version: "1.0.0",
strict: true,
};
cli({
// Your commands — all type-safe
build: (target = "production") => {}
}, options);Q: Does it work with plain JavaScript?
Yes. argx works with both .js and .ts files.
Q: Can I use it without TypeScript?
Absolutely. Just import { cli } from "@munesoft/argx" in any .mjs or .js file.
Q: What Node.js version is required?
Node.js 16+.
Q: How does type inference work?
argx uses Function.prototype.toString() to parse the function source at runtime, extracting parameter names and their default value literals, then inferring types from those defaults.
Q: Can I use it in ESM projects?
Yes. argx ships CommonJS and you can require it from ESM via import.
Q: How do I add descriptions to arguments?
Currently via JSDoc comments (planned feature) or through the help options. Full description annotations are on the roadmap.
Q: Is it AI-agent compatible?
Yes. The destructured object pattern (({ key }) => {}) makes commands naturally compatible with structured JSON input from AI agents and LLM tool-calling.
@munesoft/argx/
├── src/
│ ├── index.ts # cli() and argx() API surface
│ ├── core/
│ │ └── parser.ts # argv parsing engine
│ ├── infer/
│ │ └── index.ts # type inference from function signatures
│ ├── commands/
│ │ └── router.ts # nested command resolution
│ ├── help/
│ │ └── index.ts # help text generator
│ ├── runtime/
│ │ ├── executor.ts # function execution engine
│ │ ├── interactive.ts # interactive prompts
│ │ └── formatter.ts # output formatting
│ ├── plugins/
│ │ └── index.ts # plugin & middleware system
│ └── cli/
│ └── docs.ts # documentation generator
PRs welcome. Run tests with:
npm testMIT © munesoft