- Add startup_command field to ToolType model and API - Execute startup command before interactive shell in terminal sessions - Add tmux and ranger to OpenCode container spec - Update Tool Workshop UI with startup_command input for terminal types - Add backend tests for startup_command CRUD operations - Sync specs: tool-terminal, tool-types-definition, opencode-web-server - New spec: tool-terminal-startup-command Quality gates: Frontend typecheck/lint passed. Backend tests blocked by environment (Python/Docker not available). OpenSpec: terminal-startup-and-container-tools
4.1 KiB
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 APItool-terminal: Defines WebSocket terminal session behavioropencode-web-server: Defines OpenCode container requirementstool-config-management: ToolConfig already hasstart_commandfor runtime process startup
Goals / Non-Goals
Goals:
- Allow tool type authors to specify a
startup_commandthat executes for every new terminal session - Execute the startup command before the interactive shell in terminal sessions
- Make
tmuxandrangeravailable in OpenCode containers - Support creating and editing
startup_commandvia 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 "<startup_command>" && 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|| truepattern). Actually, use:bash -c "<cmd>" || true; exec bash -il - [Risk] UI clutter from additional field in Tool Workshop → Mitigation: Show
startup_commandonly for terminal interface types
Migration Plan
- Database migration: Add
startup_commandtext column totool_typestable - Backend: Update ToolType model, Pydantic schemas, API endpoints
- Backend: Update TerminalSession to accept and execute startup_command
- Backend: Update terminal WebSocket endpoint to fetch and pass startup_command
- Frontend: Add
startup_commandfield to Tool Workshop form - Infrastructure: Update OpenCode compose template to install tmux and ranger
- Tests: Update existing tests and add new ones for startup command behavior
Open Questions
None at this time.