kavin525zhang/llm_reasoning_framework/terminal-tools-pty-sessions
- community
Checking that the SKILL.md file is still in the repository.
Use when you need state across calls — building env vars, navigating with cd, driving REPLs (python -i, mysql, psql, node), or responding to interactive prompts (sudo password, ssh host-key confirmation, mysql connection). Teaches the prompt-sentinel exec pattern (default mode), raw I/O for REPLs (raw_send=True then read_only=True), the one-in-flight-per-session rule, and the close-or-leak-against-the-cap discipline. Bash on macOS — never zsh; explicit shell=/bin/zsh is rejected. Read before calling terminal_pty_open.
Install
npx vskill@latest install kavin525zhang/llm_reasoning_framework/terminal-tools-pty-sessionsSKILL.md
The same SKILL.md was published earlier as aden-hive/hive/terminal-tools-pty-sessions.
Persistent PTY sessions
PTY sessions are how you talk to interactive programs — programs that detect a terminal (isatty()) and behave differently when they don't see one. Use a session when:
- You need state to persist across calls (
cd, env vars, sourced scripts) - You're driving a REPL (
python -i,mysql,psql,node,irb) - A program demands an interactive prompt (
sudo,ssh,npm login,gh auth login)
For everything else, terminal_exec is simpler. Sessions cost more (per-session bash process, ring buffer, idle-reaping bookkeeping) and have a hard cap (TERMINAL_TOOLS_MAX_PTY, default 8).
Why PTY (and not subprocess pipes)
Subprocess pipes break on every interactive program. The moment a program calls isatty() and sees False, it disables prompts, color, line-editing, password masking, progress bars — sometimes refuses to start. PTY makes us look like a real terminal so these programs work the same as in your shell.
The cost: PTY output includes terminal escape codes (cursor moves, color codes). The session captures them as-is; if you need clean text, strip ANSI escapes in your processing layer.
Bash on macOS — by deliberate policy
terminal_pty_open always invokes /bin/bash, regardless of the user's $SHELL. macOS users: yes, even when zsh is your interactive default. This is the terminal-tools-foundations policy applied to PTYs.
Reasons:
- zsh has command/builtin classes (
zmodload,=cmdexpansion,zpty,ztcp) that bypass bash-shaped security checks - One shell behavior across platforms eliminates "works on Linux, breaks on macOS" surprises
- Bash is universal: any shell you've used will accept the bash subset
The bash invocation uses --norc --noprofile so user dotfiles don't leak in. PS1 is set to a unique sentinel for prompt detection. PS2 is empty. PROMPT_COMMAND is empty.
Three modes of terminal_pty_run
1. Default: send command, wait for prompt sentinel
The session writes ls -la\n, waits for the sentinel that its custom PS1 emits, returns the slice between submission and prompt. One in-flight call per session — a concurrent call returns a "session busy" error.
2. raw_send: send raw input, no waiting
For REPLs, vim keystrokes, password prompts. The session writes the bytes and returns immediately — it doesn't wait for a prompt (REPLs don't print bash's prompt; they print their own).
After a raw_send, you typically follow with:
3. read_only: drain currently-buffered output
Reads whatever the session has accumulated since the last drain, with a brief settle window. Use after raw_send to capture the REPL's response.
Custom prompt detection (expect)
When the command launches a program with its own prompt (Python REPL's >>> , mysql's mysql> , sudo's password prompt), the bash sentinel won't appear until the program exits. Override:
For sudo:
(Treat passwords carefully — they end up in the ring buffer.)
Always close
Leaked sessions count against TERMINAL_TOOLS_MAX_PTY (default 8). Idle reaping happens lazily on every _open call (sessions inactive longer than idle_timeout_sec, default 1800s, are dropped) — but don't rely on it. Close when you're done.
For unresponsive sessions, force=True skips the graceful "exit" attempt and goes straight to SIGTERM/SIGKILL.
Common patterns
Stateful navigation
Python REPL
ssh with host-key prompt
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingHarness/hive/core/framework/skills/_preset_skills/terminal-tools-pty-sessions/SKILL.md
Popularity
- Repository stars
- 1
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/kavin525zhang/llm_reasoning_framework/terminal-tools-pty-sessions)