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 🙏

© 2025 – Pkg Stats / Ryan Hefner

unix-shell-js

v1.2.2

Published

Browser-based Unix/Linux command emulator with vi editor support

Downloads

23

Readme

Unix Shell JS

Tests Build npm version

A browser-based Unix/Linux command emulator with vi editor support.

Try the Live Demo

Features

  • Common Unix commands (ls, cd, cat, mkdir, rm, etc.)
  • Vi/Vim editor with modal editing
  • Tab completion
  • Command history
  • Pipe and redirection support
  • Wildcard expansion (* and ?)
  • Customizable filesystem
  • Custom command support

Installation

From npm

npm install unix-shell-js

Local Development

If you're working locally and want to use this library in another project:

cd ../unix-shell-js
npm install
npm run build
npm link

cd ../your-project
npm link unix-shell-js

Development

This library is written in TypeScript and compiled to JavaScript.

Build Commands

  • npm run build - Compile TypeScript to JavaScript (outputs to dist/) and copy to demo
  • npm run copy-to-demo - Copy built files to docs/ directory for GitHub Pages demo
  • npm run watch - Watch mode for development (auto-recompiles on changes)
  • npm run prepublishOnly - Automatically runs before publishing to npm

Testing

  • npm test - Run all tests
  • npm run test:watch - Run tests in watch mode
  • npm run test:coverage - Run tests with coverage report

The project includes comprehensive test suites covering:

  • Core shell functionality (commands, navigation, environment)
  • File system operations (create, read, delete files/directories)
  • File redirection and piping
  • Custom command support
  • Tab completion
  • User switching (su, sudo, exit)
  • localStorage persistence

Project Structure

  • src/ - TypeScript source files
    • index.ts - Main Unix Shell implementation
    • vi-editor.ts - Vi/Vim editor
    • example-files.ts - Example filesystem generator
  • dist/ - Compiled JavaScript files (generated by TypeScript compiler)
    • Includes .js, .d.ts (type definitions), and .map (source maps) files

Usage

TypeScript

The library is written in TypeScript and includes full type definitions:

import { UnixShell } from 'unix-shell-js';
import { createExampleFiles } from 'unix-shell-js/dist/example-files';

const shell = new UnixShell({
    username: 'user',
    fileSystem: createExampleFiles('user'),
    persistence: {
        enabled: true,
        prefix: 'myapp'
    }
});

const output: string = shell.execute('ls -la');
console.log(output);

Type definitions included:

  • UnixShellOptions - Constructor options
  • FileSystem - Filesystem structure types
  • PersistenceOptions - Persistence configuration
  • CommandHandler - Custom command function signature
  • CompletionResult - Tab completion result type

JavaScript (Browser)

Include the library files in your HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Terminal</title>
</head>
<body>
    <script src="node_modules/unix-shell-js/dist/index.js"></script>
    <script src="node_modules/unix-shell-js/dist/vi-editor.js"></script>
    <script src="node_modules/unix-shell-js/dist/example-files.js"></script>
    <script>
        // Create the shell with example files
        const shell = new UnixShell({
            username: 'user',
            fileSystem: createExampleFiles('user')
        });

        // Execute a command
        const output = shell.execute('ls -la');
        console.log(output);
    </script>
</body>
</html>

Initialize with Custom Filesystem

const customFS = {
    '/': {
        'home': {
            'myuser': {
                'welcome.txt': 'Hello, world!\n',
                'projects': {
                    'app.js': 'console.log("Hello");\n'
                }
            }
        }
    }
};

const shell = new UnixShell({
    username: 'myuser',
    fileSystem: customFS
});

Enable localStorage Persistence

The library includes built-in localStorage persistence to automatically save and restore the filesystem, current path, and current user across page reloads:

const shell = new UnixShell({
    username: 'user',
    fileSystem: createExampleFiles('user'),
    persistence: {
        enabled: true,
        prefix: 'myapp'  // Uses 'myapp_filesystem', 'myapp_current_user', 'myapp_current_path'
    }
});

How it works:

  • When persistence is enabled, the shell automatically loads saved state from localStorage on initialization
  • After each command execution, the filesystem and current state are automatically saved
  • If no saved data exists, it uses the provided fileSystem and username options
  • Use a custom prefix to avoid conflicts with other apps on the same domain

Clear saved data:

// Clear localStorage for this shell
shell.clearStorage();

Initialize with Custom Commands

