or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-shx

Portable Shell Commands for Node - cross-platform wrapper around ShellJS for npm package scripts

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/shx@0.4.x

To install, run

npx @tessl/cli install tessl/npm-shx@0.4.0

index.mddocs/

shx

shx is a wrapper around ShellJS Unix commands, providing an easy solution for simple Unix-like, cross-platform commands in npm package scripts. It enables running shell commands that work consistently across Windows, macOS, and Linux systems, solving the problem of platform-specific shell command differences in Node.js development workflows.

Package Information

  • Package Name: shx
  • Package Type: npm
  • Language: JavaScript (ES6+ with Babel)
  • Installation: npm install shx --save-dev
  • Repository: https://github.com/shelljs/shx

Core Imports

For programmatic usage:

import { shx } from 'shx';

CommonJS:

const { shx } = require('shx/lib/shx');

Note: shx is primarily designed as a CLI tool, but the core function can be imported directly from the package for programmatic use.

Basic Usage

Command Line Usage

# Install globally for command line usage
npm install -g shx

# Basic file operations
shx ls                          # List files
shx mkdir build                 # Create directory
shx cp src/file.js build/       # Copy files
shx rm -rf build                # Remove directory recursively
shx echo "Hello World"          # Output text

# With options
shx --silent ls nonexistent     # Suppress error output
shx --verbose cp file.js dest/  # Verbose logging
shx --negate test -d mydir      # Negate exit code

npm Package Scripts

Most common usage in package.json:

{
  "scripts": {
    "clean": "shx rm -rf build dist",
    "prebuild": "shx mkdir -p build && shx cp -r src/* build/",
    "postbuild": "shx echo \"Build complete!\"",
    "test:cleanup": "shx rm -rf coverage && shx rm *.log"
  }
}

Architecture

shx is a cross-platform CLI wrapper around ShellJS commands with several key architectural components:

  • CLI Entry Point (cli.js): Handles command-line argument parsing and stdin detection, passes execution to the core shx function
  • Core Command Processor (shx.js): Main execution engine that validates commands, loads plugins, applies options, and executes ShellJS functions
  • Configuration System (config.js): Manages exit codes, command blocklists, pipe detection, and plugin loading configuration
  • Plugin Architecture: Extensible plugin system supporting both built-in plugins (true/false) and external plugins via .shxrc.json
  • Special Command Processing: Enhanced sed command with Unix-like regex syntax conversion
  • Stream Handling: Automatic stdin detection and processing for pipe-compatible commands

The architecture ensures that all ShellJS commands work consistently across Windows, macOS, and Linux by normalizing the execution environment and providing cross-platform path and glob handling.

Capabilities

CLI Binary

The main shx command-line interface that wraps ShellJS commands with cross-platform compatibility.

// Binary entry point: lib/cli.js
// Usage: shx [options] <command> [args...]

Supported Commands: All ShellJS commands except: cd, pushd, popd, dirs, set, exit, exec, ShellString

Common Commands:

  • File operations: cp, mv, rm, mkdir, rmdir, ls, find
  • Text processing: cat, head, tail, grep, sed, sort, uniq
  • File testing: test, which, pwd
  • Output: echo
  • Built-in: true, false (via plugin)

Global Options

Options that modify shx behavior across all commands:

// Global shx options (prefix with --)
interface ShxOptions {
  // shx-specific options
  version: boolean;    // Display version information
  help: boolean;       // Show help text
  negate: boolean;     // Flip exit status (0→1, non-zero→0)
  
  // ShellJS shell.config options (inherited)
  silent: boolean;     // Suppress error output
  verbose: boolean;    // Enable verbose logging  
  noglob: boolean;     // Disable glob expansion
  fatal: boolean;      // Exit on first error (not supported in CLI)
  
  // Command-specific options (passed through to ShellJS)
  [key: string]: any;  // Additional options passed to underlying ShellJS commands
}

Programmatic API

Core function for programmatic usage:

/**
 * Execute shx command programmatically
 * @param argv - Command line arguments in process.argv format
 * @returns Exit code (0 for success, non-zero for errors)
 */
function shx(argv: string[]): number;

Exit Codes:

const EXIT_CODES = {
  SUCCESS: 0,      // Successful execution
  CMD_FAILED: 1,   // Command execution failed
  SHX_ERROR: 27    // shx-specific error (invalid command, etc.)
};

Configuration System

Configuration file support for plugin loading:

// .shxrc.json format
interface ShxConfig {
  plugins: string[];  // Array of plugin names to load
}

Example .shxrc.json:

{
  "plugins": ["shelljs-plugin-open", "custom-plugin"]
}

sed Command Enhancement

Special regex conversion for Unix-like sed syntax:

# Unix-style sed syntax (converted internally)
shx sed "s/original/replacement/g" filename.txt
shx sed -i "s/find/replace/" file.txt

# Flags supported: g (global), i (case-insensitive)

Important: Forward slashes / in patterns must be escaped as \/ in shell, or \\/ in package.json.

Input Stream Handling

