Reference: Internal CLI Tool
A reference internal CLI for platform teams: Commander.js, ESM, private npm publish - Node.js 24 patterns for acme-cli style tools.
Search across all documentation pages
A reference internal CLI for platform teams: Commander.js, ESM, private npm publish - Node.js 24 patterns for acme-cli style tools.
Quick-reference recipe card.
package.json bin → dist/cli.js
├── acme-cli auth login
├── acme-cli deploy promote --service orders-api
└── acme-cli db migrate status{
"name": "@acme/cli",
"version": "2.4.0",
"type": "module",
"bin": { "acme-cli": "./dist/cli.js" },
"engines": { "node": ">=24.18.0" }
}// src/cli.ts
#!/usr/bin/env node
import { Command } from "commander";
import { registerDeployCommands } from "./commands/deploy.js";
import { registerAuthCommands } from "./commands/auth.js";
const program = new Command()
.name("acme-cli")
.description("Acme platform CLI")
.version("2.4.0");
registerAuthCommands(program);
registerDeployCommands(program);
await program.parseAsync(process.argv);// src/commands/deploy.ts
import type { Command } from "commander";
import { getConfig } from "../config.js";
export function registerDeployCommands(program: Command) {
program
.command("promote")
.requiredOption("--service <name>")
.option("--env <env>", "target", "staging")
.action(async (opts) => {
const cfg = await getConfig();
const res = await fetch(`${cfg.apiBase}/v1/deploy/promote`, {
method: "POST",
headers: { Authorization: `Bearer ${cfg.token}` },
body: JSON.stringify(opts),
});
if (!res.ok) throw new Error(`promote failed: ${res.status}`);
console.log(await res.json());
});
}// test/deploy.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
test("promote requires --service", async () => {
const child = spawn("node", ["dist/cli.js", "promote"], { shell: false });
const code = await new Promise<number>((r) => child.on("close", r));
assert.notEqual(code, 0);
});# .github/workflows/publish-cli.yml
- run: npm run build
- run: npm publish --access restricted
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}npx @acme/cli@latest documented in platform wiki| Pro | Con |
|---|---|
| Same language as APIs | Cold start vs Go/Rust |
| Shared types with monorepo | Binary size |
fetch built-in Node 24 | Requires Node installed |
1. --flag
2. ACME_API_TOKEN env
3. ~/.config/acme/config.json
4. defaults| Channel | Use |
|---|---|
| Private npm | Default for JS orgs |
pkg / nexe | Air-gapped (add build complexity) |
| Docker image | CI-only operators |
"type":"module" + .js imports in dist.acme-cli --version mismatch. Fix: Document npm update -g @acme/cli.node:testStack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.
Reviewed by Chris St. John·Last updated Jul 16, 2026