Build complex CLIs with type safety and no dependencies
Build and run @stricli/core CLI applications. Supports both single-command and multi-command (route map) applications.
// Single command
const app = buildApplication(command, { name: "myapp" })
// Multiple commands
const app = buildApplication(routeMap, { name: "myapp", versionInfo: { currentVersion: "1.0.0" } })
// Run
await run(app, process.argv.slice(2), { process })Builds an application from a command or route map.
function buildApplication<CONTEXT extends CommandContext>(
root: Command<CONTEXT> | RouteMap<CONTEXT>,
config: PartialApplicationConfiguration
): Application<CONTEXT>Parameters:
root: Command or RouteMap serving as entry pointconfig: Application configuration (name required, rest optional with defaults)Returns: Complete Application instance
Example:
const app = buildApplication(
buildCommand({
func: async function(flags) {
this.process.stdout.write(`Port: ${flags.port}\n`);
},
parameters: {
flags: {
port: { kind: "parsed", parse: numberParser, brief: "Server port", default: "3000" }
}
},
docs: { brief: "Start server" }
}),
{
name: "myapp",
versionInfo: { currentVersion: "1.0.0" },
scanner: { caseStyle: "allow-kebab-for-camel" }
}
);Runs a CLI application with command-line inputs and context. Sets process.exitCode but doesn't call process.exit().
async function run<CONTEXT extends CommandContext>(
app: Application<CONTEXT>,
inputs: readonly string[],
context: StricliDynamicCommandContext<CONTEXT>
): Promise<void>Parameters:
app: Application to runinputs: Command-line arguments (typically process.argv.slice(2))context: Dynamic context with process info and optional command context builderBehavior:
--version flag if configuredcontext.process.exitCode (does not call process.exit())Example:
await run(app, process.argv.slice(2), {
process,
locale: "en"
});
// Or with custom context builder
await run(app, process.argv.slice(2), {
process,
async forCommand(info) {
return {
process,
database: await connectDB(),
logger: createLogger(info.prefix.join(" "))
};
}
});interface Application<CONTEXT extends CommandContext> {
readonly root: Command<CONTEXT> | RouteMap<CONTEXT>
readonly config: ApplicationConfiguration
readonly defaultText: ApplicationText
}import { buildApplication, buildRouteMap, buildCommand, run } from "@stricli/core";
interface MyContext extends CommandContext {
database: Database;
}
const app = buildApplication(
buildRouteMap({
routes: {
start: buildCommand({
func: async function(this: MyContext) {
await this.database.connect();
this.process.stdout.write("Started\n");
},
parameters: {},
docs: { brief: "Start service" }
}),
stop: buildCommand({
func: async function(this: MyContext) {
await this.database.disconnect();
this.process.stdout.write("Stopped\n");
},
parameters: {},
docs: { brief: "Stop service" }
})
},
docs: { brief: "Service management" }
}),
{
name: "service-cli",
versionInfo: { currentVersion: "1.0.0" },
scanner: { caseStyle: "allow-kebab-for-camel" }
}
);
await run(app, process.argv.slice(2), {
process,
async forCommand() {
return { process, database: createDatabase() };
}
});Install with Tessl CLI
npx tessl i tessl/npm-stricli--core