oc exec: stream by default, implement oc exec attach#189
Merged
Conversation
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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix two CLI UX holes:
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/execand printed "Session X created / attach with ..." — a dead-end for anyone who actually wanted output.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 (
0x00stdin,0x01stdout,0x02stderr,0x03exit (big-endian int32),0x04scrollback-end). No backend changes — all the server-side plumbing for this has existed since exec sessions shipped.Flag changes
--detach--wait/exec/runPOST, 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/killand 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; useoc exec killto terminate it).Test plan
oc exec <sb> -- echo hello— streams "hello", exits 0oc exec <sb> -- sh -c 'echo out; echo err >&2; exit 7'— stdout and stderr visibly separated, CLI exits 7oc exec <sb> -- sleep 5with Ctrl-C — first Ctrl-C interrupts, prints^C sent SIGINT; CLI exits when sleep is killedoc exec <sb> -- catwith piped stdin (echo foo | oc exec ...) —fooechoed backoc exec <sb> --detach -- long-job— prints session id, exits immediatelyoc exec attach <sb> <sid>against a detached session — scrollback replayed, live streaming continuesoc exec <sb> --wait -- cmd— unchanged behavior, buffered resultoc exec <sb> --wait --detach -- cmd— rejected with clear errorFollow-ups (not in this PR)
--waitdelegate 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