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

shelltogo

v1.3.1

Published

TUI agent for ShellToGo - access your terminal from anywhere

Downloads

13

Readme

tmux-relay Agent

Production-ready Node.js/TypeScript CLI agent for the tmux-relay project. Enables mobile access to tmux sessions from anywhere by connecting your workspace to the relay server.

Overview

The agent is a lightweight CLI tool that:

  • Runs in your development workspace (devpod, cloud VM, homelab server)
  • Authenticates via GitHub (using gh CLI or device OAuth flow)
  • Generates persistent 3-word BIP39 session codes
  • Connects outbound to the relay server via secure WebSocket (WSS)
  • Discovers and manages tmux sessions and panes
  • Relays terminal I/O between tmux and mobile clients
  • Implements rate limiting and security features

Installation

Via npx (recommended)

npx tmux-relay

Via npm global install

npm install -g @shelltogo/agent
tmux-relay

From source

cd packages/agent
npm install
npm run build
npm start

Usage

First Run

$ npx tmux-relay

╔═══════════════════════════════════════╗
║                                       ║
║         shelltogo Agent v1.0.0        ║
║                                       ║
║    Mobile access to tmux sessions     ║
║                                       ║
╚═══════════════════════════════════════╝

🚀 shelltogo Agent Setup

Step 1: Creating directory structure...
✓ Directories created

Step 2: Checking tmux installation...
✓ tmux is installed (version: 3.3a)

Step 3: Checking git installation...
✓ git is installed

Step 4: Creating tmux configuration...
✓ tmux configuration created

Step 5: Installing TPM (Tmux Plugin Manager)...
✓ TPM installed

Step 6: Installing tmux plugins...
✓ Plugins installed

Step 7: Checking for tmux sessions...
No tmux sessions found.

You can create one with:
  tmux new -s relay-alpha

✅ Setup complete!

With Existing Sessions

$ npx tmux-relay

shelltogo Agent v1.0.0

Checking GitHub authentication... ✓ alice
Connecting to relay... ✓

════════════════════════════════════════════════════
  Workspace: apple-brave-crystal
  URL: https://relay.shelltogo.dev/r/apple-brave-crystal
════════════════════════════════════════════════════

Found tmux sessions:
  ● relay-alpha    (3 panes)
  ● relay-bravo    (1 pane)

Waiting for connections...

─────────────────────────────────────────────────────
10:32:15  Connected: alice (mobile)
10:32:18  Attached: relay-alpha:1

Architecture

Components

packages/agent/
├── src/
│   ├── cli.ts              # CLI entry point, banner, session display
│   ├── agent.ts            # Main Agent class
│   ├── auth.ts             # GitHub authentication
│   ├── tmux.ts             # tmux integration
│   ├── config.ts           # Configuration management
│   ├── setup/              # Setup utilities
│   │   ├── index.ts        # Setup orchestration
│   │   ├── directory.ts    # Directory creation
│   │   ├── tmux-check.ts   # tmux detection
│   │   ├── tmux-install.ts # tmux installation
│   │   └── tmux-config.ts  # tmux configuration
│   └── index.ts            # Package exports
├── dist/                   # Compiled JavaScript
├── package.json
└── tsconfig.json

Key Features

1. GitHub Authentication (FR-1.2, FR-1.3)

  • gh CLI Integration: Checks for existing gh auth status
  • Device Flow Fallback: Browser-based OAuth if gh CLI not available
  • Token Validation: Verifies tokens via GitHub API
// Try gh CLI first
const ghAuth = await checkGhAuth();

// Fall back to device flow
if (!ghAuth) {
  const auth = await deviceFlowAuth(relayUrl);
}

2. Session Code Generation (FR-2.1)

Uses full BIP39 wordlist (256 words) from @shelltogo/shared:

  • 3-word codes: apple-brave-crystal
  • 256³ = 16,777,216 possible combinations
  • Persistent across restarts in .shelltogo/session
import { generateSessionCode } from '@shelltogo/shared';

const code = generateSessionCode();
// => "apple-brave-crystal"

3. tmux Discovery (FR-2.7, FR-2.8)

# List sessions
tmux list-sessions -F "#{session_name}|#{session_windows}|..."

# List panes
tmux list-panes -t "session" -a -F "#{pane_index}|#{pane_title}|..."
const sessions = await discoverSessions();
// [
//   { name: "relay-alpha", panes: [...] },
//   { name: "relay-bravo", panes: [...] }
// ]

4. Terminal I/O Relay (FR-4.1)

Uses pipe-pane for reliable output capture:

// Create FIFO for output
await execAsync(`mkfifo "${fifoPath}"`);

// Attach pipe-pane
await execAsync(`tmux pipe-pane -t "${target}" -o "cat > ${fifoPath}"`);

// Read output
fifoStream.on('data', (chunk) => {
  outputHandlers.forEach(handler => handler(chunk.toString()));
});

// Send input
exec(`tmux send-keys -t "${target}" -l -- ${JSON.stringify(data)}`);

5. Scrollback Management (FR-4.2, FR-4.3)

// Initial viewport (3x screen = ~150 lines)
const viewport = await getViewport(sessionName, pane, 150);

