@liam-public/node-pty-session
v0.2.0
Published
PTY session wrapper and terminal websocket message protocol.
Downloads
37
Readme
@liam-public/node-pty-session
PTY session wrapper and terminal websocket message protocol.
import { PtySession, parseClientMsg, encodeServerMsg } from '@liam-public/node-pty-session'
const session = new PtySession({ bin: 'bash', args: ['-l'], cwd: '/srv/work' })
session.onData((d) => ws.send(encodeServerMsg({ t: 'out', d })))
session.onExit((code) => ws.send(encodeServerMsg({ t: 'exit', code })))
ws.on('message', (raw) => {
const msg = parseClientMsg(String(raw))
if (msg?.t === 'in') session.write(msg.d)
if (msg?.t === 'resize') session.resize(msg.cols, msg.rows)
})parseClientMsg is total — it returns null for any malformed frame rather
than throwing, because frames arrive off an untrusted socket.
Running an agent with permissions disabled
interactiveClaudeArgs builds the argv for an interactive claude session.
--dangerously-skip-permissions is opt-in:
interactiveClaudeArgs({ sessionId }) // prompts stay on
interactiveClaudeArgs({ sessionId, dangerouslySkipPermissions: true }) // no prompts at allOpting in runs the agent with every tool-permission prompt disabled. Only do
that when the pty is confined some other way — a container, a throwaway cwd, a
trusted operator on the other end of the socket. extra cannot smuggle the flag
in without the option: passing it there throws, so the decision stays visible at
the call site.
Note that PtySession spawns whatever bin and args it is given. If the
websocket layer lets a remote client influence either, that client chooses the
process — authenticate and pin them server-side.
node-pty needs its native spawn-helper binary. If installs skip build
scripts, run npm rebuild node-pty --build-from-source.
