opencode-pty

repository·main·Indexed 19 days ago

https://github.com/shekohex/opencode-pty

An OpenCode plugin for interactive pseudo-terminal (PTY) management. It enables AI agents to run long-running background processes, send interactive input, and monitor output via a buffer or a real-time React-based Web UI. The plugin includes a REST API for session management, WebSocket support for real-time output streaming, and tools for regex filtering and session lifecycle control.

Tokens
9.6K
Snippets
32
Records
45
Agent score
68%

What's inside opencode-pty

  1. How to send interactive input to a running session

    main

    Input can be sent to a running PTY session through two primary paths:

    Via Web UI (Human Input)

    When a user types or pastes text into the xterm.js terminal in the browser:

    1. The UI sends a JSON message: {type: "input", sessionId, data: "<input_text>\n"}.
    2. The WebSocket server calls manager.write(sessionId, data).
    3. The Manager writes the data to the bun-pty process.

    Via AI Agent (Automated Input)

    The AI Agent can programmatically send input (e.g., sending Ctrl+C via \x03):

    1. The Agent calls pty_write(id, data) via the plugin.
    2. The Plugin calls manager.write(id, data).
    3. The Manager writes the data to the process.
  2. How to start a long-running background process

    main

    You can start background processes (like dev servers) via the OpenCode Chat. The AI Agent uses the PTY Plugin to spawn these processes.

    Workflow:

    1. Command: The user asks the chat to start a process (e.g., "start vite dev server in background").
    2. Spawning: The Agent calls pty_spawn(command, args, ...) via the plugin.
    3. Execution: The PTY Manager launches the real process using bun-pty.
    4. Monitoring: Output (stdout/stderr) is captured by the Manager, appended to a RingBuffer, and published via WebSocket to the Web UI if it is open.
    5. Confirmation: The Agent receives session info and confirms the start to the user with a Session ID (e.g., pty_abc123).
  3. How the PTY Monitor Web UI works

    main

    The PTY Monitor Web UI is a browser-based interface used to view and interact with running PTY sessions. It connects to a WebSocket server managed by the PTY Plugin.

    Workflow:

    1. Opening the UI: A user triggers the /pty-open-background-spy slash command in the OpenCode Chat. The plugin instructs the browser to open the server's origin.
    2. Connection: The browser connects via WebSocket (ws://.../ws).
    3. Session Discovery: The WebSocket server queries the PTY Manager (manager.list()) to retrieve current sessions.
    4. Real-time Updates: The browser receives the session_list and subscribes to updates. The UI uses xterm.js to render live terminal output as the WebSocket server publishes raw_data and session_update events.
  4. How to read output and logs on demand

    main

    Logs from running sessions are stored in a RingBuffer. You can request specific segments of logs through the chat.

    Workflow:

    1. Request: The user asks for logs (e.g., "show me the last 200 lines of the dev server").
    2. Retrieval: The Agent calls pty_read(id, offset?, limit=200, pattern?) via the plugin.
    3. Processing: The Manager reads from the RingBuffer using the provided offset, limit, or pattern (for searching).
    4. Response: The Manager returns the matching or paginated lines to the Agent, which then formats and displays them in the chat.
  5. How to kill or clean up a PTY session

    main

    Sessions can be terminated either through the Web UI or via the AI Agent.

    Via Web UI

    1. The user clicks "Kill" or "×" on a session in the UI.
    2. The UI sends an HTTP request: DELETE /api/sessions/:id (or /cleanup).
    3. The Manager calls kill(id, cleanup?).
    4. The Manager sends SIGTERM to the process. Upon exit, the Manager publishes a session_update (status: killed/exited) via WebSocket to update the UI.
  6. Configure PTY permissions in OpenCode

    main

    The plugin respects OpenCode's bash permission settings. Commands spawned via pty_spawn are checked against your permission.bash configuration.

    Important Limitations:

    • 'ask' permissions are treated as 'deny': Plugins cannot trigger the OpenCode permission prompt UI. If a command matches an 'ask' pattern, it will be denied. You must explicitly set it to 'allow' or 'deny'.
    • 'external_directory' with 'ask' is treated as 'allow': If the working directory is outside the project and permission.external_directory is set to 'ask', this plugin allows it.
    {
      "$schema": "https://opencode.ai/config.json",
      "permission": {
        "bash": {
          "npm run dev": "allow",
          "npm run build": "allow",
          "npm test *": "allow",
          "cargo *": "allow",
          "python *": "allow"
        }
      }
    }
  7. How to kill or clean up a PTY session via Agent

    main

    The AI Agent can terminate sessions based on user requests.

    Workflow:

    1. Request: The user asks to kill a session (e.g., "kill the dev server").
    2. Command: The Agent calls pty_kill(id, cleanup=true) via the plugin.
    3. Execution: The Manager calls kill(id, true), which sends SIGTERM and removes the session from the list if cleanup is true.
    4. Notification: The Manager broadcasts a session_update (status: killed/exited) via WebSocket to update any open Web UIs.
  8. Understand the PTY session lifecycle

    main

    A PTY session follows this lifecycle:

    spawn $\rightarrow$ running $\rightarrow$ [exited | killed]

    When a process exits, the session remains in the list until pty_kill is called with cleanup=true. This allows the agent to read the final output or check the exit code after completion. If notifyOnExit=true was set during spawn, the agent will receive an <pty_exited> notification immediately upon exit.

  9. How automatic exit notifications work

    main

    If a process exits, the system can notify the user via the chat interface.

    Workflow:

    1. Exit Event: The bun-pty process exits, and the Manager captures the exitCode.
    2. Condition: If notifyOnExit was set to true when the session was spawned:
      • The Manager triggers an exit notification through the plugin.
      • The plugin sends a formatted message to the chat using the SDK in the format:
        <pty_exited>
        ID: <session_id>
        Exit: <exit_code>
        Lines: <line_count>
        Last: <last_output_lines>
        </pty_exited>
      • The chat triggers the AI Agent with this exit message.
    3. UI Update: The WebSocket server publishes a final session_update (status: exited), causing the Web UI to show an "exited" badge or stop live output.
  10. Install the opencode-pty plugin

    main

    To install the plugin, add opencode-pty to the plugin array in your OpenCode configuration file. OpenCode will automatically handle the installation on the next run.

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["opencode-pty"]
    }
  11. Access the PTY Web UI

    main

    The Web UI is a React-based interface for monitoring and interacting with PTY sessions in real-time. To start it:

    1. Run OpenCode with the opencode-pty plugin enabled.
    2. Execute the slash command /pty-open-background-spy in the chat.

    Note: When instructing an agent to run something in the background, you must explicitly refer to it as a "session" (e.g., "run xy as a background SESSION"). If you use terms like "task" or "process", the agent may fallback to using & instead of a proper PTY session.