| name | headless-terminal |
| description | This skill provides guidance for implementing headless terminal interfaces that programmatically control shell sessions. Use this skill when implementing terminal emulation, pseudo-terminal wrappers, |
Headless Terminal Implementation
Overview
This skill guides the implementation of headless terminal interfaces—programmatic wrappers that control shell sessions without a visible terminal UI. These implementations typically involve spawning shell processes, sending input (keystrokes, commands), and capturing output.
Approach
Step 1: Understand the Interface Contract
Before implementing, thoroughly read and understand the interface to be implemented:
- Identify all required methods and their signatures
- Note return types and expected behaviors
- Check for optional methods or features
- Look for existing implementations or tests that clarify expected behavior
Step 2: Select the Underlying Library
Common libraries for terminal emulation in Python:
| Library | Best For | Trade-offs |
|---|
pexpect | Interactive terminal emulation, pattern matching | Higher-level API, good for expect/send patterns |
pty | Low-level pseudo-terminal control | More control, but more boilerplate |
subprocess | Simple non-interactive commands | Limited for true terminal emulation |
Decision criteria to document:
- Does the task require interactive input (passwords, prompts)? →
pexpect
- Does the task need low-level terminal control? →
pty
- Is it purely non-interactive command execution? →
subprocess may suffice
Document the choice explicitly with reasoning for future maintainability.
Step 3: Handle Shell Configuration
When spawning a shell process, consider these configuration options:
Interactive mode (-i flag):
- Ensures startup files (
.bashrc, .bash_profile) are sourced
- Affects signal handling behavior
- Required if tests verify startup file sourcing
Echo behavior:
echo=False in pexpect prevents input from appearing in output
- Consider whether the use case needs to see echoed input
Terminal dimensions:
- Default
(24, 80) is standard terminal size
- May affect output formatting for commands that detect terminal width
- Document why specific dimensions are chosen
Step 4: Implement Core Functionality
Focus on implementing exactly what the interface requires:
- Process lifecycle management - Spawn, check liveness, terminate
- Input handling - Send keystrokes, handle special keys (Ctrl+C, etc.)
- Output capture - Read available output, handle buffering
- Resource cleanup - Proper termination, context manager support
Step 5: Address Edge Cases
Explicitly handle these scenarios:
| Edge Case | Handling Strategy |
|---|
| Shell exits unexpectedly | Check process liveness before operations |
| Long-running commands | Configurable timeouts, background execution support |
| Non-ASCII characters | Explicit encoding handling (UTF-8 typically) |
| Race conditions | Appropriate delays between send and read operations |
| Command cancellation | Proper signal handling (SIGINT for Ctrl+C) |
Verification Strategies
Testing Approach
Create focused tests for each capability:
- Basic functionality - Import, instantiation
- Non-interactive commands - Simple command execution and output
- Interactive commands - Commands requiring input
- Signal handling - Ctrl+C cancellation
- Shell state - Variable persistence, environment
- Startup configuration - Verify startup files are sourced
- Background execution - Long-running command handling
Verification Guidelines
- Run the test suite to verify all functionality
- Avoid redundant manual verification after tests pass
- If a single comprehensive test file exists, use it rather than creating separate verification scripts
Common Pitfalls
Scope Management
- Implement only what is required - Avoid adding unrequested features like extra utility methods
- If additional methods seem useful, note them but don't implement unless asked
- Context manager support is often expected but verify it's in the interface
Efficiency
- Avoid redundant searches - If searching for a class, one targeted search is sufficient
- Don't duplicate verification - If tests pass, additional manual checks are unnecessary
- Don't create example files unless explicitly requested
Documentation Gaps
Common decisions that should be documented but often aren't:
- Why the chosen library over alternatives
- Why specific shell flags are used
- Why specific default values were selected
- Thread safety considerations (or explicit statement that it's not thread-safe)
Error Handling
Consider and document handling for:
- Invalid keystroke sequences
- Terminal process termination
- Timeout scenarios
- Permission issues
Implementation Checklist
Before considering the implementation complete:
Overview
This skill guides implementing headless terminal interfaces that programmatically control shell sessions without a visual UI. It focuses on spawning shell processes, sending keystrokes, capturing output, and managing lifecycle and edge cases. The guidance helps choose libraries, document decisions, and verify behavior with focused tests.
How this skill works
The implementation spawns a shell process via a chosen backend (pexpect, pty, or subprocess), configures interactive flags, terminal dimensions, and echo behavior, and exposes methods to send input and read output. It includes lifecycle management (spawn, liveness checks, terminate), signal handling for cancellations (e.g., Ctrl+C), and explicit resource cleanup and encoding handling.
When to use it
Building programmatic terminal emulation or pseudo-terminal wrappers
Implementing a BaseTerminal-style interface that must send keystrokes and read shell output
Automating interactive shell tasks that require prompts or password entry
Testing shell startup configuration or environment persistence
Handling long-running commands or background shell jobs
Best practices
Document and justify the chosen underlying library (pexpect, pty, or subprocess) and why alternatives were rejected
Expose only the methods required by the interface; avoid adding unrequested features
Set and document terminal dimensions and interactive flags so test behavior is reproducible
Handle encoding explicitly (UTF-8) and validate non-ASCII behavior in tests
Provide configurable timeouts and robust liveness checks to manage long-running commands and unexpected exits
Implement and document proper resource cleanup and context manager support if the interface expects it
Example use cases
A CI runner that needs to drive interactive installers and capture prompts
A remote automation agent that runs shells and reacts to output patterns using expect/send logic
A test harness that verifies shell startup files are sourced in interactive mode
A wrapper that exposes a programmatic API for sending special keys (Ctrl+C) and cancelling commands
A logging proxy that records both sent keystrokes and terminal output for replay and debugging
FAQ
Which library should I pick for interactive shells?
Use pexpect for high-level expect/send interactions and prompts; use pty for low-level control when precise terminal semantics are required; use subprocess only for non-interactive command execution.
How should I handle unexpected shell exits?
Always check process liveness before operations, surface clear errors to callers, and provide configurable retries or timeouts for recovery; document whether automatic restarts are in-scope.
Skill score
0
Health score
i
D
65
/100
Stats
278
stars
First Seen
2 months ago
Repository
benchflow-ai
/
skillsbench
Tag