Automatic stdin processing for pipe-compatible commands:

# Commands that support piped input
echo "content" | shx grep "pattern"
cat file.txt | shx head -5
ls | shx sort

Pipe-compatible commands:

  • cat (minArgs: 1)
  • grep (minArgs: 2)
  • head (minArgs: 1)
  • sed (minArgs: 2)
  • sort (minArgs: 1)
  • tail (minArgs: 1)
  • uniq (minArgs: 1)

Plugin System

Built-in and custom plugin support with automatic loading:

// Built-in true/false plugin (always loaded)
function shellTrue(): string;   // Returns empty string, exit code 0
function shellFalse(): void;    // Sets error state, exit code 1

Plugin Loading System:

/**
 * Plugin configuration loaded from .shxrc.json in current working directory
 * Plugins are loaded via require() before command execution
 */
interface PluginConfig {
  plugins: string[];  // Array of npm package names to require as plugins
}

/**
 * Built-in plugin registration (example from true/false plugin)
 * Uses ShellJS plugin system for command registration
 */
import plugin from 'shelljs/plugin';

plugin.register('true', shellTrue, {
  allowGlobbing: false,  // Disable glob expansion for this command
  wrapOutput: true       // Wrap output in ShellString object
});

plugin.register('false', shellFalse, {
  allowGlobbing: false,
  wrapOutput: true
});

Plugin Loading Process:

  1. shx checks for .shxrc.json in current working directory
  2. Attempts to require() each plugin listed in the plugins array
  3. Built-in true/false plugin is always loaded automatically
  4. Plugin loading errors throw descriptive error messages

Help System

Dynamic help generation:

/**
 * Generate help text with available commands and options
 * @returns Formatted help string
 */
function help(): string;

Utility Functions

Output formatting and result handling:

/**
 * Handle output formatting for ShellJS command results
 * @param ret - Command result (string, object, or boolean)
 */
function printCmdRet(ret: any): void;

/**
 * Determine if command should read from stdin
 * @param args - Command arguments array
 * @returns true if should read stdin, false otherwise
 */
function shouldReadStdin(args: string[]): boolean;

/**
 * Convert Unix-style sed syntax to JavaScript RegExp for ShellJS
 * @param args - Array of sed command arguments
 * @returns Array with regex patterns converted to RegExp objects
 * @throws Error for empty regex patterns
 */
function convertSedRegex(args: string[]): (string | RegExp)[];

Configuration Constants

Core configuration values used throughout shx:

// Command blocklist - unsupported ShellJS commands
const CMD_BLOCKLIST: string[];

// Option blocklist - ShellJS options not supported in CLI
const OPTION_BLOCKLIST: string[];

// Configuration file name for plugin loading
const CONFIG_FILE: string; // '.shxrc.json'

// Pipe information for stdin-compatible commands
const SHELLJS_PIPE_INFO: {
  [command: string]: { minArgs: number };
};

Error Handling

Command Validation

  • Invalid commands return exit code 27 with error message
  • Blocklisted commands show appropriate warnings
  • Plugin loading failures throw descriptive errors

Input Validation

  • Empty sed patterns are rejected with clear error messages
  • Missing required arguments are validated before execution
  • TTY vs pipe detection for stdin handling

Cross-Platform Compatibility

  • Consistent behavior across Windows, macOS, and Linux
  • Proper path handling and glob expansion
  • Environment-specific optimizations

Advanced Usage

Complex Package Scripts

{
  "scripts": {
    "clean": "shx rm -rf dist coverage *.log",
    "prebuild": "npm run clean && shx mkdir -p dist/js dist/css",
    "build": "shx cp -r src/* dist/ && shx echo \"Build complete\"",
    "test": "shx rm -rf coverage && npm run test:unit",
    "deploy": "shx test -d dist && shx cp dist/* deploy/ || shx echo \"Deploy failed\""
  }
}

Plugin Configuration

{
  "plugins": [
    "shelljs-plugin-open",
    "@company/custom-shell-plugin"
  ]
}

Command Chaining

# Using shell operators (handled by OS shell)
shx mkdir temp && shx cp file.txt temp/ && shx ls temp
shx rm -rf old || shx echo "Nothing to clean"

# In package.json (escape quotes)
"script": "shx mkdir build && shx echo \"Directory created\""

Migration from Shell Scripts

Windows Compatibility

Replace platform-specific commands:

{
  "scripts": {
    // Instead of: "clean": "rm -rf build" (Unix only)
    "clean": "shx rm -rf build",
    
    // Instead of: "copy": "cp -r src dest" (Unix only)  
    "copy": "shx cp -r src dest",
    
    // Instead of: "mkdir": "mkdir -p build" (Unix only)
    "mkdir": "shx mkdir -p build"
  }
}

Glob Patterns

Use double quotes for cross-platform glob support:

{
  "scripts": {
    "clean": "shx rm -rf \"build/**/*.js\" \"dist/*.css\"",
    "copy": "shx cp \"src/**/*.ts\" build/"
  }
}