// Additional scrollback on demand
const history = await getScrollback(sessionName, pane, 500);

6. Security & Rate Limiting (FR-6.1, FR-6.2)

// Track failed auth attempts
interface SecurityState {
  failedAuths: number;
  failedAuthsWindow: number[];  // timestamps
  rotationCount: number;
}

// Rotate session code after threshold
if (recentFailures >= 5 || totalFailures >= 20) {
  await rotateSessionCode();
}

7. Reconnection Logic (FR-5.1, FR-5.2, FR-5.3)

// Load persisted session code
const savedCode = await loadWorkspaceSession(workspaceRoot);
this.sessionCode = savedCode || generateSessionCode();

// Attempt to reclaim on reconnect
ws.on('close', () => {
  scheduleReconnect();  // Reconnect after 5 seconds
});

Message Protocol

Agent → Relay

{ type: 'register', code: 'apple-brave-crystal', name: 'laptop', owner: 'alice' }
{ type: 'unregister' }
{ type: 'sessions_update', sessions: TmuxSessionSummary[] }
{ type: 'rotate', newCode: 'orange-delta-falcon' }
{ type: 'to_client', clientId: 'xxx', payload: ... }
{ type: 'broadcast', payload: ... }
{ type: 'client_rejected', clientId: 'xxx', reason: 'unauthorized' }

Relay → Agent

{ type: 'registered', code: 'apple-brave-crystal' }
{ type: 'register_failed', reason: 'code_taken' }
{ type: 'client_connected', clientId: 'xxx', username: 'alice' }
{ type: 'client_disconnected', clientId: 'xxx' }
{ type: 'client_message', clientId: 'xxx', payload: ... }

Terminal Protocol (Mobile ↔ Agent via Relay)

// Session management
{ type: 'sessions', sessions: TmuxSession[] }
{ type: 'create_session', name?: string }
{ type: 'session_created', session: TmuxSession }

// Pane attachment
{ type: 'attach', session: 'relay-alpha', pane: 1 }
{ type: 'attached', session: 'relay-alpha', pane: 1 }
{ type: 'detach' }

// Terminal I/O
{ type: 'buffer', lines: string[], hasMore: boolean, totalLines: number }
{ type: 'output', data: string }
{ type: 'input', data: string }
{ type: 'resize', cols: number, rows: number }

// Scrollback
{ type: 'fetch_scrollback', before: number, count: number }
{ type: 'scrollback', lines: string[], startLine: number }

// Keepalive
{ type: 'ping' }
{ type: 'pong' }

Configuration

User Config (~/.shelltogo/config.json)

{
  "relayUrl": "wss://relay.shelltogo.dev",
  "githubToken": "ghp_...",
  "githubUser": "alice"
}

Workspace Config (.shelltogo/session)

apple-brave-crystal

tmux Config (.tmux.conf)

Auto-generated with:

  • Mouse mode enabled
  • tmux-resurrect plugin (session persistence)
  • tmux-continuum plugin (auto-save every 15 min)
  • Session storage in .tmux/resurrect/

Command Line Options

# Normal startup
npx tmux-relay

# Force re-run setup
npx tmux-relay setup

# Environment variables
SHELLTOGO_RELAY_URL=wss://custom.relay.url npx tmux-relay

Development

Build

npm run build

Development Mode (Hot Reload)

npm run dev

Testing

npm test              # Run all tests
npm run test:watch    # Watch mode

Dependencies

Production

  • ws - WebSocket client for relay connection
  • chalk - Terminal colors and formatting
  • inquirer - Interactive CLI prompts
  • ora - Loading spinners
  • @shelltogo/shared - Shared types and utilities

Development

  • typescript - TypeScript compiler
  • tsx - TypeScript executor for dev mode
  • vitest - Fast unit test runner
  • @types/* - Type definitions

Troubleshooting

tmux not found

# macOS
brew install tmux

# Ubuntu/Debian
sudo apt-get install tmux

# RHEL/CentOS
sudo yum install tmux

GitHub authentication failed

# Use gh CLI
gh auth login

# Then restart agent
npx tmux-relay

Connection to relay failed

Check relay URL configuration:

# Default
wss://relay.shelltogo.dev

# Custom
export SHELLTOGO_RELAY_URL=wss://your-relay.example.com
npx tmux-relay

Session code already taken

The agent will automatically generate a new code if the previous one is taken by another workspace.

Security Considerations

  1. WebSocket over TLS: All connections use WSS (WebSocket Secure)
  2. GitHub Authentication: Both agent and mobile clients must authenticate
  3. User Validation: Agent validates mobile connections are from same GitHub user
  4. Rate Limiting: Tracks and blocks excessive failed auth attempts
  5. Session Code Rotation: Automatically rotates codes on suspicious activity
  6. No Credential Storage on Relay: Relay never sees or stores credentials

Performance

  • Connection Latency: < 500ms initial connection
  • Input Latency: < 100ms keypress to echo
  • Scrollback Fetch: < 200ms for 500 lines
  • Memory Usage: < 100MB for 10 panes with 10k scrollback each

License

MIT

Support

For issues, questions, or contributions:

  • GitHub Issues: https://github.com/yourusername/shelltogo/issues
  • Documentation: https://shelltogo.dev/docs