@hienlh/ppm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agent-memory/tester/MEMORY.md +3 -0
- package/.claude/agent-memory/tester/project-ppm-test-conventions.md +32 -0
- package/.env.example +1 -0
- package/.github/workflows/release.yml +46 -0
- package/README.md +349 -0
- package/bun.lock +1217 -0
- package/components.json +21 -0
- package/docs/code-standards.md +574 -0
- package/docs/codebase-summary.md +294 -0
- package/docs/deployment-guide.md +631 -0
- package/docs/design-guidelines.md +661 -0
- package/docs/project-overview-pdr.md +142 -0
- package/docs/project-roadmap.md +400 -0
- package/docs/system-architecture.md +459 -0
- package/package.json +68 -0
- package/plans/260314-2009-ppm-implementation/phase-01-project-skeleton.md +81 -0
- package/plans/260314-2009-ppm-implementation/phase-02-backend-core.md +148 -0
- package/plans/260314-2009-ppm-implementation/phase-03-frontend-shell.md +256 -0
- package/plans/260314-2009-ppm-implementation/phase-04-file-explorer-editor.md +120 -0
- package/plans/260314-2009-ppm-implementation/phase-05-web-terminal.md +174 -0
- package/plans/260314-2009-ppm-implementation/phase-06-git-integration.md +244 -0
- package/plans/260314-2009-ppm-implementation/phase-07-ai-chat.md +242 -0
- package/plans/260314-2009-ppm-implementation/phase-08-cli-commands.md +143 -0
- package/plans/260314-2009-ppm-implementation/phase-09-pwa-build-deploy.md +209 -0
- package/plans/260314-2009-ppm-implementation/phase-10-testing.md +311 -0
- package/plans/260314-2009-ppm-implementation/plan.md +202 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-01-backend-project-router.md +145 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-02-frontend-api-migration.md +107 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-03-per-project-tabs.md +100 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-04-websocket-migration.md +66 -0
- package/plans/260315-0356-project-scoped-api-refactor/plan.md +87 -0
- package/plans/reports/brainstorm-260314-1938-final-techstack.md +342 -0
- package/plans/reports/docs-manager-260315-1314-documentation-creation.md +386 -0
- package/plans/reports/fullstack-developer-260314-2252-phase-02-backend-core.md +57 -0
- package/plans/reports/fullstack-developer-260314-2253-phase-03-frontend-shell.md +70 -0
- package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-api-terminal-ws.md +49 -0
- package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-explorer-editor-terminal.md +52 -0
- package/plans/reports/fullstack-developer-260314-2307-ai-chat-phase7.md +58 -0
- package/plans/reports/fullstack-developer-260314-2307-phase-06-git-integration.md +33 -0
- package/plans/reports/research-260314-1911-ppm-tech-stack.md +318 -0
- package/plans/reports/research-260314-1930-claude-code-integration.md +293 -0
- package/plans/reports/researcher-260314-2232-node-pty-bun-crash-analysis.md +305 -0
- package/plans/reports/researcher-260314-2232-ui-style.md +942 -0
- package/plans/reports/researcher-260315-0300-opcode-claude-interaction.md +745 -0
- package/plans/reports/researcher-260315-0303-opcode-deep-analysis.md +742 -0
- package/plans/reports/researcher-260315-0305-claude-agent-sdk-github-research.md +423 -0
- package/plans/reports/tester-260314-2053-initial-test-suite.md +81 -0
- package/ppm.example.yaml +14 -0
- package/repomix-output.xml +23745 -0
- package/scripts/build.ts +13 -0
- package/src/cli/commands/chat-cmd.ts +259 -0
- package/src/cli/commands/config-cmd.ts +121 -0
- package/src/cli/commands/git-cmd.ts +315 -0
- package/src/cli/commands/init.ts +57 -0
- package/src/cli/commands/open.ts +19 -0
- package/src/cli/commands/projects.ts +100 -0
- package/src/cli/commands/start.ts +3 -0
- package/src/cli/commands/stop.ts +33 -0
- package/src/cli/utils/project-resolver.ts +27 -0
- package/src/index.ts +59 -0
- package/src/providers/claude-agent-sdk.ts +499 -0
- package/src/providers/claude-binary-finder.ts +256 -0
- package/src/providers/claude-code-cli.ts +413 -0
- package/src/providers/claude-process-registry.ts +106 -0
- package/src/providers/mock-provider.ts +171 -0
- package/src/providers/provider.interface.ts +10 -0
- package/src/providers/registry.ts +45 -0
- package/src/server/helpers/resolve-project.ts +22 -0
- package/src/server/index.ts +181 -0
- package/src/server/middleware/auth.ts +30 -0
- package/src/server/routes/chat.ts +153 -0
- package/src/server/routes/files.ts +168 -0
- package/src/server/routes/git.ts +261 -0
- package/src/server/routes/project-scoped.ts +27 -0
- package/src/server/routes/projects.ts +57 -0
- package/src/server/routes/static.ts +26 -0
- package/src/server/ws/chat.ts +130 -0
- package/src/server/ws/terminal.ts +89 -0
- package/src/services/chat.service.ts +110 -0
- package/src/services/claude-usage.service.ts +113 -0
- package/src/services/config.service.ts +90 -0
- package/src/services/file.service.ts +261 -0
- package/src/services/git-dirs.service.ts +112 -0
- package/src/services/git.service.ts +372 -0
- package/src/services/project.service.ts +107 -0
- package/src/services/slash-items.service.ts +184 -0
- package/src/services/terminal.service.ts +212 -0
- package/src/types/api.ts +37 -0
- package/src/types/chat.ts +92 -0
- package/src/types/config.ts +41 -0
- package/src/types/git.ts +50 -0
- package/src/types/project.ts +18 -0
- package/src/types/terminal.ts +20 -0
- package/src/web/app.tsx +168 -0
- package/src/web/components/auth/login-screen.tsx +88 -0
- package/src/web/components/chat/attachment-chips.tsx +55 -0
- package/src/web/components/chat/chat-placeholder.tsx +10 -0
- package/src/web/components/chat/chat-tab.tsx +301 -0
- package/src/web/components/chat/file-picker.tsx +126 -0
- package/src/web/components/chat/message-input.tsx +420 -0
- package/src/web/components/chat/message-list.tsx +838 -0
- package/src/web/components/chat/session-picker.tsx +139 -0
- package/src/web/components/chat/slash-command-picker.tsx +135 -0
- package/src/web/components/chat/usage-badge.tsx +186 -0
- package/src/web/components/editor/code-editor.tsx +329 -0
- package/src/web/components/editor/diff-viewer.tsx +276 -0
- package/src/web/components/editor/editor-placeholder.tsx +10 -0
- package/src/web/components/explorer/file-actions.tsx +191 -0
- package/src/web/components/explorer/file-tree.tsx +298 -0
- package/src/web/components/git/git-graph.tsx +727 -0
- package/src/web/components/git/git-placeholder.tsx +55 -0
- package/src/web/components/git/git-status-panel.tsx +850 -0
- package/src/web/components/layout/mobile-drawer.tsx +137 -0
- package/src/web/components/layout/mobile-nav.tsx +103 -0
- package/src/web/components/layout/sidebar.tsx +90 -0
- package/src/web/components/layout/tab-bar.tsx +152 -0
- package/src/web/components/layout/tab-content.tsx +85 -0
- package/src/web/components/projects/dir-suggest.tsx +152 -0
- package/src/web/components/projects/project-list.tsx +187 -0
- package/src/web/components/settings/settings-tab.tsx +57 -0
- package/src/web/components/terminal/terminal-placeholder.tsx +10 -0
- package/src/web/components/terminal/terminal-tab.tsx +133 -0
- package/src/web/components/ui/button.tsx +64 -0
- package/src/web/components/ui/context-menu.tsx +250 -0
- package/src/web/components/ui/dialog.tsx +156 -0
- package/src/web/components/ui/dropdown-menu.tsx +257 -0
- package/src/web/components/ui/input.tsx +21 -0
- package/src/web/components/ui/scroll-area.tsx +56 -0
- package/src/web/components/ui/separator.tsx +26 -0
- package/src/web/components/ui/sonner.tsx +40 -0
- package/src/web/components/ui/tabs.tsx +91 -0
- package/src/web/components/ui/tooltip.tsx +57 -0
- package/src/web/hooks/use-chat.ts +420 -0
- package/src/web/hooks/use-terminal.ts +182 -0
- package/src/web/hooks/use-url-sync.ts +66 -0
- package/src/web/hooks/use-websocket.ts +48 -0
- package/src/web/index.html +16 -0
- package/src/web/lib/api-client.ts +90 -0
- package/src/web/lib/file-support.ts +68 -0
- package/src/web/lib/utils.ts +6 -0
- package/src/web/lib/ws-client.ts +100 -0
- package/src/web/main.tsx +10 -0
- package/src/web/public/icon-192.svg +5 -0
- package/src/web/public/icon-512.svg +5 -0
- package/src/web/stores/file-store.ts +81 -0
- package/src/web/stores/project-store.ts +50 -0
- package/src/web/stores/settings-store.ts +65 -0
- package/src/web/stores/tab-store.ts +187 -0
- package/src/web/styles/globals.css +227 -0
- package/src/web/vite-env.d.ts +1 -0
- package/tests/integration/api/chat-routes.test.ts +95 -0
- package/tests/integration/claude-agent-sdk-integration.test.ts +228 -0
- package/tests/integration/ws/chat-websocket.test.ts +312 -0
- package/tests/test-setup.ts +5 -0
- package/tests/unit/providers/claude-agent-sdk.test.ts +339 -0
- package/tests/unit/providers/mock-provider.test.ts +143 -0
- package/tests/unit/services/chat-service.test.ts +100 -0
- package/tsconfig.json +32 -0
- package/vite.config.ts +62 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# Research Report: node-pty Crash in Bun Runtime
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-14
|
|
4
|
+
**Researcher:** Claude Code
|
|
5
|
+
**Context:** PPM v1 crashed when node-pty `posix_spawnp` was called in WebSocket handlers. v2 must avoid this.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Executive Summary
|
|
10
|
+
|
|
11
|
+
**Root Cause:** node-pty uses NAN (Native Abstractions for Node.js), not NAPI. Bun's runtime cannot resolve the required C++ symbols (`_node_module_register`, V8 API, libuv symbols), causing dyld linking errors on macOS and runtime crashes.
|
|
12
|
+
|
|
13
|
+
**Status:** This is a **hard incompatibility** — node-pty fundamentally cannot work with Bun's current architecture. No patches or workarounds exist.
|
|
14
|
+
|
|
15
|
+
**Recommended Path for PPM v2:** Use **Bun.spawn() with the native Terminal API** (POSIX-only, but acceptable for dev environment). Fallback to `script -q /dev/null` wrapper if resize features needed.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Root Cause Analysis
|
|
20
|
+
|
|
21
|
+
### The Incompatibility Chain
|
|
22
|
+
|
|
23
|
+
1. **node-pty Architecture**
|
|
24
|
+
- Built on NAN (Native Abstractions for Node.js) — pre-2015 binding system
|
|
25
|
+
- Compiles to `pty.node` native addon with C++ code
|
|
26
|
+
- Requires V8 C++ APIs, libuv symbols, and the `_node_module_register` symbol at runtime
|
|
27
|
+
|
|
28
|
+
2. **Bun's Module System**
|
|
29
|
+
- Implements NAPI (modern Node.js API) but NOT NAN
|
|
30
|
+
- Cannot resolve `_node_module_register` or most V8 C++ symbols
|
|
31
|
+
- Module loading fails immediately on `require('node-pty')`
|
|
32
|
+
|
|
33
|
+
3. **Why It Crashes in WebSocket Context**
|
|
34
|
+
- Even if module loads partially, `posix_spawnp` syscall invocation in node-pty's native code crashes due to incomplete symbol binding
|
|
35
|
+
- Happens specifically in WebSocket handler because that's where PTY spawn is called
|
|
36
|
+
- Segfault takes down entire Bun process (no error catching possible)
|
|
37
|
+
|
|
38
|
+
### Upstream Status
|
|
39
|
+
|
|
40
|
+
- **node-pty issue #632** (2024): Maintainers confirmed "Bun doesn't work with `nan`/`napi` so this isn't possible"
|
|
41
|
+
- **node-pty PR #644** (ongoing): Effort to port to NAPI, but still incomplete and unstable
|
|
42
|
+
- **Bun issue #4290** (2024-2026): Bun team tracking V8 C++ API support, no ETA
|
|
43
|
+
- **Closure:** Both projects closed Bun-related issues as "not planned"
|
|
44
|
+
|
|
45
|
+
**Verdict:** Don't wait for fixes. This won't be solved in the foreseeable future.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## What Works in claude_remote
|
|
50
|
+
|
|
51
|
+
Checked `/Users/hienlh/claude_remote/codepeer/`:
|
|
52
|
+
|
|
53
|
+
- **package.json:** Declares `node-pty@^1.0.0` as dependency
|
|
54
|
+
- **terminal.js:** Frontend-only file — uses xterm.js client-side, doesn't interact with PTY
|
|
55
|
+
- **Architecture:** Claude_remote is a **Node.js** project, not Bun — that's why node-pty works there
|
|
56
|
+
|
|
57
|
+
**Key Difference:** If claude_remote were ported to Bun, it would crash immediately on PTY spawn.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Recommended Approaches for PPM v2
|
|
62
|
+
|
|
63
|
+
### Option 1: Bun.spawn() with Native Terminal API ✅ RECOMMENDED
|
|
64
|
+
|
|
65
|
+
**Pros:**
|
|
66
|
+
- Zero external dependencies
|
|
67
|
+
- Built into Bun runtime, fully compatible
|
|
68
|
+
- Supports PTY features: colors, cursor movement, interactive input
|
|
69
|
+
- Can resize with `terminal.resize(cols, rows)`
|
|
70
|
+
- Simplest implementation
|
|
71
|
+
|
|
72
|
+
**Cons:**
|
|
73
|
+
- POSIX only (Linux, macOS) — but acceptable for web IDE dev environment
|
|
74
|
+
- Windows developers must use WSL or fall back to raw pipes
|
|
75
|
+
|
|
76
|
+
**Implementation:**
|
|
77
|
+
```typescript
|
|
78
|
+
// src/services/terminal.service.ts
|
|
79
|
+
import { Subprocess } from 'bun';
|
|
80
|
+
|
|
81
|
+
interface TerminalSession {
|
|
82
|
+
id: string;
|
|
83
|
+
proc: Subprocess;
|
|
84
|
+
terminal: Terminal;
|
|
85
|
+
projectPath: string;
|
|
86
|
+
createdAt: Date;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class TerminalService {
|
|
90
|
+
private sessions: Map<string, TerminalSession> = new Map();
|
|
91
|
+
|
|
92
|
+
create(projectPath: string, shell: string = 'bash'): string {
|
|
93
|
+
const id = crypto.randomUUID();
|
|
94
|
+
let output = '';
|
|
95
|
+
|
|
96
|
+
const proc = Bun.spawn([shell], {
|
|
97
|
+
cwd: projectPath,
|
|
98
|
+
terminal: {
|
|
99
|
+
cols: 80,
|
|
100
|
+
rows: 24,
|
|
101
|
+
data(terminal, chunk) {
|
|
102
|
+
output += chunk.toString();
|
|
103
|
+
// Emit to all connected WebSocket clients
|
|
104
|
+
// (bridge via eventBus or direct WS handler)
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.sessions.set(id, {
|
|
110
|
+
id,
|
|
111
|
+
proc,
|
|
112
|
+
terminal: proc.terminal!,
|
|
113
|
+
projectPath,
|
|
114
|
+
createdAt: new Date(),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return id;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
write(id: string, data: string): void {
|
|
121
|
+
const session = this.sessions.get(id);
|
|
122
|
+
if (session) {
|
|
123
|
+
session.terminal.write(data);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
resize(id: string, cols: number, rows: number): void {
|
|
128
|
+
const session = this.sessions.get(id);
|
|
129
|
+
if (session) {
|
|
130
|
+
session.terminal.resize(cols, rows);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
kill(id: string): void {
|
|
135
|
+
const session = this.sessions.get(id);
|
|
136
|
+
if (session) {
|
|
137
|
+
session.terminal.close();
|
|
138
|
+
session.proc.kill();
|
|
139
|
+
this.sessions.delete(id);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**WebSocket Handler:**
|
|
146
|
+
```typescript
|
|
147
|
+
// src/server/ws/terminal.ts
|
|
148
|
+
import { TerminalService } from '../services/terminal.service';
|
|
149
|
+
|
|
150
|
+
const terminalService = new TerminalService();
|
|
151
|
+
|
|
152
|
+
export function handleTerminalWS(ws: WebSocket, req: Request) {
|
|
153
|
+
const sessionId = extractSessionId(req); // from URL
|
|
154
|
+
|
|
155
|
+
ws.onmessage = (event) => {
|
|
156
|
+
const msg = JSON.parse(event.data);
|
|
157
|
+
|
|
158
|
+
if (msg.type === 'input') {
|
|
159
|
+
terminalService.write(sessionId, msg.data);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (msg.type === 'resize') {
|
|
163
|
+
terminalService.resize(sessionId, msg.cols, msg.rows);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
ws.onerror = () => terminalService.kill(sessionId);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### Option 2: Bun.spawn() + `script -q /dev/null` Wrapper
|
|
174
|
+
|
|
175
|
+
**Use Case:** If targeting Windows or need maximum compatibility.
|
|
176
|
+
|
|
177
|
+
**How It Works:**
|
|
178
|
+
```bash
|
|
179
|
+
script -q /dev/null /bin/bash
|
|
180
|
+
```
|
|
181
|
+
The `script` utility (POSIX standard) allocates a PTY and runs the shell inside it.
|
|
182
|
+
|
|
183
|
+
**Pros:**
|
|
184
|
+
- Works on macOS and Linux
|
|
185
|
+
- No dependencies
|
|
186
|
+
- Allocates true PTY without node-pty
|
|
187
|
+
|
|
188
|
+
**Cons:**
|
|
189
|
+
- Extra process overhead (script utility wrapper)
|
|
190
|
+
- Less direct control over PTY
|
|
191
|
+
- Platform-specific edge cases
|
|
192
|
+
|
|
193
|
+
**Implementation:**
|
|
194
|
+
```typescript
|
|
195
|
+
const proc = Bun.spawn(['script', '-q', '/dev/null', 'bash'], {
|
|
196
|
+
cwd: projectPath,
|
|
197
|
+
terminal: {
|
|
198
|
+
cols: 80,
|
|
199
|
+
rows: 24,
|
|
200
|
+
data(terminal, chunk) {
|
|
201
|
+
// Handle output
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Not Recommended for PPM:** Option 1 is simpler and more direct.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Option 3: Bun.spawn() + Raw Pipes (No PTY)
|
|
212
|
+
|
|
213
|
+
**Use Case:** Windows-only fallback, or if PTY features not critical.
|
|
214
|
+
|
|
215
|
+
**Pros:**
|
|
216
|
+
- Cross-platform (Windows, Linux, macOS)
|
|
217
|
+
- Works with raw process I/O
|
|
218
|
+
|
|
219
|
+
**Cons:**
|
|
220
|
+
- No terminal features: colors, cursor movement, job control fail
|
|
221
|
+
- `Ctrl+C` kills Bun process instead of shell
|
|
222
|
+
- Shell behaves as non-interactive
|
|
223
|
+
|
|
224
|
+
**Not Recommended:** Degrades user experience significantly. Use Option 1 instead.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
### Option 4: Avoid PTY in v2, Use `bun-pty` Later
|
|
229
|
+
|
|
230
|
+
**Context:** Community package `@skitee3000/bun-pty` exists on npm.
|
|
231
|
+
|
|
232
|
+
**Status:** Bun-specific library built with Bun's FFI (Foreign Function Interface) to Rust's portable-pty. Early stage, not production-tested.
|
|
233
|
+
|
|
234
|
+
**Decision:** Skip for now. Option 1 (native Bun Terminal API) is more stable and maintainable.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Compilation with `bun build --compile`
|
|
239
|
+
|
|
240
|
+
**Question from Task:** Can Bun.spawn() work when code is compiled with `bun build --compile`?
|
|
241
|
+
|
|
242
|
+
**Answer:** YES, but with important caveats.
|
|
243
|
+
|
|
244
|
+
- **Bun.spawn() works fine** — it's native Bun API, included in compiled binary
|
|
245
|
+
- **PTY support is included** — `terminal` option works in compiled apps
|
|
246
|
+
- **Shell availability required** — compiled app must run on system with bash/zsh at runtime
|
|
247
|
+
- **Caveat:** If compiled as standalone binary on macOS, ensure $PATH includes system shells
|
|
248
|
+
|
|
249
|
+
**Recommended:** For distributed compiled binaries, fall back to raw pipes or document shell requirement.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Migration Path from PPM v1 → v2
|
|
254
|
+
|
|
255
|
+
**v1 Problem:**
|
|
256
|
+
```typescript
|
|
257
|
+
// CRASHES BUNT PROCESS
|
|
258
|
+
const pty = require('node-pty').spawn('bash', [], { cwd: projectPath });
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**v2 Solution:**
|
|
262
|
+
```typescript
|
|
263
|
+
// WORKS RELIABLY
|
|
264
|
+
const proc = Bun.spawn(['bash'], {
|
|
265
|
+
cwd: projectPath,
|
|
266
|
+
terminal: { cols: 80, rows: 24, data(t, chunk) { /* handle */ } }
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**No breaking changes to Frontend:** xterm.js, WebSocket protocol, and terminal-tab component unchanged.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Summary Table
|
|
275
|
+
|
|
276
|
+
| Approach | Works | Portable | PTY Features | Dependency | Stability |
|
|
277
|
+
|----------|-------|----------|--------------|------------|-----------|
|
|
278
|
+
| node-pty | ❌ Crash | - | Yes | Native NAN | Dead |
|
|
279
|
+
| Bun.Terminal | ✅ | POSIX | Yes | Built-in | ✅ Stable |
|
|
280
|
+
| script wrapper | ✅ | POSIX | Yes | Bun + system | ✅ Good |
|
|
281
|
+
| Raw pipes | ✅ | All | No | Bun | Basic |
|
|
282
|
+
| bun-pty | ⚠️ Works | All | Yes | Rust FFI | Experimental |
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Unresolved Questions
|
|
287
|
+
|
|
288
|
+
1. **Performance impact** of Bun.Terminal vs node-pty under heavy I/O (1000+ char/sec)? — Likely negligible, but worth benchmarking if terminal lag reported.
|
|
289
|
+
|
|
290
|
+
2. **Windows support timeline** — If Windows devs become critical user base later, when would we port to `bun-pty` or implement fallback? Current: dev environment is macOS/Linux only, acceptable.
|
|
291
|
+
|
|
292
|
+
3. **Compiled binary distribution** — If PPM released as standalone `ppm` executable, how to ensure shell availability in compiled form? Not in scope for v2, address in v3 deployment phase.
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## References & Sources
|
|
297
|
+
|
|
298
|
+
- [Bun Spawn Documentation - Terminal API](https://bun.com/docs/runtime/child-process)
|
|
299
|
+
- [Bun.spawn SpawnOptions Reference](https://bun.com/reference/bun/Spawn/SpawnOptions)
|
|
300
|
+
- [GitHub: node-pty unable to be run from bun · Issue #7362 · oven-sh/bun](https://github.com/oven-sh/bun/issues/7362)
|
|
301
|
+
- [GitHub: Bun support · Issue #632 · microsoft/node-pty](https://github.com/microsoft/node-pty/issues/632)
|
|
302
|
+
- [GitHub: Port to NAPI · PR #644 · microsoft/node-pty](https://github.com/microsoft/node-pty/pull/644)
|
|
303
|
+
- [npm: @skitee3000/bun-pty](https://www.npmjs.com/package/@skitee3000/bun-pty)
|
|
304
|
+
- [GitHub: sursaone/bun-pty - Fork pseudoterminals in Bun](https://github.com/sursaone/bun-pty)
|
|
305
|
+
- [TTY Shell Upgrade Techniques - 0xffsec Handbook](https://0xffsec.com/handbook/shells/full-tty/)
|