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

shelltender

v0.7.0

Published

All-in-one package combining @shelltender/core, @shelltender/server, and @shelltender/client

Readme

shelltender

All-in-one package for building web-based persistent terminal applications. This package combines @shelltender/core, @shelltender/server, and @shelltender/client into a single convenient import.

Installation

npm install shelltender

This single package includes all Shelltender functionality:

  • TypeScript types and interfaces
  • Server-side session management
  • React components for the UI
  • WebSocket communication

Why Use This Package?

The combined shelltender package is ideal when:

  • You're building a full-stack terminal application
  • You want a simpler dependency management
  • You need both server and client components
  • You're prototyping or building a demo

Use individual packages (@shelltender/core, @shelltender/server, @shelltender/client) when:

  • You only need specific functionality (e.g., server-only)
  • You want to minimize bundle size
  • You're building a custom client implementation
  • You need more granular version control

Quick Start

Full-Stack Example

import {
  // Server components
  SessionManager,
  BufferManager,
  SessionStore,
  WebSocketServer,
  
  // Client components
  Terminal,
  SessionTabs,
  SessionManagerComponent,
  
  // Types
  TerminalSession,
  SessionOptions,
  MessageType
} from 'shelltender';

// Server setup
const bufferManager = new BufferManager();
const sessionStore = new SessionStore();
const sessionManager = new SessionManager(bufferManager, sessionStore);
const wsServer = new WebSocketServer(8080, sessionManager, bufferManager);

// React client
function App() {
  const [sessions, setSessions] = useState<TerminalSession[]>([]);
  const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);

  return (
    <>
      <SessionTabs
        sessions={sessions}
        currentSessionId={currentSessionId}
        onSelectSession={setCurrentSessionId}
        onNewSession={() => setCurrentSessionId('')}
        onCloseSession={handleCloseSession}
        onShowSessionManager={() => setShowManager(true)}
      />
      <Terminal
        sessionId={currentSessionId}
        onSessionCreated={handleSessionCreated}
      />
    </>
  );
}

Exports

Types and Constants (from @shelltender/core)

// Terminal types
export interface TerminalSession { ... }
export interface TerminalEvent { ... }

// Session types  
export interface SessionOptions { ... }

// WebSocket types
export interface TerminalData { ... }

// Constants
export const MessageType = { ... }
export const DEFAULT_COLS = 80;
export const DEFAULT_ROWS = 24;
export const DEFAULT_BUFFER_SIZE = 10000;

Server Components (from @shelltender/server)

// Core session management
export class SessionManager { ... }

// Buffer management
export class BufferManager { ... }

// Session persistence
export class SessionStore { ... }

// Security features
export class RestrictedShell { ... }

// WebSocket server
export class WebSocketServer { ... }

// Additional types
export type StoredSession = { ... }

Client Components (from @shelltender/client)

// Terminal emulator component
export const Terminal: React.FC<TerminalProps>

// Session management modal (aliased to avoid name conflict)
export const SessionManagerComponent: React.FC<SessionManagerProps>

// Tab interface
export const SessionTabs: React.FC<SessionTabsProps>

// Session list sidebar
export const SessionList: React.FC<SessionListProps>

// WebSocket service
export class WebSocketService { ... }

Usage Examples

Basic Terminal with Tabs

import { Terminal, SessionTabs } from 'shelltender';
import 'shelltender/styles/terminal.css';

function BasicTerminal() {
  const [sessions, setSessions] = useState([]);
  const [currentId, setCurrentId] = useState(null);

  return (
    <div className="h-screen flex flex-col">
      <SessionTabs
        sessions={sessions}
        currentSessionId={currentId}
        onSelectSession={setCurrentId}
        onNewSession={() => setCurrentId('')}
      />
      <Terminal sessionId={currentId} />
    </div>
  );
}

Server with Restricted Sessions

import { SessionManager, RestrictedShell } from 'shelltender';

const sessionManager = new SessionManager();

// Create a sandboxed session
const demoSession = sessionManager.createSession({
  restrictToPath: '/home/demo',
  blockedCommands: ['rm', 'sudo', 'dd'],
  readOnlyMode: false,
  env: { PS1: 'demo> ' }
});

Custom Terminal Events

import { TerminalEvent, MessageType } from 'shelltender';

sessionManager.on('sessionOutput', (sessionId, data) => {
  // Detect patterns in output
  if (data.includes('ERROR')) {
    const event: TerminalEvent = {
      type: 'output-match',
      sessionId,
      timestamp: new Date().toISOString(),
      data: { pattern: 'ERROR', content: data }
    };
    handleTerminalEvent(event);
  }
});

Full Application Structure

import express from 'express';
import {
  // Server
  SessionManager,
  BufferManager,
  SessionStore,
  WebSocketServer,
  
  // Types
  SessionOptions,
  TerminalSession
} from 'shelltender';

// Initialize server components
const app = express();
const bufferManager = new BufferManager();
const sessionStore = new SessionStore();
const sessionManager = new SessionManager(bufferManager, sessionStore);
const wsServer = new WebSocketServer(8080, sessionManager, bufferManager);

// REST API
app.get('/api/sessions', (req, res) => {
  res.json(sessionManager.getAllSessions());
});

app.post('/api/sessions', (req, res) => {
  const options: SessionOptions = req.body;
  const session = sessionManager.createSession(options);
  res.json(session);
});

app.delete('/api/sessions/:id', (req, res) => {
  sessionManager.killSession(req.params.id);
  res.sendStatus(204);
});

app.listen(3000);

Migration Guide

From Individual Packages

If you're currently using individual packages:

// Before
import { TerminalSession } from '@shelltender/core';
import { SessionManager } from '@shelltender/server';
import { Terminal } from '@shelltender/client';

// After
import { TerminalSession, SessionManager, Terminal } from 'shelltender';

Handling Name Conflicts

The client SessionManager component is exported as SessionManagerComponent to avoid conflicts with the server SessionManager class:

import { 
  SessionManager,           // Server class
  SessionManagerComponent   // React component
} from 'shelltender';

CSS Styles

Don't forget to import the required styles:

// In your main app file
import 'shelltender/styles/terminal.css';

Or in CSS:

@import 'shelltender/styles/terminal.css';

Complete Example

See the demo app for a full working example using the combined package.

API Documentation

For detailed API documentation, refer to the individual package READMEs:

Requirements

  • Node.js 16+
  • React 18+ (for client components)
  • Modern browser with WebSocket support

License

MIT