CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-shelljs

Portable Unix shell commands for Node.js that provide cross-platform compatibility across Windows, Linux, and macOS.

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration and Utilities

Configuration system, error handling, environment variables, and utility functions for controlling ShellJS behavior and extending functionality.

Capabilities

config - Global Configuration

Global configuration object that controls the behavior of all ShellJS commands.

/**
 * Global configuration object for controlling ShellJS behavior
 */
const config: {
  /** Suppress all command output if true (default: false) */
  silent: boolean;
  
  /** Throw JavaScript errors on command failures if true (default: false) */
  fatal: boolean;
  
  /** Print each command as it executes if true (default: false) */
  verbose: boolean;
  
  /** Options passed to fast-glob for file matching (deprecated) */
  globOptions: object;
  
  /** Path to Node.js executable (null for auto-detect) */
  execPath: string | null;
  
  /** Maximum directory depth for recursive operations (default: 255) */
  maxdepth: number;
  
  /** Disable glob expansion if true (default: false) */
  noglob: boolean;
  
  /** Buffer length for I/O operations (default: 64KB) */  
  bufLength: number;
  
  /** Reset configuration to default values */
  reset(): void;
};

Usage Examples:

// Enable silent mode (suppress output)
shell.config.silent = true;
shell.ls(); // No output to console

// Enable fatal mode (throw errors on failures)
shell.config.fatal = true;
try {
  shell.cp('nonexistent.txt', 'dest.txt'); // Throws error
} catch (e) {
  console.log('Command failed:', e.message);
}

// Enable verbose mode (show commands)
shell.config.verbose = true;
shell.cd('mydir'); // Prints: cd mydir

// Save and restore configuration
const originalSilent = shell.config.silent;
shell.config.silent = true;
// ... do silent operations
shell.config.silent = originalSilent;

// Reset to defaults
shell.config.reset();

// Custom exec path (for bundled environments)
shell.config.execPath = '/custom/path/to/node';

// Disable glob expansion
shell.config.noglob = true;
shell.ls('*.txt'); // Treats *.txt literally, not as glob pattern

env - Environment Variables

Direct access to environment variables as a convenient alias for process.env.

/**
 * Environment variables object (alias for process.env)
 */
const env: NodeJS.ProcessEnv;

Usage Examples:

// Read environment variables
console.log('Home directory:', shell.env.HOME);
console.log('Path:', shell.env.PATH);

// Set environment variables
shell.env.NODE_ENV = 'production';
shell.env.CUSTOM_VAR = 'custom_value';

// Use in commands
const nodeVersion = shell.env.NODE_VERSION || '18';
shell.exec(`nvm use ${nodeVersion}`);

// Check if variable exists
if (shell.env.CI) {
  shell.echo('Running in CI environment');
}

// Remove environment variable
delete shell.env.TEMP_VAR;

// Environment-aware operations
const configFile = shell.env.NODE_ENV === 'production' 
  ? 'config.prod.json' 
  : 'config.dev.json';

error - Error State Check

Returns the error message from the last command that failed, or null if no error occurred.

/**
 * Check if error occurred in the last command
 * @returns Error message string if error occurred, null otherwise
 */
function error(): string | null;

Usage Examples:

// Check for errors after commands
shell.cp('source.txt', 'dest.txt');
if (shell.error()) {
  console.log('Copy failed:', shell.error());
}

// Error handling in loops
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
files.forEach(file => {
  shell.cp(file, 'backup/');
  if (shell.error()) {
    console.log(`Failed to backup ${file}:`, shell.error());
  }
});

// Conditional logic based on errors
shell.mkdir('new_directory');
if (!shell.error()) {
  shell.echo('Directory created successfully');
  shell.cd('new_directory');
}

// Clear error state (done automatically by next command)
shell.rm('nonexistent.txt'); // Sets error
console.log(shell.error()); // Shows error message
shell.echo('test'); // Clears error state
console.log(shell.error()); // Returns null

errorCode - Error Code Check

Returns the numeric error code from the last command, or 0 if no error occurred.

/**
 * Get error code from the last command
 * @returns Numeric error code (0 for success, non-zero for errors)
 */
function errorCode(): number;

Usage Examples:

// Check error codes
shell.exec('npm test');
if (shell.errorCode() !== 0) {
  shell.echo(`Tests failed with code ${shell.errorCode()}`);
  shell.exit(shell.errorCode());
}

// Compare error codes
shell.rm('protected_file.txt');
const code = shell.errorCode();
switch (code) {
  case 0:
    shell.echo('File removed successfully');
    break;
  case 1:
    shell.echo('Permission denied');
    break;
  case 2:
    shell.echo('File not found');
    break;
  default:
    shell.echo(`Unknown error: ${code}`);
}

// Use error codes for flow control
function tryOperation() {
  shell.mkdir('temp_dir');
  if (shell.errorCode() === 0) {
    // Success path
    shell.cd('temp_dir');
    return true;
  } else {
    // Error path
    return false;
  }
}

set - Set Shell Options

Sets shell options similar to the bash set command, providing an alternative way to configure behavior.

/**
 * Set shell options (similar to bash set command)
 * @param options - Option string (e.g., '-e', '+e', '-v', '+v')
 * @returns ShellString with operation result
 */
function set(options: string): ShellString;

Options:

  • -e / +e: Enable/disable exit on error (sets config.fatal)
  • -v / +v: Enable/disable verbose mode (sets config.verbose)
  • -f / +f: Disable/enable filename expansion (globbing) (sets config.noglob)

Usage Examples:

// Enable exit on error
shell.set('-e');
shell.cp('nonexistent.txt', 'dest.txt'); // Will throw error

// Disable exit on error
shell.set('+e');
shell.cp('nonexistent.txt', 'dest.txt'); // Won't throw, sets error state

// Enable verbose mode
shell.set('-v');
shell.ls(); // Shows command before execution

// Disable verbose mode
shell.set('+v');

// Disable globbing
shell.set('-f');
shell.ls('*.txt'); // Treats *.txt literally, not as pattern

// Enable globbing  
shell.set('+f');
shell.ls('*.txt'); // Expands *.txt pattern

// Multiple options
shell.set('-ev'); // Enable both error exit and verbose mode

// Use in scripts for strict error handling
shell.set('-e'); // Exit on any error
shell.exec('npm install');
shell.exec('npm test');
shell.exec('npm run build');
// Script will exit early if any command fails

ShellString - Command Return Type

The return type for most ShellJS commands, extending String with additional properties and methods for command chaining and file operations.

/**
 * ShellJS command return type with additional properties and methods
 */
class ShellString extends String {
  /** Standard output from the command */
  stdout: string;
  
  /** Standard error output from the command */
  stderr: string;
  
  /** Exit code from the command (0 for success) */
  code: number;
  
  /**
   * Create a new ShellString
   * @param stdout - Standard output content
   * @param stderr - Standard error content  
   * @param code - Exit code
   */
  constructor(stdout: string | string[], stderr?: string, code?: number);
  
  /**
   * Write ShellString content to file (overwrite)
   * @param file - Target file path
   * @returns Same ShellString for chaining
   */
  to(file: string): ShellString;
  
  /**
   * Append ShellString content to file
   * @param file - Target file path
   * @returns Same ShellString for chaining
   */
  toEnd(file: string): ShellString;
}

Usage Examples:

// Access command output properties
const result = shell.exec('ls -la');
console.log('Exit code:', result.code);
console.log('Output:', result.stdout);
console.log('Errors:', result.stderr);

// Use as string
const files = shell.ls();
console.log('Files:', files.toString());
console.log('Count:', files.split('\n').length);

// Method chaining with file output
shell.cat('input.txt')
  .sed('old', 'new')
  .to('output.txt');

// Pipe to append
shell.echo('Log entry: ' + new Date())
  .toEnd('application.log');

// Create custom ShellString
const customResult = new shell.ShellString('custom output', '', 0);
customResult.to('custom.txt');

// Check for command success
const gitStatus = shell.exec('git status', { silent: true });
if (gitStatus.code === 0) {
  console.log('Git repository is clean');
} else {
  console.log('Git error:', gitStatus.stderr);
}

// Array-like behavior for some commands
const fileList = shell.ls();
fileList.forEach(file => {
  console.log('Processing:', file);
});

Plugin System

ShellJS provides a plugin system for extending functionality with custom commands.

Plugin Utilities

/**
 * Plugin utilities for extending ShellJS (from 'shelljs/plugin')
 */
interface PluginAPI {
  /** Register a new command */
  register(name: string, implementation: Function, options?: RegisterOptions): void;
  
  /** Signal errors from within commands */
  error(message: string, code?: number, options?: ErrorOptions): void;
  
