## Context The system provides terminal access to running tool instances via WebSocket, spawning a `bash -il` shell inside the container using `docker exec`. Currently, there is no way to customize what runs when a new terminal session starts. The OpenCode tool type provides a web terminal interface but lacks common productivity utilities (`tmux`, `ranger`) that developers expect. Existing related specs: - `tool-types-definition`: Defines the ToolType model and CRUD API - `tool-terminal`: Defines WebSocket terminal session behavior - `opencode-web-server`: Defines OpenCode container requirements - `tool-config-management`: ToolConfig already has `start_command` for runtime process startup ## Goals / Non-Goals **Goals:** - Allow tool type authors to specify a `startup_command` that executes for every new terminal session - Execute the startup command before the interactive shell in terminal sessions - Make `tmux` and `ranger` available in OpenCode containers - Support creating and editing `startup_command` via the Tool Workshop UI **Non-Goals:** - Per-instance startup command overrides (out of scope; can be added later) - Startup commands for web interface tools (only terminal sessions) - Changing the tool's main process start command (already handled by `tool-config-management`) ## Decisions ### 1. Add `startup_command` to ToolType model **Rationale**: The startup command is a property of the tool type itself, defining the environment/setup expected for that tool. This aligns with how tool types define other container behavior. **Alternative considered**: Adding it to ToolConfig. Rejected because ToolConfig is per-user configuration, and startup behavior is more of a tool type contract. ### 2. Execute startup command via bash -c before interactive shell **Rationale**: The simplest approach that works with any shell. We'll construct the command as: `bash -c "" && bash -il` or use a here-document approach. **Alternative considered**: Writing a startup script to the container filesystem. Rejected because it requires container filesystem modification and doesn't work well with read-only containers. ### 3. Pass startup_command through TerminalSession.start() **Rationale**: The TerminalSession is responsible for spawning the shell, so it needs the command. The terminal_manager will fetch the tool type's startup_command from the database when creating a session. **Implementation**: Modify `TerminalManager.get_or_create_session()` to accept an optional `startup_command` parameter. The terminal API endpoint will fetch the tool type via the instance and pass it. ### 4. Install tmux and ranger via compose template **Rationale**: OpenCode is defined as a Docker Compose tool type. The most maintainable approach is to install utilities via the container's package manager in the compose template (e.g., via a custom Dockerfile or init commands). **Alternative considered**: Building a custom OpenCode Docker image. Rejected because it adds operational complexity; installing via compose is sufficient for now. ## Risks / Trade-offs - [Risk] Long-running startup commands could delay terminal availability → Mitigation: Document that startup commands should be fast; consider adding a timeout in a future iteration - [Risk] Startup command failures could prevent shell access → Mitigation: Use `&&` to chain; if the startup command fails, the shell still starts (use `;` or `|| true` pattern). Actually, use: `bash -c "" || true; exec bash -il` - [Risk] UI clutter from additional field in Tool Workshop → Mitigation: Show `startup_command` only for terminal interface types ## Migration Plan 1. Database migration: Add `startup_command` text column to `tool_types` table 2. Backend: Update ToolType model, Pydantic schemas, API endpoints 3. Backend: Update TerminalSession to accept and execute startup_command 4. Backend: Update terminal WebSocket endpoint to fetch and pass startup_command 5. Frontend: Add `startup_command` field to Tool Workshop form 6. Infrastructure: Update OpenCode compose template to install tmux and ranger 7. Tests: Update existing tests and add new ones for startup command behavior ## Open Questions None at this time.