Skip to content

feat(shell): in-browser interactive container shell - #123

Merged
ParadoxInfinite merged 2 commits into
mainfrom
feat/container-shell
Jun 28, 2026
Merged

feat(shell): in-browser interactive container shell#123
ParadoxInfinite merged 2 commits into
mainfrom
feat/container-shell

Conversation

@ParadoxInfinite

Copy link
Copy Markdown
Owner

An interactive shell into a running container, opened from its details panel —
the top roadmap item. Built with no new mandatory dependencies.

Transport — no dependency

  • A small, self-contained WebSocket server (internal/server/ws.go, RFC 6455
    scoped to text/binary + ping/pong/close). The protocol is frozen, so this
    carries no upkeep or license to track. The binary grows by a handful of KB, not
    a library.
  • GET /api/containers/{id}/shell upgrades, runs an exec with a PTY
    (internal/docker/exec.go), and pumps bytes both ways: container→browser as
    binary frames; browser→container, a binary frame is stdin and a text frame is a
    {resize} control message.

Terminal — fetched on demand, never bundled

  • xterm.js is downloaded on first shell-open by the backend, cached on disk, and
    served same-origin (/api/term/{file}), so it loads under the app's CSP and
    adds nothing to the binary or the main JS bundle. The component lazy-imports it,
    so anyone who never opens a shell pays zero cost.

Scope & safety

  • UI-only and gated by the same /api auth as everything else; never exposed over
    MCP (an interactive PTY doesn't fit the request/response tool model and is too
    large an agent surface).
  • A runtime toggle (Settings → Container shell) turns it off; the UI only shows
    the Shell tab for a running container when the backend advertises it.

Testing

  • A WebSocket handshake+codec test (RFC accept key, masked client frames, unmasked
    server frames) and an end-to-end check against a real container (exec output
    round-trips) both pass. go build, go test ./..., npm run build, and the
    i18n catalog check pass.

Notes: the shell command probes for bash and falls back to sh. Input over a
remote connection has normal WebSocket latency; xterm needs network the first
time a shell is opened on a given browser (cached after).

@ParadoxInfinite
ParadoxInfinite merged commit c344300 into main Jun 28, 2026
1 check passed
@ParadoxInfinite
ParadoxInfinite deleted the feat/container-shell branch June 28, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant