{"id":24743420,"url":"https://github.com/layerdynamics/node-rust-pty","last_synced_at":"2025-10-06T19:04:53.659Z","repository":{"id":257957321,"uuid":"871998293","full_name":"LayerDynamics/node-rust-pty","owner":"LayerDynamics","description":"A high-performance Node.js native module providing comprehensive PTY (pseudo-terminal) functionality with virtual DOM-based rendering and advanced session management, implemented in Rust with N-API bindings.","archived":false,"fork":false,"pushed_at":"2025-06-13T10:40:45.000Z","size":6476,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-06T19:04:43.158Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LayerDynamics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-13T14:24:11.000Z","updated_at":"2025-05-06T14:46:12.000Z","dependencies_parsed_at":"2024-10-17T04:53:18.248Z","dependency_job_id":"83135ba6-e5f3-4a2d-9415-91acbab1ae1a","html_url":"https://github.com/LayerDynamics/node-rust-pty","commit_stats":null,"previous_names":["layerdynamics/node-rust-pty"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/LayerDynamics/node-rust-pty","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerDynamics%2Fnode-rust-pty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerDynamics%2Fnode-rust-pty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerDynamics%2Fnode-rust-pty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerDynamics%2Fnode-rust-pty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LayerDynamics","download_url":"https://codeload.github.com/LayerDynamics/node-rust-pty/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerDynamics%2Fnode-rust-pty/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278663361,"owners_count":26024388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-28T01:36:08.559Z","updated_at":"2025-10-06T19:04:53.624Z","avatar_url":"https://github.com/LayerDynamics.png","language":"Rust","readme":"# node-rust-pty\n\nA high-performance Node.js native module providing comprehensive PTY (pseudo-terminal) functionality with virtual DOM-based rendering and advanced session management, implemented in Rust with N-API bindings.\n\n## Core Features \u0026 Implementation Details\n\n### PTY Process Management\n\n#### Process Creation and Lifecycle\n```typescript\n// Process initialization\nconst pty = await PtyHandle.new({\n  env: process.env,           // Environment variables\n  cwd: process.cwd(),        // Working directory\n  defaultShell: true         // Use system default shell\n});\n\n// Status monitoring\nconst status = await pty.status();\n// Returns: \"Running\" | \"Not Running\" | \"Unknown\"\n\n// Graceful shutdown with timeout\nawait pty.close({timeout: 5000});\n```\n\n#### Platform-Specific Implementations\n- **Linux**\n  - Uses `/dev/pts` for PTY allocation\n  - Full `termios` settings support\n  - Process group handling\n  ```rust\n  // Linux PTY creation (internal)\n  let master_fd = unsafe { posix_openpt(O_RDWR | O_NOCTTY) };\n  unsafe { grantpt(master_fd) };\n  unsafe { unlockpt(master_fd) };\n  ```\n\n- **macOS**\n  - Native PTY through BSD API\n  - Terminal attribute management\n  - Process group signals\n  ```rust\n  // macOS PTY handling (internal)\n  let mut master: libc::c_int = 0;\n  let mut slave: libc::c_int = 0;\n  let ret = unsafe { openpty(\u0026mut master, \u0026mut slave, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()) };\n  ```\n\n- **Windows**\n  - Basic process spawning\n  - Environment handling\n  - Working directory support\n\n### Virtual DOM Terminal Engine\n\n#### Core Virtual DOM Types\n```typescript\ninterface VNode {\n  type: 'text' | 'element';\n  content: string | VElement;\n}\n\ninterface VElement {\n  tag: string;\n  props: {\n    content?: string;\n    id?: string;\n    class?: string;\n    [key: string]: string | undefined;\n  };\n  styles: {\n    color?: 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white';\n    background?: string;\n    bold?: 'true' | 'false';\n    underline?: 'true' | 'false';\n    italic?: 'true' | 'false';\n    strikethrough?: 'true' | 'false';\n    [key: string]: string | undefined;\n  };\n  children: VNode[];\n}\n```\n\n#### Diff Engine Implementation\n```typescript\n// Available patch types\ntype Patch =\n  | { type: 'Replace'; node: VNode }\n  | { type: 'UpdateProps'; props: Record\u003cstring, string\u003e }\n  | { type: 'AppendChild'; node: VNode }\n  | { type: 'RemoveChild'; index: number }\n  | { type: 'UpdateText'; text: string }\n  | { type: 'None' };\n\n// Usage example\nconst oldNode = createTextNode(\"Hello\");\nconst newNode = createTextNode(\"Hello World\");\nconst patches = diff(oldNode, newNode);\n// Results in: [{ type: 'UpdateText', text: 'Hello World' }]\n```\n\n#### Renderer Capabilities\n```typescript\n// Text styling example\nconst styledOutput = {\n  type: 'element',\n  content: {\n    tag: 'text',\n    props: { content: 'Styled Output' },\n    styles: {\n      color: 'blue',\n      background: 'white',\n      bold: 'true',\n      underline: 'true'\n    },\n    children: []\n  }\n};\n\n// Render update\nawait pty.render(styledOutput);\n```\n\n### Session Management System\n\n#### Session Creation and Control\n```typescript\n// Create multiple sessions\nconst session1 = await pty.createSession();\nconst session2 = await pty.createSession();\n\n// Session operations\ninterface SessionOperations {\n  // Send data to specific session\n  sendToSession(\n    sessionId: number,\n    data: Buffer,\n    options?: {\n      flush?: boolean,      // Flush buffer immediately\n      encoding?: string,    // Buffer encoding\n      timeout?: number      // Operation timeout\n    }\n  ): Promise\u003cvoid\u003e;\n\n  // Read from session with options\n  readFromSession(\n    sessionId: number,\n    options?: {\n      maxBytes?: number,    // Maximum bytes to read\n      timeout?: number,     // Read timeout\n      encoding?: string     // Output encoding\n    }\n  ): Promise\u003cstring\u003e;\n\n  // Merge sessions\n  mergeSessions(\n    sessionIds: number[],\n    options?: {\n      primary?: number     // Primary session ID\n    }\n  ): Promise\u003cvoid\u003e;\n\n  // Split session\n  splitSession(\n    sessionId: number\n  ): Promise\u003c[number, number]\u003e;\n}\n```\n\n#### Session Buffer Management\n```typescript\n// Internal buffer management (Rust)\npub struct SessionBuffer {\n    input_buffer: Vec\u003cu8\u003e,\n    output_buffer: Arc\u003cMutex\u003cVec\u003cu8\u003e\u003e\u003e,\n    max_buffer_size: usize,\n    encoding: String,\n}\n\n// Buffer operations\nimpl SessionBuffer {\n    pub fn write(\u0026mut self, data: \u0026[u8]) -\u003e io::Result\u003cusize\u003e;\n    pub fn read(\u0026mut self, max_bytes: Option\u003cusize\u003e) -\u003e io::Result\u003cVec\u003cu8\u003e\u003e;\n    pub fn flush(\u0026mut self) -\u003e io::Result\u003c()\u003e;\n    pub fn clear(\u0026mut self);\n}\n```\n\n### Text Processing Engine\n\n#### ASCII/ANSI Parser\n```typescript\n// Supported ANSI sequences\nconst ANSISupport = {\n  cursor: {\n    up: '\\x1b[{n}A',\n    down: '\\x1b[{n}B',\n    forward: '\\x1b[{n}C',\n    backward: '\\x1b[{n}D',\n    nextLine: '\\x1b[{n}E',\n    prevLine: '\\x1b[{n}F',\n    setPosition: '\\x1b[{line};{column}H'\n  },\n  clear: {\n    screen: '\\x1b[2J',\n    line: '\\x1b[2K',\n    toEnd: '\\x1b[0J',\n    toStart: '\\x1b[1J'\n  },\n  style: {\n    reset: '\\x1b[0m',\n    bold: '\\x1b[1m',\n    dim: '\\x1b[2m',\n    italic: '\\x1b[3m',\n    underline: '\\x1b[4m',\n    reverse: '\\x1b[7m'\n  },\n  color: {\n    // Foreground colors\n    black: '\\x1b[30m',\n    red: '\\x1b[31m',\n    green: '\\x1b[32m',\n    yellow: '\\x1b[33m',\n    blue: '\\x1b[34m',\n    magenta: '\\x1b[35m',\n    cyan: '\\x1b[36m',\n    white: '\\x1b[37m',\n    // Background colors\n    bgBlack: '\\x1b[40m',\n    bgRed: '\\x1b[41m',\n    bgGreen: '\\x1b[42m',\n    bgYellow: '\\x1b[43m',\n    bgBlue: '\\x1b[44m',\n    bgMagenta: '\\x1b[45m',\n    bgCyan: '\\x1b[46m',\n    bgWhite: '\\x1b[47m'\n  }\n};\n```\n\n#### Input Event Handling\n```typescript\n// Available input events\ninterface InputEvent {\n  type: 'keypress' | 'keydown' | 'keyup';\n  key: string;\n  modifiers: {\n    ctrl: boolean;\n    alt: boolean;\n    shift: boolean;\n    meta: boolean;\n  };\n  raw: number[];  // Raw byte sequence\n}\n\n// Event handling example\npty.on('input', (event: InputEvent) =\u003e {\n  if (event.type === 'keypress' \u0026\u0026 event.modifiers.ctrl \u0026\u0026 event.key === 'c') {\n    // Handle Ctrl+C\n  }\n});\n```\n\n## Installation \u0026 Setup\n\n### Prerequisites\n```bash\n# Linux build dependencies\nsudo apt-get install -y \\\n  build-essential \\\n  pkg-config \\\n  libssl-dev\n\n# macOS build dependencies\nxcode-select --install\n\n# Windows build dependencies\n# Ensure you have Visual Studio Build Tools with Windows SDK\n```\n\n### Installation\n```bash\n# NPM installation\nnpm install node-rust-pty\n\n# Yarn installation\nyarn add node-rust-pty\n\n# Build from source\ngit clone https://github.com/layerdynamics/node-rust-pty.git\ncd node-rust-pty\nnpm install\nnpm run build\n```\n\n## Usage Examples\n\n### Basic Terminal Session\n```typescript\nimport { PtyHandle } from 'node-rust-pty';\n\nasync function basicTerminal() {\n  const pty = await PtyHandle.new();\n  const session = await pty.createSession();\n\n  // Execute command\n  await pty.sendToSession(session, Buffer.from('ls -la\\n'));\n\n  // Read with timeout\n  const output = await pty.readFromSession(session, {\n    timeout: 1000,\n    maxBytes: 4096\n  });\n\n  console.log('Command output:', output);\n  await pty.removeSession(session);\n  await pty.close();\n}\n```\n\n### Styled Terminal Output\n```typescript\nimport { PtyHandle, VNode } from 'node-rust-pty';\n\nasync function styledOutput() {\n  const pty = await PtyHandle.new();\n  const session = await pty.createSession();\n\n  // Create styled header\n  const header: VNode = {\n    type: 'element',\n    content: {\n      tag: 'text',\n      props: {\n        content: '=== Terminal Output ===\\n',\n        id: 'header'\n      },\n      styles: {\n        color: 'blue',\n        bold: 'true',\n        underline: 'true'\n      },\n      children: []\n    }\n  };\n\n  // Create content node\n  const content: VNode = {\n    type: 'element',\n    content: {\n      tag: 'text',\n      props: {\n        content: 'Command output below:\\n',\n        class: 'output'\n      },\n      styles: {\n        color: 'green'\n      },\n      children: []\n    }\n  };\n\n  // Render both nodes\n  await pty.render(header);\n  await pty.render(content);\n\n  // Execute command with styled output\n  await pty.sendToSession(session, Buffer.from('echo \"Hello World\"\\n'));\n\n  await pty.close();\n}\n```\n\n### Multiple Session Management\n```typescript\nimport { PtyHandle } from 'node-rust-pty';\n\nasync function multiSession() {\n  const pty = await PtyHandle.new();\n\n  // Create multiple sessions\n  const sessions = await Promise.all([\n    pty.createSession(),\n    pty.createSession(),\n    pty.createSession()\n  ]);\n\n  // Send different commands to each session\n  await Promise.all([\n    pty.sendToSession(sessions[0], Buffer.from('echo \"Session 1\"\\n')),\n    pty.sendToSession(sessions[1], Buffer.from('echo \"Session 2\"\\n')),\n    pty.sendToSession(sessions[2], Buffer.from('echo \"Session 3\"\\n'))\n  ]);\n\n  // Read from all sessions\n  const outputs = await Promise.all(\n    sessions.map(sid =\u003e pty.readFromSession(sid))\n  );\n\n  // Merge first two sessions\n  await pty.mergeSessions([sessions[0], sessions[1]]);\n\n  // Split remaining session\n  const [newSession1, newSession2] = await pty.splitSession(sessions[2]);\n\n  // Cleanup\n  await pty.closeAllSessions();\n  await pty.close();\n}\n```\n\n## Configuration\n\n### TypeScript Configuration\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true\n  },\n  \"include\": [\n    \"index.ts\",\n    \"index.d.ts\",\n    \"npm/prebuilds/*.d.ts\"\n  ]\n}\n```\n\n### Build Configuration\n```json\n{\n  \"napi\": {\n    \"name\": \"node-rust-pty\",\n    \"triples\": {\n      \"defaults\": true,\n      \"additional\": [\n        \"aarch64-apple-darwin\",\n        \"x86_64-unknown-linux-gnu\",\n        \"aarch64-unknown-linux-gnu\"\n      ]\n    }\n  }\n}\n```\n\n## Development Commands\n```bash\n# Build commands\nnpm run build              # Build everything\nnpm run build:ts          # Build TypeScript only\nnpm run build:debug       # Debug build\nnpm run clean            # Clean build artifacts\n\n# Testing\nnpm test                 # Run all tests\nnpm test -- --watch     # Watch mode\n\n# Publishing\nnpm run prepublishOnly  # Prepare for publishing\n```\n\n## Current Limitations\n\n1. PTY Process Limitations:\n   - Windows support lacks full ConPTY integration\n   - Limited process group signal handling on Windows\n   - No job control support\n\n2. Terminal Emulation:\n   - Subset of VT100/VT220 sequences supported\n   - Limited mouse input support\n   - Basic color palette (8 colors + backgrounds)\n\n3. Session Management:\n   - In-memory session storage only\n   - No persistent sessions\n   - Limited session sharing capabilities\n\n4. Performance Considerations:\n   - Large output buffers may impact memory usage\n   - Virtual DOM updates may be CPU intensive\n   - No hardware acceleration\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Support \u0026 Documentation\n\n- Issue Tracker: GitHub Issues\n- API Documentation: See `docs/` directory\n- Examples: See `examples/` directory\n- Technical Documentation: See `docs/technical/`\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed contribution guidelines.\n\nKey areas for contribution:\n1. Windows ConPTY integration\n2. Additional terminal sequences\n3. Performance optimizations\n4. Testing improvements\n\n## Credits\n\nBuilt with:\n- [Rust](https://www.rust-lang.org/)\n- [N-API](https://nodejs.org/api/n-api.html)\n- [Tokio](https://tokio.rs/)\n- [TypeScript](https://www.typescriptlang.org/)\n\n## Version History\n\nSee [CHANGELOG.md](CHANGELOG.md) for detailed version history.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayerdynamics%2Fnode-rust-pty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flayerdynamics%2Fnode-rust-pty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayerdynamics%2Fnode-rust-pty/lists"}