Skip to content

feat: add CLI shell and exec commands for pod terminal access#124

Draft
V2arK wants to merge 28 commits intomainfrom
honglin/shell-forwarding-clean
Draft

feat: add CLI shell and exec commands for pod terminal access#124
V2arK wants to merge 28 commits intomainfrom
honglin/shell-forwarding-clean

Conversation

@V2arK
Copy link
Contributor

@V2arK V2arK commented Mar 12, 2026

Summary

  • Add centml cluster shell <id> for interactive terminal sessions (like docker exec -it)
  • Add centml cluster exec <id> -- <command> for running commands and returning output (like ssh host "cmd")
  • Both connect via WebSocket through the Platform API terminal proxy, matching the same protocol used by the Web UI TerminalView
  • Add get_status_v3() to SDK client for pod discovery
  • Add websockets>=13.0 dependency

Changes

File Description
centml/cli/shell.py New: WebSocket URL builder, pod resolver, interactive/exec sessions, Click commands
tests/test_shell.py New: 26 unit tests covering URL building, pod resolution, exec session, terminal restore, Click integration
centml/sdk/api.py Add get_status_v3() method (+3 lines)
centml/cli/main.py Register shell and exec commands (+3 lines)
requirements.txt Add websockets>=13.0 (+1 line)

Test plan

  • centml cluster exec <id> -- echo hello returns clean output
  • centml cluster exec <id> -- cat /etc/os-release returns full file content
  • centml cluster exec <id> -- nvidia-smi --query-gpu=name --format=csv,noheader returns GPU name
  • centml cluster exec <id> --shell sh -- echo test respects shell option
  • centml cluster shell <id> rejects non-TTY with clear error
  • 26 unit tests pass (pytest tests/test_shell.py)
  • centml cluster shell <id> interactive mode (manual TTY test)

@V2arK V2arK marked this pull request as draft March 12, 2026 18:12
    Add two new commands under `centml cluster`:
    - `shell <id>` -- interactive terminal session (like docker exec -it)
    - `exec <id> -- <command>` -- run a command and return output (like ssh host "cmd")

    Both connect via WebSocket through the Platform API terminal proxy,
    matching the same protocol used by the Web UI TerminalView.
@V2arK V2arK self-assigned this Mar 12, 2026
@V2arK V2arK force-pushed the honglin/shell-forwarding-clean branch from 06e9ae1 to 155fdbf Compare March 12, 2026 18:15
V2arK added 2 commits March 12, 2026 14:23
Replaces str.replace("https://", "wss://") with urllib.parse.urlparse
scheme replacement to avoid CodeQL py/incomplete-url-substring-sanitization.
Replace url.startswith() assertions with urllib.parse.urlparse() checks
to satisfy CodeQL py/incomplete-url-substring-sanitization rule. Reformat
both shell.py and test_shell.py with black.
@V2arK V2arK force-pushed the honglin/shell-forwarding-clean branch from 0073b53 to 095bd1e Compare March 12, 2026 18:24
V2arK added 22 commits March 12, 2026 14:27
Add pyte as local terminal emulator (equivalent to xterm.js) to solve
cursor positioning and line wrapping issues. Feed WebSocket output through
pyte Screen/Stream and render only dirty lines with ANSI escape sequences.
shutil.get_terminal_size() returns (columns, lines), not (rows, cols).
The swapped unpacking caused pyte Screen to be created with terminal
line count as width, making the display extremely narrow.
…andling

Replace regex-based _strip_ansi with pyte single-row screen for marker
detection. pyte interprets all VT100/VT220 sequences including OSC and
truecolor escapes that the regex could miss.
If two Code signals arrive within 3 seconds, the shell has exited and
the reconnect just opened a new session. Exit cleanly instead of
looping forever.
Logs to /tmp/centml_shell_debug.log (overridable via
CENTML_SHELL_DEBUG_LOG env var). Traces every WS message, stdin event,
task lifecycle, reconnect decision, and connection close.
V2arK added 3 commits March 12, 2026 20:15
The platform API proxy never forwards ArgoCD Code messages and does
not close the WebSocket when the remote shell exits.  Replace the
Code/reconnect logic with exit echo detection: when the server echoes
back "exit\r\n", arm a 2-second idle timeout on ws.recv().  If no
more data arrives, the shell has exited -- break out cleanly.

Also removes Code handling from _exec_session (markers already work).
…ompt

When "exit\r\n" appears at the end of ws data (nothing after it), the
shell has exited -- return immediately instead of waiting 2s.  When
"exit\r\n" is followed by a new prompt (e.g. from echo exit), ignore
it and continue the session.
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