Files
headquarter/openspec/changes/archive/2026-05-24-terminal-startup-and-container-tools/design.md
T
OpenCode Agent 01a0ef46c9 feat: terminal startup command and container tools
- 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
2026-05-24 22:21:55 +00:00

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 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 "<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 || true pattern). Actually, use: bash -c "<cmd>" || 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.