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

@mmmbuto/pty-termux-utils

v1.1.4

Published

Shared PTY utilities for Termux/Android with graceful fallback

Readme

PTY Termux Utils — Shared PTY Library for Termux/Android


Overview

@mmmbuto/pty-termux-utils is a shared library that provides unified PTY management for Termux/Android and Linux ARM64 environments. It offers native PTY support via @mmmbuto/node-pty-android-arm64 or @lydell/node-pty-linux-arm64 with graceful fallback to child_process when unavailable. Type-safe, ESM+CJS compatible, and with consistent debug logging.


npm downloads ko-fi


Features

  • Multi-Provider PTY — Native PTY support for Termux and Linux ARM64
  • Graceful Fallback — Degrades to child_process adapter when native PTY unavailable
  • Type-Safe — PTY types defined internally, no dependency on optional module
  • Memoized Loading — Native module loaded once per process
  • Consistent Logging[PTY] prefix, debug-only via PTY_DEBUG=1
  • ESM + CJS — Works with both TypeScript (ESM) and CommonJS (CJS) projects

PTY Providers

| Priority | Platform | Provider | Module | Version | |----------|-----------|----------|---------|----------| | 1 | Termux | Native | @mmmbuto/node-pty-android-arm64 | ~1.1.0 | | 2 | Linux ARM64 | Native | @lydell/node-pty-linux-arm64 | ~1.2.0-beta.2 | | 3 | All platforms | Fallback | child_process adapter | built-in |

Platform Detection

// Termux detection
process.platform === 'android' || process.env.PREFIX?.includes('com.termux')

// Linux ARM64 detection
process.platform === 'linux' && process.arch === 'arm64'

Installation

npm install @mmmbuto/[email protected]

Optional Native PTY

For native PTY support:

# Termux
npm install @mmmbuto/node-pty-android-arm64@~1.1.0

# Linux ARM64
npm install @lydell/node-pty-linux-arm64@~1.2.0-beta.2

These are optional dependencies — the library works without them.

Usage

TypeScript (ESM)

import { getPty, spawnPty } from '@mmmbuto/pty-termux-utils';

// Get PTY implementation
const pty = await getPty();
if (pty) {
  console.log('Using provider:', pty.name); // 'mmmbuto-node-pty' or 'lydell-node-pty-linux-arm64'
  const proc = pty.module.spawn('bash', ['-c', 'echo test'], { cols: 80, rows: 24 });
  proc.on('data', (data) => console.log(data));
  proc.on('exit', (code, signal) => console.log(`Exit: ${code}`));
}

// Or spawn directly with error handling
try {
  const proc = await spawnPty('bash', ['-c', 'echo test'], { cols: 80, rows: 24 });
} catch (e) {
  if (e instanceof PtyError && e.code === 'NATIVE_NOT_FOUND') {
    // Fallback to child_process
  }
}

Fallback Pattern

import { getPty, createFallbackAdapter } from '@mmmbuto/pty-termux-utils';

const pty = await getPty();
let proc;

if (pty) {
  console.log('Using provider:', pty.name);
  proc = pty.module.spawn('bash', ['-c', 'echo test'], { cols: 80, rows: 24 });
} else {
  const adapter = createFallbackAdapter();
  proc = adapter.spawn('bash', ['-c', 'echo test'], { cols: 80, rows: 24 });
}

CommonJS (CJS)

const { getPty, createFallbackAdapter } = require('@mmmbuto/pty-termux-utils');

async function runCommand() {
  const pty = await getPty();
  if (pty) {
    const proc = pty.module.spawn('bash', ['-c', 'echo test'], { cols: 80, rows: 24 });
    // ... use proc
  }
}

runCommand();

Debug Logging

Enable debug logging:

PTY_DEBUG=1 npm run start

Output:

[PTY] Native module loaded: @mmmbuto/node-pty-android-arm64
[PTY] Using provider: mmmbuto-node-pty
[PTY] Native module not found, using fallback adapter
[PTY] Using fallback PTY adapter with child_process

API