const customCommands = {
    // Example: ps aux command
    ps: function(args) {
        // Parse flags
        let showAll = false;

        for (const arg of args) {
            if (arg === 'aux' || arg === '-aux') {
                showAll = true;
            }
        }

        const processes = [
            { pid: 1, user: 'root', command: '/sbin/init' },
            { pid: 100, user: this.currentUser, command: '-bash' }
        ];

        if (showAll) {
            processes.push(
                { pid: 50, user: 'root', command: '/usr/sbin/sshd' },
                { pid: 75, user: 'www-data', command: 'nginx' }
            );
        }

        let output = 'USER       PID COMMAND\n';
        processes.forEach(p => {
            output += `${p.user.padEnd(10)} ${String(p.pid).padStart(4)} ${p.command}\n`;
        });

        return output;
    },

    // Example: custom greeting command
    hello: function(args) {
        const name = args[0] || 'World';
        return `Hello, ${name}!`;
    }
};

const shell = new UnixShell({
    username: 'user',
    fileSystem: createExampleFiles('user'),
    customCommands: customCommands
});

// Now you can use your custom commands
console.log(shell.execute('hello Alice')); // Output: Hello, Alice!
console.log(shell.execute('ps aux'));      // Shows process list

Full Example with Terminal UI

// Initialize the shell
const shell = new UnixShell({
    username: 'developer',
    fileSystem: createExampleFiles('developer'),
    customCommands: {
        status: function(args) {
            // Example custom command
            return 'System Status: OK\nUptime: 5 days\nLoad: 0.5';
        }
    }
});

// Handle user input
function handleCommand(inputText) {
    const output = shell.execute(inputText);

    // Handle special outputs
    if (output === '__CLEAR__') {
        // Clear the terminal display
        clearTerminal();
    } else if (output === '__VI_OPENED__') {
        // Vi editor was opened
    } else if (output && output.startsWith('__USER_SWITCHED__:')) {
        // User changed (su/sudo command)
        updatePrompt();
    } else {
        // Display normal output
        displayOutput(output);
    }
}

Integration Tips

Managing the Command Prompt

When building a terminal UI, you'll need to display a prompt that shows the current user and directory. The prompt typically needs to update after commands like cd or su that change the current path or user.

Pattern for updating the prompt:

function updatePrompt() {
    const user = shell.getCurrentUser();
    let path = shell.getCurrentPath();
    const home = shell.environment.HOME;

    // Replace home directory with ~
    if (path === home) {
        path = '~';
    } else if (path.startsWith(home + '/')) {
        path = '~' + path.substring(home.length);
    }

    // Use # for root, $ for regular users
    const promptChar = user === 'root' ? '#' : '$';

    // Update your prompt element
    promptElement.textContent = `${user}@hostname:${path}${promptChar}`;
}

Typical command execution flow:

  1. User enters a command
  2. Capture the current prompt text (for display in command history)
  3. Execute the command: const output = shell.execute(command)
  4. Display the command with its original prompt in history
  5. Display the command output
  6. Update the active prompt to reflect any changes (new path, new user, etc.)
  7. Clear the input field for the next command

Key point: When displaying command history, preserve the prompt as it was when the command was entered. Only update the active input prompt after command execution.

See the live demo source code for a complete working example.

API Reference

UnixShell Constructor

new UnixShell(options)

Options:

  • fileSystem (Object): Custom filesystem structure
  • username (String): Current user name (default: 'user')
  • customCommands (Object): Custom command handlers
  • persistence (Object): localStorage persistence configuration
    • enabled (Boolean): Enable/disable persistence
    • prefix (String): localStorage key prefix (default: 'unixshell')

Methods

  • execute(commandLine) - Execute a command and return output
  • getCurrentPath() - Get current working directory
  • getCurrentUser() - Get current user
  • getNode(path) - Get filesystem node at path
  • resolvePath(path) - Resolve relative/absolute path
  • getCompletions(partial) - Get tab completion suggestions
  • saveToStorage() - Manually save state to localStorage (auto-called after commands if persistence enabled)
  • loadFromStorage() - Load state from localStorage (auto-called during initialization if persistence enabled)
  • clearStorage() - Clear saved state from localStorage

Built-in Commands

  • help - Show available commands
  • ls - List directory contents
  • cd - Change directory
  • pwd - Print working directory
  • cat - Display file contents
  • echo - Display text
  • clear - Clear terminal
  • whoami - Print current user
  • date - Display date/time
  • uname - Print system information
  • env - Print environment variables
  • history - Show command history
  • mkdir - Create directory
  • touch - Create file
  • rm - Remove file/directory
  • tree - Display directory tree
  • ps - Report process status (basic - can be overridden)
  • vi/vim - Edit file
  • su - Switch user
  • sudo - Execute as superuser
  • exit - Exit user session

Note: All built-in commands can be overridden by providing a custom command with the same name in the customCommands option.

Vi Editor

The library includes a fully functional vi/vim modal editor with:

  • Normal, Insert, and Command modes
  • Movement keys (hjkl, arrows, 0, $, G)
  • Insert commands (i, a, o, O)
  • Delete commands (x, dd, dw, d$, etc.)
  • Yank and paste (Y, p)
  • Save and quit (:w, :q, :wq, :q!)

License

MIT