Gluegun is a comprehensive Node.js toolkit specifically designed for building sophisticated command-line interfaces (CLIs) in TypeScript or modern JavaScript. It provides a rich ecosystem of functionality including parameter parsing, template generation, file manipulation, system command execution, HTTP client capabilities, interactive prompts, colorful output, and an extensible plugin architecture.
npm install gluegunimport { build } from "gluegun";For CommonJS:
const { build } = require("gluegun");Individual toolbox imports:
import { filesystem, strings, print, system, semver, http, patching, prompt, packageManager } from "gluegun";import { build } from "gluegun";
// Create a CLI using the fluent builder API
const movieCLI = build("movie")
.src(`${__dirname}/commands`)
.plugins("node_modules", { matching: "movie-*" })
.help()
.version()
.defaultCommand()
.create();
// Run the CLI
movieCLI.run();Command example:
// In a command file (e.g., commands/hello.ts)
export = {
name: "hello",
alias: "h",
run: async (toolbox) => {
const { print, strings, filesystem } = toolbox;
print.success("Hello from Gluegun!");
const fileName = strings.kebabCase("My New File");
filesystem.write(`${fileName}.txt`, "File contents");
}
};Gluegun is built around several key architectural patterns:
build()) for configuring CLI applications with commands, plugins, and extensionsCore builder API for creating and configuring CLI applications with plugins, commands, and extensions.
function build(brand?: string): Builder;
interface Builder {
brand(value: string): Builder;
exclude(excludes: string[]): Builder;
src(value: string, options?: GluegunLoadOptions): Builder;
plugin(value: string, options?: GluegunLoadOptions): Builder;
plugins(value: string, options?: GluegunLoadOptions & GluegunMultiLoadOptions): Builder;
help(command?: any): Builder;
version(command?: any): Builder;
defaultCommand(command?: any): Builder;
command(command: GluegunCommand): Builder;
checkForUpdates(frequency: number): Builder;
create(): Runtime;
}Command definition interface and execution system for handling CLI operations.
interface GluegunCommand<TContext = GluegunToolbox> {
name?: string;
description?: string;
run: (toolbox: TContext) => void | Promise<void>;
hidden?: boolean;
commandPath?: string[];
alias?: string | string[];
dashed?: boolean;
file?: string;
plugin?: Plugin;
}
interface GluegunToolbox {
config: Options;
result?: any;
parameters: GluegunParameters;
plugin?: Plugin;
command?: Command;
pluginName?: string;
commandName?: string;
runtime?: Runtime;
// Toolbox extensions
filesystem: GluegunFilesystem;
strings: GluegunStrings;
print: GluegunPrint;
system: GluegunSystem;
semver: GluegunSemver;
http: GluegunHttp;
patching: GluegunPatching;
prompt: GluegunPrompt;
packageManager: GluegunPackageManager;
template: GluegunTemplate;
meta: GluegunMeta;
}Comprehensive file system operations built on fs-jetpack with additional Gluegun-specific utilities.
interface GluegunFilesystem {
eol: string;
separator: string;
homedir(): string;
subdirectories(path: string, isRelative?: boolean, matching?: string): string[];
isFile(path: string): boolean;
isDirectory(path: string): boolean;
// Plus all fs-jetpack methods: read, write, exists, copy, move, etc.
}Extensive string utilities including case conversion, pluralization, and text manipulation functions.
interface GluegunStrings {
camelCase(value: string): string;
kebabCase(value: string): string;
snakeCase(value: string): string;
pascalCase(value: string): string;
pluralize(word: string, count?: number, inclusive?: boolean): string;
trim(string: string, chars?: string): string;
pad(string: string, length: number, chars?: string): string;
// Plus many more string utilities
}Console output utilities with colors, tables, spinners, and formatted messaging for CLI interfaces.
interface GluegunPrint {
colors: GluegunPrintColors;
checkmark: string;
xmark: string;
info(message: any): void;
warning(message: any): void;
success(message: any): void;
error(message: any): void;
table(data: string[][], options?: GluegunPrintTableOptions): void;
spin(options?: string | object): any;
printHelp(toolbox: GluegunToolbox): void;
}System command execution utilities for running external processes and system operations.
interface GluegunSystem {
exec(command: string, options?: any): Promise<any>;
run(command: string, options?: any): Promise<string>;
spawn(command: string, options?: any): Promise<any>;
which(command: string): string | void;
startTimer(): GluegunTimer;
}Advanced file manipulation utilities for updating, appending, and modifying file contents programmatically.
interface GluegunPatching {
exists(filename: string, pattern: string | RegExp): Promise<boolean>;
update(filename: string, callback: (contents: any) => any): Promise<string | object | boolean>;
append(filename: string, contents: string): Promise<string | boolean>;
prepend(filename: string, contents: string): Promise<string | boolean>;
replace(filename: string, search: string, replace: string): Promise<string | boolean>;
patch(filename: string, ...options: GluegunPatchingPatchOptions[]): Promise<string | boolean>;
}Interactive command-line prompts for user input, confirmations, and selections using enquirer.
interface GluegunPrompt {
confirm(message: string, initial?: boolean): Promise<boolean>;
ask<T>(questions: PromptOptions | PromptOptions[]): Promise<T>;
separator(): string;
}HTTP client utilities built on apisauce for making API requests and handling responses.
interface GluegunHttp {
create(options: ApisauceConfig): ApisauceInstance;
}Package manager integration for installing and managing npm packages within CLI applications.
interface GluegunPackageManager {
add(packageName: string | string[], options: GluegunPackageManagerOptions): Promise<GluegunPackageManagerResult>;
remove(packageName: string | string[], options: GluegunPackageManagerOptions): Promise<GluegunPackageManagerResult>;
hasYarn(): boolean;
}Template generation system using EJS for creating files from templates with variable substitution.
interface GluegunTemplate {
generate(options: GluegunTemplateGenerateOptions): Promise<string>;
}Semantic versioning utilities for version comparison, validation, and range checking.
interface GluegunSemver {
valid(version: string): string | null;
clean(version: string): string | null;
satisfies(version: string, range: string): boolean;
gt(version: string, other: string): boolean;
lt(version: string, other: string): boolean;
}CLI metadata and information utilities for accessing package details, version information, update checking, and process management. The meta extension automatically resolves CLI source paths and provides runtime information about the current CLI application.
interface GluegunMeta {
/** Source directory path of the currently running CLI plugin */
src: string | void;
/** Get the current CLI version from package.json */
version(): string;
/** Get the complete package.json contents */
packageJSON(): PackageJSON;
/** Get formatted command information for help display */
commandInfo(): string[][];
/** Check if a newer version is available on npm */
checkForUpdate(): Promise<boolean | string>;
/** Register callback for graceful process termination */
onAbort: (callback: (signal: AbortSignals) => void | Promise<void>) => void;
}
type AbortSignals = 'SIGINT' | 'SIGQUIT' | 'SIGTERM' | 'SIGHUP' | 'SIGBREAK';Meta Extension Usage:
// In a CLI command
export = {
name: "info",
description: "Show CLI information",
run: async (toolbox) => {
const { meta, print } = toolbox;
// Get CLI version and package info
const version = meta.version();
const pkg = meta.packageJSON();
const src = meta.src;
print.info(`CLI: ${pkg.name}`);
print.info(`Version: ${version}`);
print.info(`Description: ${pkg.description}`);
print.info(`Source: ${src}`);
// Check for updates
const updateAvailable = await meta.checkForUpdate();
if (updateAvailable) {
print.warning(`Update available: ${updateAvailable}`);
print.info(`Run: npm install -g ${pkg.name}@${updateAvailable}`);
} else {
print.success("You're running the latest version!");
}
// Show available commands
const commands = meta.commandInfo();
print.info("\nAvailable commands:");
commands.forEach(([command, description]) => {
print.info(` ${command.padEnd(20)} ${description}`);
});
}
};
// Graceful shutdown handling
export = {
name: "long-running-task",
run: async (toolbox) => {
const { meta, print } = toolbox;
let isRunning = true;
// Register cleanup handler
meta.onAbort(async (signal) => {
print.warning(`\nReceived ${signal}, cleaning up...`);
isRunning = false;
// Perform cleanup operations
await cleanupResources();
print.success("Cleanup completed");
});
// Long-running operation
while (isRunning) {
await performWork();
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
};The meta extension provides access to CLI metadata and is automatically available in the toolbox as toolbox.meta.
interface GluegunParameters {
array?: string[];
options: Options;
first?: string;
second?: string;
third?: string;
string?: string;
raw?: any;
argv?: any;
plugin?: string;
command?: string;
}
interface GluegunLoadOptions {
hidden?: boolean;
commandFilePattern?: string[];
extensionFilePattern?: string[];
required?: boolean;
name?: string;
preloadedCommands?: object[];
}
interface GluegunMultiLoadOptions {
matching?: string;
}
interface Options {
[key: string]: any;
}
// Additional Type Definitions
/**
* Timer function that returns elapsed milliseconds
*/
type GluegunTimer = () => number;
/**
* Extended error interface for system command failures
*/
interface GluegunError extends Error {
/** Command stdout output */
stdout?: string;
/** Command stderr output */
stderr?: string;
/** Process exit code */
exitCode?: number;
/** Whether command was killed */
killed?: boolean;
/** Signal that terminated the process */
signal?: string;
/** Whether command timed out */
timedOut?: boolean;
}
/**
* Package.json interface for meta extension
*/
interface PackageJSON {
name?: string;
version?: string;
description?: string;
main?: string;
scripts?: { [key: string]: string };
dependencies?: { [key: string]: string };
devDependencies?: { [key: string]: string };
peerDependencies?: { [key: string]: string };
[key: string]: any;
}
/**
* Apisauce configuration for HTTP client
*/
interface ApisauceConfig {
baseURL?: string;
headers?: { [key: string]: string };
timeout?: number;
withCredentials?: boolean;
auth?: {
username: string;
password: string;
};
}
/**
* Apisauce instance interface for HTTP operations
*/
interface ApisauceInstance {
get: (url: string, params?: any, config?: any) => Promise<any>;
post: (url: string, data?: any, config?: any) => Promise<any>;
put: (url: string, data?: any, config?: any) => Promise<any>;
patch: (url: string, data?: any, config?: any) => Promise<any>;
delete: (url: string, config?: any) => Promise<any>;
head: (url: string, config?: any) => Promise<any>;
setHeader: (name: string, value: string) => void;
setHeaders: (headers: { [key: string]: string }) => void;
deleteHeader: (name: string) => void;
setBaseURL: (baseURL: string) => void;
axiosInstance: any;
}
/**
* Prompt options interface for enquirer integration
*/
interface PromptOptions {
type?: string;
name?: string;
message?: string;
initial?: any;
choices?: any[];
validate?: (value: any) => boolean | string;
format?: (value: any) => any;
result?: (value: any) => any;
skip?: boolean;
[key: string]: any;
}
/**
* Process termination signals for onAbort handler
*/
type AbortSignals = 'SIGINT' | 'SIGQUIT' | 'SIGTERM' | 'SIGHUP' | 'SIGBREAK';