npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@suin/shell-escape-arg

v0.1.2

Published

Format strings as POSIX shell argument literals

Readme

@suin/shell-escape-arg

social-preview

npm version npm downloads License: MIT TypeScript Zero Dependencies API Reference

Format strings as POSIX shell argument literals.

Warning: This library is for display and formatting purposes only. Do NOT use it to build commands for actual shell execution. If you need to execute commands safely, use proper APIs like execFile() with argument arrays, or dedicated security-focused libraries.

Use Cases

This library is intended for:

  • Displaying commands in logs or UIs – Show users what a command would look like
  • Generating documentation – Create example shell commands in docs
  • Testing and debugging – Format arguments for visual inspection
  • Code generation – Generate shell scripts for review (not direct execution)

Features

  • Zero dependencies – Lightweight
  • Unicode-aware – Handles Unicode whitespace (NBSP, ideographic space, etc.)
  • TypeScript-first – Full type definitions included
  • Minimal formatting – Safe strings pass through unchanged

Installation

# npm
npm install @suin/shell-escape-arg

# bun
bun add @suin/shell-escape-arg

# pnpm
pnpm add @suin/shell-escape-arg

Quick Start

import shellEscapeArg from "@suin/shell-escape-arg";

// Safe strings pass through unchanged
shellEscapeArg("abc"); // "abc"
shellEscapeArg("日本語"); // "日本語"

// Strings with spaces or special chars are quoted
shellEscapeArg("a b"); // "'a b'"
shellEscapeArg("$HOME"); // "'$HOME'"
shellEscapeArg("*.txt"); // "'*.txt'"

// Single quotes are escaped with '\''
shellEscapeArg("O'Reilly"); // "'O'\\''Reilly'"

// Empty string becomes ''
shellEscapeArg(""); // "''"

// Leading tilde is quoted to prevent expansion
shellEscapeArg("~user"); // "'~user'"

Example: Logging Commands

import shellEscapeArg from "@suin/shell-escape-arg";

function logCommand(program: string, args: string[]): void {
    const formatted = args.map(shellEscapeArg).join(" ");
    console.log(`Would run: ${program} ${formatted}`);
}

logCommand("grep", ["-r", "hello world", "*.txt"]);
// Output: Would run: grep -r 'hello world' '*.txt'

Example: Generating Documentation

import shellEscapeArg from "@suin/shell-escape-arg";

function generateInstallDocs(packageName: string): string {
    return `
## Installation

\`\`\`bash
npm install ${shellEscapeArg(packageName)}
\`\`\`
`;
}

Formatting Rules

The library uses POSIX single-quote formatting:

| Input | Output | Reason | | ---------- | --------------- | -------------------------------- | | abc | abc | Alphanumeric – no quoting needed | | 日本語 | 日本語 | Unicode text – no quoting needed | | a b | 'a b' | Contains space – quoted | | $HOME | '$HOME' | Contains $ – quoted | | *.txt | '*.txt' | Contains * – quoted | | O'Reilly | 'O'\''Reilly' | Contains ' – escaped as '\'' | | `` | '' | Empty string – quoted | | ~user | '~user' | Starts with ~ – quoted |

Why Single Quotes?

Inside POSIX single quotes, everything is literal except the single quote itself:

  • $VAR stays as $VAR
  • `cmd` stays as `cmd`
  • \n stays as \n
  • * stays as *

When Quoting is Applied

The library quotes strings that contain:

  • Empty string – Would disappear without quotes
  • Unicode whitespace – Space, tab, newline, NBSP, ideographic space (U+3000), etc.
  • ASCII control characters – U+0001–U+001F, U+007F
  • Shell meta-characters' " \ $ ` | & ; < > ( ) * ? [ ] { } ! #
  • Leading tilde – Would trigger tilde expansion

Error Handling

import shellEscapeArg from "@suin/shell-escape-arg";

// Throws TypeError for non-string input
shellEscapeArg(123); // TypeError: escape: arg must be a string
shellEscapeArg(null); // TypeError: escape: arg must be a string

// Throws Error for NUL character (cannot exist in POSIX arguments)
shellEscapeArg("a\0b"); // Error: escape: arg must not include NUL (\u0000)

Limitations

Single Argument Only

This library formats a single argument. It does not parse or build command lines.

POSIX Format Only

Produces output for POSIX-compatible shells (sh, bash, zsh, dash, ksh). Not suitable for:

  • Windows cmd.exe
  • PowerShell

Not for Execution

This library does not provide security guarantees. For executing commands:

// ✓ Use execFile with argument arrays (no shell involved)
import { execFile } from "child_process";
execFile("grep", ["-r", pattern, filename]);

// ✓ Use Bun's $ with template literals (handles escaping internally)
import { $ } from "bun";
await $`grep -r ${pattern} ${filename}`;

// ✗ Do NOT use this library for execution
import { exec } from "child_process";
exec(`grep ${shellEscapeArg(pattern)} ${shellEscapeArg(filename)}`); // Don't do this

API Reference

See the full API documentation.

License

MIT

Contributing

Issues and pull requests are welcome on GitHub.