  /** Parse command options */
  parseOptions(optionString: string, optionMap: object, options?: ParseOptions): object;
  
  /** Read input from pipe for commands that accept piped input */
  readFromPipe(): string;
}

interface RegisterOptions {
  /** Allow command to receive piped input */
  canReceivePipe?: boolean;
  
  /** Command-specific option definitions */
  cmdOptions?: object;
  
  /** Allow glob patterns in arguments */
  allowGlobbing?: boolean;
  
  /** Use Unix-style behavior */
  unix?: boolean;
  
  /** Don't wrap output in ShellString */
  wrapOutput?: boolean;
}

Usage Examples:

// Create a plugin file
const shell = require('shelljs');
const plugin = require('shelljs/plugin');

// Register a custom command
plugin.register('count', countLines, {
  canReceivePipe: true,
  cmdOptions: {
    'l': 'lines',
    'w': 'words',
    'c': 'chars'
  }
});

function countLines(options, ...files) {
  // Get piped input if available
  let input = plugin.readFromPipe();
  
  // Parse options
  const opts = plugin.parseOptions(options, {
    'l': 'lines',
    'w': 'words', 
    'c': 'chars'
  });
  
  // Implementation
  if (!input && files.length === 0) {
    plugin.error('No input provided');
    return;
  }
  
  // Process files or input
  const content = input || shell.cat(files).toString();
  const lines = content.split('\n').length;
  const words = content.split(/\s+/).length;
  const chars = content.length;
  
  if (opts.lines) return lines;
  if (opts.words) return words;
  if (opts.chars) return chars;
  
  return `${lines} ${words} ${chars}`;
}

// Use the custom command
shell.count('file.txt');
shell.cat('file.txt').count('-l');

Make System

ShellJS includes a make-like build system for task automation.

/**
 * Make system for task automation (from 'shelljs/make')
 */
const target: {
  [targetName: string]: (args?: string[]) => any;
};

Usage Examples:

// In a make.js file
require('shelljs/make');

target.all = function() {
  target.build();
  target.test();
};

target.build = function() {
  shell.echo('Building project...');
  shell.exec('npm run build');
};

target.test = function() {
  shell.echo('Running tests...');
  shell.exec('npm test');
};

target.clean = function() {
  shell.echo('Cleaning build artifacts...');
  shell.rm('-rf', 'dist/');
  shell.rm('-rf', 'coverage/');
};

target.deploy = function(args) {
  const env = args && args[0] || 'staging';
  shell.echo(`Deploying to ${env}...`);
  shell.exec(`npm run deploy:${env}`);
};

// Run with: node make.js build
// Run with: node make.js deploy production
// Run with: node make.js --help

Configuration Patterns

Environment-Aware Configuration

// Setup based on environment
function configureShell() {
  if (shell.env.NODE_ENV === 'production') {
    shell.config.silent = true;
    shell.config.fatal = true;
  } else if (shell.env.NODE_ENV === 'development') {
    shell.config.verbose = true;
  }
  
  // CI environment settings
  if (shell.env.CI) {
    shell.config.silent = true;
    shell.config.fatal = true;
  }
}

// Scoped configuration changes
function withSilentMode(callback) {
  const originalSilent = shell.config.silent;
  shell.config.silent = true;
  
  try {
    return callback();
  } finally {
    shell.config.silent = originalSilent;
  }
}

// Usage
const result = withSilentMode(() => {
  return shell.exec('npm list --depth=0');
});

Error Handling Strategies

// Comprehensive error checking
function robustOperation() {
  // Method 1: Check error state
  shell.mkdir('temp');
  if (shell.error()) {
    console.log('Failed to create directory:', shell.error());
    return false;
  }
  
  // Method 2: Check error code
  shell.cp('source.txt', 'temp/');
  if (shell.errorCode() !== 0) {
    console.log('Copy failed with code:', shell.errorCode());
    return false;
  }
  
  // Method 3: Use fatal mode with try/catch
  const originalFatal = shell.config.fatal;
  shell.config.fatal = true;
  
  try {
    shell.exec('npm install');
    shell.exec('npm test');
    return true;
  } catch (e) {
    console.log('Command failed:', e.message);
    return false;
  } finally {
    shell.config.fatal = originalFatal;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-shelljs

docs

configuration.md

file-system.md

index.md

process-management.md

text-processing.md

tile.json