Cross-platform pseudoterminal (PTY) implementation for Bun with native performance (fork of bun-pty)
npm install @zenyr/bun-pty


A cross-platform pseudo-terminal (PTY) implementation for Bun runtime, powered by Rust's portable-pty library and Bun's FFI capabilities.
> ⚠️ Bun Runtime Required: This package uses bun:ffi and Bun-specific APIs. For Node.js, please use node-pty instead.
> Note: This is a fork of bun-pty (v0.3.2) with significant improvements and architectural changes.
This fork adds the following improvements over the original bun-pty:
bun_pty_write FFI bindings and removed unnecessary null terminatorsBUN_PTY_LIB environment variableThe following improvements have been submitted as pull requests to the upstream repository:
- #10 - Fix: Report actual process exit code instead of hardcoded 0 - Fixes exit code handling bug
- #11 - Fix bash -c argument handling and FFI bindings - Fixes argument quoting and FFI binding issues
These fixes are already included in this fork (v0.3.3+) and are pending review in the upstream repository.
- Cross-platform - Works on macOS, Linux, and Windows
- Simple API - Clean Promise-based API similar to node-pty
- Type-safe - Complete TypeScript definitions included
- Efficient - Rust backend with proper error handling and multithreading
- Zero dependencies - No external JavaScript dependencies required
- Modern - Built specifically for Bun using its FFI capabilities
``bash`
bun add @zenyr/bun-pty
The package automatically installs the correct native library for your platform. Platform-specific packages are installed as optional dependencies:
- @zenyr/bun-pty-linux-x64 - Linux x86_64@zenyr/bun-pty-linux-arm64
- - Linux ARM64@zenyr/bun-pty-darwin-x64
- - macOS x86_64 (Intel)@zenyr/bun-pty-darwin-arm64
- - macOS ARM64 (Apple Silicon)@zenyr/bun-pty-win32-x64
- - Windows x86_64
> Note: Only the platform-specific package matching your system will be downloaded, keeping installation size minimal (~600KB instead of ~3-4MB).
Installing from GitHub requires building from source (Rust toolchain needed):
`bash`
bun add github:zenyr/bun-pty --trust
Important: GitHub installations include source code and require the Rust toolchain (cargo) to build. Bun requires explicit permission to run build scripts. Use the --trust flag or add to trustedDependencies:
`json`
{
"dependencies": {
"@zenyr/bun-pty": "github:zenyr/bun-pty"
},
"trustedDependencies": [
"@zenyr/bun-pty"
]
}
> Tip: For production use, prefer the npm package which includes prebuilt binaries and doesn't require Rust.
- Bun 1.0.0 or higher
- Rust toolchain (cargo) is required only when installing from GitHub or building from source
- TypeScript (included as devDependency)
| Platform | Status | Notes |
|----------|--------|-------|
| macOS | ✅ | Fully supported |
| Linux | ✅ | Fully supported |
| Windows | ✅ | Fully supported |
`typescript
import { spawn } from "@zenyr/bun-pty";
// Create a new terminal
const terminal = spawn("bash", [], {
name: "xterm-256color",
cols: 80,
rows: 24
});
// Handle data from the terminal
terminal.onData((data) => {
console.log("Received:", data);
});
// Handle terminal exit
terminal.onExit(({ exitCode, signal }) => {
console.log(Process exited with code ${exitCode} and signal ${signal});
});
// Write to the terminal
terminal.write("echo Hello from Bun PTY\n");
// Resize the terminal
terminal.resize(100, 40);
// Kill the process when done
setTimeout(() => {
terminal.kill();
}, 5000);
`
The library includes complete TypeScript definitions. Here's how to use it with full type safety:
`typescript
import { spawn } from "@zenyr/bun-pty";
import type { IPty, IExitEvent, IPtyForkOptions } from "@zenyr/bun-pty";
// Create typed options
const options: IPtyForkOptions = {
name: "xterm-256color",
cols: 100,
rows: 30,
cwd: process.cwd()
};
// Create a terminal with proper typing
const terminal: IPty = spawn("bash", [], options);
// Typed event handlers
const dataHandler = terminal.onData((data: string) => {
process.stdout.write(data);
});
const exitHandler = terminal.onExit((event: IExitEvent) => {
console.log(Process exited with code: ${event.exitCode});
});
// Clean up when done
dataHandler.dispose();
exitHandler.dispose();
`
`typescript
import { spawn } from "@zenyr/bun-pty";
import { createInterface } from "node:readline";
// Create a PTY running bash
const pty = spawn("bash", [], {
name: "xterm-256color",
cwd: process.cwd()
});
// Forward PTY output to stdout
pty.onData((data) => {
process.stdout.write(data);
});
// Send user input to the PTY
process.stdin.on("data", (data) => {
pty.write(data.toString());
});
// Handle PTY exit
pty.onExit(() => {
console.log("Terminal session ended");
process.exit(0);
});
// Handle SIGINT (Ctrl+C)
process.on("SIGINT", () => {
pty.kill();
});
`
Creates and spawns a new pseudoterminal.
- file: The executable to launchargs
- : Arguments to pass to the executableoptions
- : Configuration optionsname
- : Terminal name (e.g., "xterm-256color")cols
- : Number of columns (default: 80)rows
- : Number of rows (default: 24)cwd
- : Working directory (default: process.cwd())env
- : Environment variables
Returns an IPty instance.
`typescript`
interface IPty {
// Properties
readonly pid: number; // Process ID
readonly cols: number; // Current columns
readonly rows: number; // Current rows
readonly process: string; // Process name
// Events
onData: (listener: (data: string) => void) => IDisposable;
onExit: (listener: (event: IExitEvent) => void) => IDisposable;
// Methods
write(data: string): void; // Write data to terminal
resize(cols: number, rows: number): void; // Resize terminal
kill(signal?: string): void; // Kill the process
}
`typescript
interface IExitEvent {
exitCode: number;
signal?: number | string;
}
interface IDisposable {
dispose(): void;
}
`
If you want to build the package from source:
`bashClone the repository
git clone https://github.com/zenyr/bun-pty.git
cd bun-pty
❓ Troubleshooting
$3
The npm package uses platform-specific optional dependencies to provide prebuilt binaries. Each platform package contains only the native library for that specific OS and architecture.
If you encounter issues with the prebuilt binaries:
1. Check if the platform package was installed:
`bash
ls node_modules/@zenyr/bun-pty-*/
`2. Force reinstall the platform package:
`bash
bun add @zenyr/bun-pty --force
`3. Build from source (development only):
`bash
cd node_modules/@zenyr/bun-pty
bun run build
`$3
You can specify a custom path to the native library using the
BUN_PTY_LIB environment variable:`bash
export BUN_PTY_LIB=/path/to/librust_pty.dylib
bun run your-script.ts
`$3
- Error: librust_pty shared library not found
- Make sure the appropriate platform package is installed
- Check that your OS and architecture match one of the supported platforms
- Try reinstalling with
bun add @zenyr/bun-pty --force- Error: Unable to load shared library
- Ensure you have the necessary system libraries installed
- On Linux, you may need
libc6` and related dependencies- Process spawn fails
- Check if you have the required permissions and paths
- Verify the executable exists and is in your PATH
This project is licensed under the MIT License.
- Forked from bun-pty by @sursaone
- Built specifically for Bun
- Uses portable-pty from WezTerm for cross-platform PTY support
- Inspired by node-pty for the API design