getPty() → Promise<PtyImplementation | null>

Detect and load native PTY module. Returns null if unavailable.

spawnPty(file, args, options) → Promise<IPty>

Spawn a PTY process. Throws PtyError on failure.

createFallbackAdapter() → IPtyAdapter

Create a fallback adapter using child_process.

Types

  • IPty — PTY process interface
  • IPtyNativeImplementation — Native module interface
  • PtyImplementation — Union type for loaded implementation
  • PtyProviderName — Provider name union ('mmmbuto-node-pty' | 'lydell-node-pty-linux-arm64')
  • PtyError — Error with specific codes (NATIVE_NOT_FOUND, NATIVE_INVALID_EXPORT, SPAWN_FAILED, RESIZE_FAILED)

Architecture

Core Components

  1. getPty.ts — PTY Detection & Loading

    • Multi-provider strategy with priority
    • Dynamic import of native modules
    • Memoizes result (cached after first call)
    • Validates spawn function exists
  2. pty-adapter.ts — Fallback Adapter

    • Implements PTY-like interface using child_process
    • Handles stdout/stderr streams
    • Emits data and exit events
    • Provides write(), kill(), resize() (no-op)
  3. types.ts — Type Definitions

    • Type-safe PTY interfaces
    • Multi-provider name union
    • No dependency on optional module
  4. errors.ts — Error Handling

    • PtyError with specific codes
    • Graceful degradation
  5. config.ts — Configuration & Logging

    • PTY_DEBUG environment variable
    • [PTY] prefix logging

Integration Guide

For TypeScript Projects

  1. Add dependency:
npm install @mmmbuto/[email protected]
  1. Replace local getPty.ts with re-export:
export * from '@mmmbuto/pty-termux-utils';
  1. Update type imports:
// Before
import type { IPty } from '@mmmbuto/node-pty-android-arm64';

// After
import type { IPty } from '@mmmbuto/pty-termux-utils';
  1. Keep optional dependencies:
{
  "optionalDependencies": {
    "@mmmbuto/node-pty-android-arm64": "~1.1.0",
    "@lydell/node-pty-linux-arm64": "~1.2.0-beta.2"
  }
}

For CommonJS Projects

  1. Add dependency:
npm install @mmmbuto/[email protected]
  1. Create wrapper:
const { getPty, spawnPty } = require('@mmmbuto/pty-termux-utils');

module.exports = { getPty, spawnPty };

Behavior Matrix

| Platform | Arch | Termux? | Module Used | Fallback? | |----------|-------|----------|-------------|------------| | Android/Termux | arm64 | Yes | @mmmbuto/node-pty-android-arm64 | If module unavailable | | Linux | arm64 | No | @lydell/node-pty-linux-arm64 | If module unavailable | | Linux | x64 | No | Fallback (no ARM64 PTY) | Always | | Darwin (macOS) | arm64 | No | Fallback (no ARM64 PTY) | Always | | Win32 | arm64 | No | Fallback (no ARM64 PTY) | Always | | Other | Any | No | Fallback | Always |

Error Handling

PtyError Codes

| Code | Description | Handling | |------|-------------|----------| | NATIVE_NOT_FOUND | Module not installed | Use fallback adapter | | NATIVE_INVALID_EXPORT | Module missing spawn | Use fallback adapter | | SPAWN_FAILED | Process spawn failed | Log error, retry or fallback | | RESIZE_FAILED | Resize not supported | Log debug, ignore |

Performance

  • getPty() is memoized — only loads module once per process
  • Dynamic import only on supported platforms
  • Minimal overhead on unsupported platforms
  • Debug logging only when PTY_DEBUG=1

Related Projects

  • @mmmbuto/node-pty-android-arm64 — Native PTY module for Termux
  • @lydell/node-pty-linux-arm64 — Native PTY module for Linux ARM64
  • gemini-cli-termux — Gemini CLI using this library
  • qwen-code-termux — Qwen CLI using this library
  • nexuscli — Multi-model CLI using this library

Documentation

Changelog

See CHANGELOG.md for version history.

License

MIT