Skip to content

oc exec: stream by default, implement oc exec attach#189

Merged
motatoes merged 1 commit intomainfrom
feat/oc-exec-stream
Apr 24, 2026
Merged

oc exec: stream by default, implement oc exec attach#189
motatoes merged 1 commit intomainfrom
feat/oc-exec-stream

Conversation

@motatoes
Copy link
Copy Markdown
Contributor

Summary

Fix two CLI UX holes:

  1. oc exec <sb> -- cmd (default, no flags) now creates a session, attaches over WebSocket, and streams stdout/stderr live to the user's terminal while forwarding stdin. The CLI exits with the command's exit code. Previously this path just POSTed to /exec and printed "Session X created / attach with ..." — a dead-end for anyone who actually wanted output.

  2. oc exec attach <sb> <sid> was a stub that printed "not yet implemented in CLI — use the SDK or websocat." It now works: replays scrollback, streams live, forwards stdin, exits with the process exit code.

Both use the same binary WS protocol the SDKs speak (0x00 stdin, 0x01 stdout, 0x02 stderr, 0x03 exit (big-endian int32), 0x04 scrollback-end). No backend changes — all the server-side plumbing for this has existed since exec sessions shipped.

Flag changes

Flag Behavior
(no flag) New default: create session + stream + exit with process exit code
--detach New: create session, print id + hint, don't wait (preserves old no-flag behavior for fire-and-forget scripts)
--wait Unchanged: buffered /exec/run POST, no streaming, prints result at the end (mutually exclusive with --detach)

Ctrl-C handling

First Ctrl-C sends SIGINT to the remote process via /exec/:sid/kill and keeps streaming — the process decides whether to handle it. Second Ctrl-C force-closes the WS and exits the CLI locally (the remote process keeps running; use oc exec kill to terminate it).

Test plan

  • oc exec <sb> -- echo hello — streams "hello", exits 0
  • oc exec <sb> -- sh -c 'echo out; echo err >&2; exit 7' — stdout and stderr visibly separated, CLI exits 7
  • oc exec <sb> -- sleep 5 with Ctrl-C — first Ctrl-C interrupts, prints ^C sent SIGINT; CLI exits when sleep is killed
  • oc exec <sb> -- cat with piped stdin (echo foo | oc exec ...) — foo echoed back
  • oc exec <sb> --detach -- long-job — prints session id, exits immediately
  • oc exec attach <sb> <sid> against a detached session — scrollback replayed, live streaming continues
  • oc exec <sb> --wait -- cmd — unchanged behavior, buffered result
  • oc exec <sb> --wait --detach -- cmd — rejected with clear error

Follow-ups (not in this PR)

  • Fix typical Ctrl-C-from-pty issue: when stdin isn't a tty we rely on OS signal delivery; terminal raw-mode for richer key forwarding could come later.
  • Consider making --wait delegate to the streaming path too (streaming is a strict superset). Not done here to avoid breaking scripts that parse the final buffered output.

🤖 Generated with Claude Code

Default `oc exec <sb> -- cmd` now creates a session, attaches to its
WebSocket, and streams stdout/stderr live to the user's terminal while
forwarding stdin. The CLI exits with the command's exit code. This is
the behavior a CLI user almost always wants — previously, without
`--wait`, the command just created a session and printed an
"attach with ..." hint, which was a dead-end UX.

New flag `--detach` preserves the old fire-and-forget path for scripts
that want to enqueue a long-running job and move on. `--wait` keeps the
buffered `/exec/run` path (no streaming; good for CI scripts that only
want the final result) and is mutually exclusive with `--detach`.

`oc exec attach <sb> <sid>` was a stub that printed "not yet implemented
— use the SDK or websocat." It now shares the same streaming helper as
the default `exec` path: replays scrollback, then streams live, forwards
stdin, SIGINT/SIGTERM relay as SIGINT to the remote process (second
Ctrl-C force-detaches).

Uses the same binary WS protocol the SDKs speak (0x00 stdin, 0x01
stdout, 0x02 stderr, 0x03 exit with big-endian int32 code, 0x04
scrollback-end). No backend changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opensandbox Ready Ready Preview, Comment Apr 24, 2026 9:52pm

Request Review

Copy link
Copy Markdown
Contributor

@breardon2011 breardon2011 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approve

@motatoes motatoes merged commit 45e0a58 into main Apr 24, 2026
3 checks passed
motatoes added a commit that referenced this pull request Apr 25, 2026
Drop the non-existent --template flag from sandbox-create examples and
correct the exec section: oc exec streams by default since #189, so
--json only makes sense paired with --wait. Also document the new exec
session subcommands (list/attach/kill) and --detach mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
motatoes added a commit that referenced this pull request Apr 25, 2026
)

* dashboard+skill: add first-run onboarding and rename openqemu skill

Replace the empty-dashboard placeholder with a two-step Getting Started
panel (install command + Generate API Key button) so new accounts have
a clear path from signup to first sandbox.

Also consolidates the project-local openqemu skill into the
opencomputer skill, and rewrites its setup section to auto-install the
oc CLI and walk users through API-key creation when missing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* skill: fix CLI reference inaccuracies

Drop the non-existent --template flag from sandbox-create examples and
correct the exec section: oc exec streams by default since #189, so
--json only makes sense paired with --wait. Also document the new exec
session subcommands (list/attach/kill) and --detach mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* api-keys: one-click create with auto-named key

Drop the intermediate name-input dialog. Clicking "Create Key" now
generates a key immediately with a date-based name ("Key YYYY-MM-DD",
suffixed (2), (3)... if multiple are created on the same day) and
reveals it inline with a Copy button — same flow as the dashboard
onboarding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert "api-keys: one-click create with auto-named key"

This reverts commit 40b16fa.

* dashboard: auto-create + display default API key on first signup

Drop the "Generate API Key" button from the onboarding panel. When a
new user lands on the dashboard with no existing keys, we now create
the Default key automatically on mount and reveal it inline. The user
can copy it without any clicks — the key feels like it was already
provisioned at signup.

If the user already has keys (e.g. created earlier in another session),
we show a note explaining we can't re-display existing values for
security and link to /api-keys to rotate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* auth/workos: don't auto-create API key during signup

The WorkOS provisioning path was creating a Default API key the moment
a new org was provisioned, then discarding the plaintext value. The
user could never see or use that key — only its hash existed in the DB.

This blocked the dashboard's onboarding flow: on first login the user
already had 1 (unusable) key, so the auto-create-and-reveal step
correctly bailed out. Removing the signup-time create lets the
dashboard create the first key when the user lands and show its
plaintext, which is the only way they can actually use it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* dashboard: mask onboarding API key behind reveal/copy buttons

Stop displaying the freshly-created API key in plain text. Render it
as bullets by default with explicit "Reveal" and "Copy" buttons —
copy works without revealing, so the user can paste into their
terminal without ever shoulder-surfing the value on screen. Same
treatment for the embedded key in the 'oc config set api-key …'
command row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants