| name | cliify |
| description | Use when wrapping CLI binaries in JavaScript, automating shell workflows in TypeScript, composing multiple CLIs into scripts, or building agent tool-use. Covers convertCliToJs, $command, $validate, $spawn, script(), .text()/.lines()/.json() output parsing. |
cliify
You are using cliify to turn CLI binaries into callable JavaScript APIs.
REQUIRED for every cliify usage:
- Call
convertCliToJs("binary") once, reuse the returned API
- Use
.text(), .lines(), or .json() for typed output — never manually split result.stdout
- Use
$validate before executing when inputs come from untrusted sources
- Use
$spawn + for await for streaming — never callbacks unless specifically asked
Flag mapping
API quick reference
import { convertCliToJs, script } from "cliify";
const tool = await convertCliToJs("binary-name");
await tool.subcommand({ flag: "val", _: ["pos"] }).text();
await tool.subcommand({ json: true }).json<MyType>();
await tool.subcommand().lines();
for await (const line of tool.$spawn.subcommand({ watch: true })) {
}
const errors = tool.$validate({ misspeled: true });
tool.$command.subcommand({ flag: "val" });
const deploy = script(git.$command.push(), docker.$command.build({ tag: "app", _: ["."] }));
deploy.run();
console.log(`${deploy}`);
When building tools
Bad:
const result = await api.status();
const lines = result.stdout.trim().split("\n");
Good:
const statusLines = await api.status().lines();
Bad:
const api1 = await convertCliToJs("git");
const api2 = await convertCliToJs("git");
Good:
const git = await convertCliToJs("git");
Bad:
await api.commit({ mesage: "fix" });
Good:
const errors = api.$validate({ mesage: "fix" });
if (errors.length > 0) throw new Error(errors[0].message);
await api.commit({ message: "fix" });
Multi-CLI workflow pattern
const git = await convertCliToJs("git");
const claude = await convertCliToJs("claude");
const files = await git.diff({ nameOnly: true, _: ["HEAD~1"] }).lines();
for (const file of files) {
const review = await claude({
print: true,
model: "sonnet",
_: [`Review ${file} for bugs`],
}).text();
if (review.includes("no issues")) continue;
console.log(`${file}: ${review}`);
}
Full API surface
| Method | Returns | Use for |
|---|
api.sub(opts) | CommandPromise | Run subcommand |
.text() | Promise<string> | Trimmed stdout |
.lines() | Promise<string[]> | Split by newlines |
.json<T>() | Promise<T> | Parse JSON output |
api.$spawn.sub(opts) | CommandProcess | for await streaming |
api.$command.sub(opts) | string | Shell string, no execution |
api.$validate(opts) | ValidationError[] | Pre-flight flag checking |
api.$validate("sub", opts) | ValidationError[] | Subcommand flag checking |
api.$schema | CliSchema | Parsed schema from --help |
api.$parse("sub") | ParsedCommand | Lazily enrich subcommand |
script(...cmds) | { run, toString } | Compose && chain |