Bound, interrupt, stream, and feed input to commands while they run.
commands.run() returns everything at once when the command ends, which is all a quick command needs. Commands that run longer are worth bounding, watching, or feeding input to while they run. These options cover that; they layer onto the same run() call and none of them change its return value.
Both commands.run() and code.run() accept a timeout parameter, in seconds. When the timeout is reached, the guest work is interrupted and the call returns instead of waiting for it to finish.
with Sandbox.create() as sandbox: result = sandbox.code.run("import time; time.sleep(30)", timeout=3)
A shell command that hits its timeout returns with exit_code124:
result = sandbox.commands.run("sleep 30", timeout=3)print(result.exit_code) # 124
A command no longer has to run to its timeout. interrupt() stops whatever is in the foreground, and the call that was waiting returns with exit code 130:
import threadingwith Sandbox.create() as sandbox: threading.Timer(1.0, sandbox.commands.interrupt).start() result = sandbox.commands.run("sleep 300") print(result.exit_code) # 130
The command really stops. This is not the caller walking away while the guest keeps working, so the sandbox is yours again immediately.Ctrl-C works too. It used to do nothing while a command was running, because KeyboardInterrupt could not land on a thread blocked inside the emulator. It now reaches the command, which makes an interactive REPL behave the way you would expect.
code.run() cannot be interrupted yet, so use timeout there.There is no signal parameter, and none is needed: run() blocks, so Ctrl-C reaches it directly and timeout already covers deadlines. The TypeScript SDK needs an AbortSignal because its call returns a promise and the caller keeps going.A command that ignores the interrupt runs to its own deadline and is recovered the same way a timeout is.
commands.run() hands back everything at once, when the command ends. For a build or a test run that is a long wait followed by a wall of text, so it also takes on_stdout and on_stderr, called with each piece of output as it arrives:
import syswith Sandbox.create() as sandbox: result = sandbox.commands.run( "for i in 1 2 3; do echo step $i; sleep 1; done", timeout=60, on_stdout=sys.stdout.write, ) print(result.exit_code) # 0
The return value does not change, so you can add a callback to existing code and nothing else moves. Chunks are verbatim, exactly the bytes the program wrote, while result.stdout trims its trailing newline: joining the chunks gives you "hi\n" where stdout gives you "hi".Chunks arrive as the guest produces output, not on a fixed schedule. A command printing two hundred lines with no pauses delivers them in one chunk; one printing a line a second delivers a chunk per line. A command that finishes quickly delivers a single chunk, which is indistinguishable from not streaming, and that is correct: there was nothing to stream.Streaming composes with interrupts. The chunks that arrived before the stop are kept, and the result still carries exit code 130.
on_stdout and on_stderr are ordered against each other only when the writes are separated in time. Two processes that both flush as they exit can arrive stdout-first even though stderr was written first, because the two streams travel separately. Use one callback if you need a single ordered transcript.
code.run() does not stream, and does not accept on_stdout. Shell commands are what tend to run long enough to be worth watching.
Pass a queue.Queue when what you send next depends on what came back. That puts the command on a terminal, so you write as it runs and putting None ends its input. run() blocks, so put from on_stdout or from another thread:
import queueinbox = queue.Queue()seen = []step = 0def on_stdout(chunk): global step seen.append(chunk) text = "".join(seen) if step == 0 and ">>>" in text: step = 1 inbox.put("print(40 + 2)\n") elif step == 1 and "42" in text: step = 2 inbox.put(None)result = sandbox.commands.run("python3 2>&1", stdin=inbox, on_stdout=on_stdout, timeout=60)
Match on the output so far rather than the chunk you were handed, and step through once: the prompt comes back after every answer.stdin accepts a str, bytes, a queue.Queue, or any iterable. An iterable is read one chunk at a time as the command runs, and running out ends the input:
Use tty=True for a terminal with no input of its own, and timeout=0 for no deadline, which is what an interactive session wants. Ctrl-C works throughout, and interrupts the command in the guest.
Close the stream only once the command has read what you sent it, by putting your input in response to output as above. Closing early is ignored and the command keeps waiting. If you have all the input up front, pass a string instead.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"vpod","description":"Give your agent a disposable Linux machine.","colors":{"primary":"#121212","light":"#e5e5e5","dark":"#121212"},"logo":{"light":"https://mintcdn.com/vpod/jo2aS6onH5gW_EaY/logo/light.svg?fit=max\u0026auto=format\u0026n=jo2aS6onH5gW_EaY\u0026q=85\u0026s=61715fcc0499fd9cbb17e105ffa27900","dark":"https://mintcdn.com/vpod/jo2aS6onH5gW_EaY/logo/dark.svg?fit=max\u0026auto=format\u0026n=jo2aS6onH5gW_EaY\u0026q=85\u0026s=3a5de1c67ec11460ccbc895437b5e9ac"},"favicon":"https://mintcdn.com/vpod/jo2aS6onH5gW_EaY/favicon.svg?fit=max\u0026auto=format\u0026n=jo2aS6onH5gW_EaY\u0026q=85\u0026s=9834db74a0da2de2ce06ed19122c65b3","appearance":{"default":"dark"},"background":{"color":{"light":"#ffffff","dark":"#121212"}},"navbar":{},"footer":{"socials":{"github":"https://github.com/capsulerun/vpod","website":"https://vpod.sh"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"vpod","hasAudioNarration":false,"actualSubdomain":"vpod","customDomains":["docs.vpod.sh"],"gitSource":{"type":"github","owner":"capsulerun","repo":"vpod-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6ab01613295cfe37c7f7ebfb","clientVersion":"0.0.4117","searchFilterCounts":[{"language":"default","tag":"TypeScript SDK","count":7},{"language":"default","tag":"Python SDK","count":5},{"language":"default","tag":"Get Started","count":3},{"language":"default","tag":"Embedded preview (In Iframe)","count":2},{"language":"default","tag":"Browser","count":2},{"language":"default","tag":"CLI","count":1},{"language":"default","tag":"Resources","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"sdk/python/process-io","slug":"/sdk/python/process-io","pageMetadata":{"title":"Process I/O","description":"Bound, interrupt, stream, and feed input to commands while they run.","icon":"arrows-left-right","href":"/sdk/python/process-io"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Bound, interrupt, stream, and feed input to commands while they run.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,p:`p`,pre:`pre`,span:`span`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[_jsx(_components.code,{children:`commands.run()`}),` returns everything at once when the command ends, which is all a quick command needs. Commands that run longer are worth bounding, watching, or feeding input to while they run. These options cover that; they layer onto the same `,_jsx(_components.a,{href:`/sdk/python/sandbox`,children:_jsx(_components.code,{children:`run()`})}),` call and none of them change its return value.`]}),`\n`,_jsx(Heading,{level:`2`,id:`timeouts`,children:`Timeouts`}),`\n`,_jsxs(_components.p,{children:[`Both `,_jsx(_components.code,{children:`commands.run()`}),` and `,_jsx(_components.code,{children:`code.run()`}),` accept a `,_jsx(_components.code,{children:`timeout`}),` parameter, in seconds. When the timeout is reached, the guest work is interrupted and the call returns instead of waiting for it to finish.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`with`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Sandbox.create() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.code.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"import time; time.sleep(30)\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`3`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`A shell command that hits its timeout returns with `,_jsx(_components.code,{children:`exit_code`}),` `,_jsx(_components.code,{children:`124`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sleep 30\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`3`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(result.exit_code) `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# 124`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`interrupting-a-command`,children:`Interrupting a command`}),`\n`,_jsxs(_components.p,{children:[`A command no longer has to run to its timeout. `,_jsx(_components.code,{children:`interrupt()`}),` stops whatever is in the foreground, and the call that was waiting returns with exit code `,_jsx(_components.code,{children:`130`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`7`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` threading`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`with`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Sandbox.create() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` threading.Timer(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1.0`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, sandbox.commands.interrupt).start()`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sleep 300\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(result.exit_code) `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# 130`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`The command really stops. This is not the caller walking away while the guest keeps working, so the sandbox is yours again immediately.`}),`\n`,_jsxs(_components.p,{children:[`Ctrl-C works too. It used to do nothing while a command was running, because `,_jsx(_components.code,{children:`KeyboardInterrupt`}),` could not land on a thread blocked inside the emulator. It now reaches the command, which makes an interactive REPL behave the way you would expect.`]}),`\n`,_jsxs(Note,{children:[_jsxs(_components.p,{children:[_jsx(_components.code,{children:`code.run()`}),` cannot be interrupted yet, so use `,_jsx(_components.code,{children:`timeout`}),` there.`]}),_jsxs(_components.p,{children:[`There is no `,_jsx(_components.code,{children:`signal`}),` parameter, and none is needed: `,_jsx(_components.code,{children:`run()`}),` blocks, so Ctrl-C reaches it directly and `,_jsx(_components.code,{children:`timeout`}),` already covers deadlines. The TypeScript SDK needs an `,_jsx(_components.code,{children:`AbortSignal`}),` because its call returns a promise and the caller keeps going.`]}),_jsx(_components.p,{children:`A command that ignores the interrupt runs to its own deadline and is recovered the same way a timeout is.`})]}),`\n`,_jsx(Heading,{level:`2`,id:`streaming-output`,children:`Streaming output`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`commands.run()`}),` hands back everything at once, when the command ends. For a build or a test run that is a long wait followed by a wall of text, so it also takes `,_jsx(_components.code,{children:`on_stdout`}),` and `,_jsx(_components.code,{children:`on_stderr`}),`, called with each piece of output as it arrives:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`10`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sys`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`with`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Sandbox.create() `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`as`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"for i in 1 2 3; do echo step $i; sleep 1; done\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`60`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` on_stdout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`sys.stdout.write,`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` )`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(result.exit_code) `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# 0`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The return value does not change, so you can add a callback to existing code and nothing else moves. Chunks are verbatim, exactly the bytes the program wrote, while `,_jsx(_components.code,{children:`result.stdout`}),` trims its trailing newline: joining the chunks gives you `,_jsx(_components.code,{children:`\"hi\\\\n\"`}),` where `,_jsx(_components.code,{children:`stdout`}),` gives you `,_jsx(_components.code,{children:`\"hi\"`}),`.`]}),`\n`,_jsx(_components.p,{children:`Chunks arrive as the guest produces output, not on a fixed schedule. A command printing two hundred lines with no pauses delivers them in one chunk; one printing a line a second delivers a chunk per line. A command that finishes quickly delivers a single chunk, which is indistinguishable from not streaming, and that is correct: there was nothing to stream.`}),`\n`,_jsxs(_components.p,{children:[`Streaming composes with interrupts. The chunks that arrived before the stop are kept, and the result still carries exit code `,_jsx(_components.code,{children:`130`}),`.`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`on_stdout`}),` and `,_jsx(_components.code,{children:`on_stderr`}),` are ordered against each other only when the writes are separated in time. Two processes that both flush as they exit can arrive stdout-first even though stderr was written first, because the two streams travel separately. Use one callback if you need a single ordered transcript.`]})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`code.run()`}),` does not stream, and does not accept `,_jsx(_components.code,{children:`on_stdout`}),`. Shell commands are what tend to run long enough to be worth watching.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`sending-input`,children:`Sending input`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`stdin`}),` gives the command something to read. A `,_jsx(_components.code,{children:`str`}),` or `,_jsx(_components.code,{children:`bytes`}),` becomes that command’s entire input, ending with a real EOF:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sort\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`stdin`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"banana`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`apple`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`cherry`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`print`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(result.stdout) `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# apple\\\\nbanana\\\\ncherry`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Input is byte-exact, so binary works the same way:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sha256sum\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`stdin`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`open`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"logo.png\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"rb\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`).read())`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Without `,_jsx(_components.code,{children:`stdin`}),` a command’s input is closed, which is why `,_jsx(_components.code,{children:`cat`}),` with no `,_jsx(_components.code,{children:`stdin`}),` returns at once rather than hanging.`]}),`\n`,_jsx(Heading,{level:`2`,id:`streaming-input`,children:`Streaming input`}),`\n`,_jsxs(_components.p,{children:[`Pass a `,_jsx(_components.code,{children:`queue.Queue`}),` when what you send next depends on what came back. That puts the command on a terminal, so you write as it runs and putting `,_jsx(_components.code,{children:`None`}),` ends its input. `,_jsx(_components.code,{children:`run()`}),` blocks, so put from `,_jsx(_components.code,{children:`on_stdout`}),` or from another thread:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`18`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`18`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` queue`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`inbox `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` queue.Queue()`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`seen `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` []`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`step `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 0`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` on_stdout`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`chunk`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` global`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` step`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` seen.append(chunk)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` text `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.join(seen)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` step `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`==`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 0`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` and`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \">>>\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` text:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` step `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` inbox.put(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"print(40 + 2)`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` elif`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` step `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`==`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` and`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"42\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` text:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` step `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 2`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` inbox.put(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`None`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"python3 2>\u00261\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`stdin`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`inbox, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`on_stdout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`on_stdout, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`60`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Match on the output so far rather than the chunk you were handed, and step through once: the prompt comes back after every answer.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`stdin`}),` accepts a `,_jsx(_components.code,{children:`str`}),`, `,_jsx(_components.code,{children:`bytes`}),`, a `,_jsx(_components.code,{children:`queue.Queue`}),`, or any iterable. An iterable is read one chunk at a time as the command runs, and running out ends the input:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` lines`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`():`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` yield`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"alpha`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` yield`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"beta`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:`\\\\n`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sandbox.commands.run(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"head -2\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`stdin`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`lines(), `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`timeout`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`60`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Use `,_jsx(_components.code,{children:`tty=True`}),` for a terminal with no input of its own, and `,_jsx(_components.code,{children:`timeout=0`}),` for no deadline, which is what an interactive session wants. Ctrl-C works throughout, and interrupts the command in the guest.`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Close the stream only once the command has read what you sent it, by putting your input in response to output as above. Closing early is ignored and the command keeps waiting. If you have all the input up front, pass a string instead.`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Process I/O","description":"Bound, interrupt, stream, and feed input to commands while they run.","icon":"arrows-left-right","href":"/sdk/python/process-io"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Timeouts","slug":"timeouts","depth":2,"children":[]},{"title":"Interrupting a command","slug":"interrupting-a-command","depth":2,"children":[]},{"title":"Streaming output","slug":"streaming-output","depth":2,"children":[]},{"title":"Sending input","slug":"sending-input","depth":2,"children":[]},{"title":"Streaming input","slug":"streaming-input","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"vpod","siteName":"vpod","title":"Process I/O - vpod","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-08-30T13:23:42.153Z","originalFileLocation":"sdk/python/process-io.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Bound, interrupt, stream, and feed input to commands while they run.\">\u003cmeta data-mint-head name=\"application-name\" content=\"vpod\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Process I/O - vpod\">\u003cmeta data-mint-head property=\"og:description\" content=\"Bound, interrupt, stream, and feed input to commands while they run.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"vpod\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.vpod.sh/sdk/python/process-io\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://vpod.mintlify.site/_mintlify/api/og/v2?division=Python+SDK\u0026amp;title=Process+I%2FO\u0026amp;description=Bound%2C+interrupt%2C+stream%2C+and+feed+input+to+commands+while+they+run.\u0026amp;theme=48dc19e4050caeb2026842a5\u0026amp;signature=424469ee991a66c901476c13963cca7765dae0303929a159559c849858c44b95\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Process I/O - vpod\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Bound, interrupt, stream, and feed input to commands while they run.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://vpod.mintlify.site/_mintlify/api/og/v2?division=Python+SDK\u0026amp;title=Process+I%2FO\u0026amp;description=Bound%2C+interrupt%2C+stream%2C+and+feed+input+to+commands+while+they+run.\u0026amp;theme=48dc19e4050caeb2026842a5\u0026amp;signature=424469ee991a66c901476c13963cca7765dae0303929a159559c849858c44b95\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/vpod/Gs2hVi5r4RXyLioT/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"vpod\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#121212\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.vpod.sh/sdk/python/process-io\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/sdk/python/process-io.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.vpod.sh/#organization\",\"name\":\"vpod\",\"url\":\"https://docs.vpod.sh\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/vpod/jo2aS6onH5gW_EaY/logo/light.svg?fit=max\u0026auto=format\u0026n=jo2aS6onH5gW_EaY\u0026q=85\u0026s=61715fcc0499fd9cbb17e105ffa27900\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.vpod.sh#website\",\"name\":\"vpod\",\"url\":\"https://docs.vpod.sh\",\"publisher\":{\"@id\":\"https://docs.vpod.sh/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.vpod.sh/sdk/python/process-io#webpage\",\"url\":\"https://docs.vpod.sh/sdk/python/process-io\",\"name\":\"Process I/O\",\"description\":\"Bound, interrupt, stream, and feed input to commands while they run.\",\"dateModified\":\"2026-08-30T13:23:42.153Z\",\"isPartOf\":{\"@id\":\"https://docs.vpod.sh#website\"},\"breadcrumb\":{\"@id\":\"https://docs.vpod.sh/sdk/python/process-io#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.vpod.sh/sdk/python/process-io#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Python SDK\",\"item\":\"https://docs.vpod.sh/sdk/python/sandbox\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Process I/O\",\"item\":\"https://docs.vpod.sh/sdk/python/process-io\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.vpod.sh/sdk/python/process-io#article\",\"headline\":\"Process I/O\",\"name\":\"Process I/O\",\"description\":\"Bound, interrupt, stream, and feed input to commands while they run.\",\"url\":\"https://docs.vpod.sh/sdk/python/process-io\",\"mainEntityOfPage\":{\"@id\":\"https://docs.vpod.sh/sdk/python/process-io#webpage\"},\"dateModified\":\"2026-08-30T13:23:42.153Z\",\"publisher\":{\"@id\":\"https://docs.vpod.sh/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.vpod.sh#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"vpod\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"vpod\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/sdk/python/process-io.md","siteName":"vpod","nav":{"global":null,"groups":[{"group":"Get Started","pages":[{"title":"Introduction","icon":"terminal","href":"/index"},{"title":"Quickstart","icon":"rocket","href":"/quickstart"},{"title":"Private snapshots","icon":"key","href":"/private-snapshots"}]},{"group":"TypeScript SDK","pages":[{"title":"Sandbox","icon":"cube","href":"/sdk/typescript/sandbox"},{"title":"Process I/O","icon":"arrows-left-right","href":"/sdk/typescript/process-io"},{"title":"Tracing","icon":"footprints","href":"/sdk/typescript/tracing"},{"title":"Snapshots","icon":"camera","href":"/sdk/typescript/snapshots"},{"title":"Suspend \u0026 resume","icon":"pause","href":"/sdk/typescript/suspend-resume"},{"group":"Browser","pages":[{"title":"Running in a browser","icon":"globe","href":"/sdk/typescript/browser"},{"title":"Embedding","icon":"box","href":"/sdk/typescript/embedding"}]}]},{"group":"Python SDK","pages":[{"title":"Sandbox","description":"Create sandboxes, run commands, and execute Python code.","icon":"cube","href":"/sdk/python/sandbox"},{"title":"Process I/O","icon":"arrows-left-right","href":"/sdk/python/process-io"},{"title":"Tracing","description":"Record what a sandbox did: which programs ran, which files changed, where it connected.","icon":"footprints","href":"/sdk/python/tracing"},{"title":"Snapshots","icon":"camera","href":"/sdk/python/snapshots"},{"title":"Suspend \u0026 resume","icon":"pause","href":"/sdk/python/suspend-resume"}]},{"group":"Embedded preview (In Iframe)","pages":[{"title":"Embed a preview","icon":"window-maximize","href":"/preview/embed"},{"title":"The iframe bridge","icon":"arrows-left-right","href":"/preview/bridge"}]},{"group":"CLI","pages":[{"title":"CLI reference","icon":"terminal","href":"/cli/reference"}]},{"group":"Resources","pages":[{"title":"Contributing","icon":"code-pull-request","href":"/contributing"}]}]},"basePath":"","title":"Process I/O - vpod","buildId":"dpl_41S5Z2jG9QnfDRwN1KZrLdBwj7DM","deploymentId":"dpl_41S5Z2jG9QnfDRwN1KZrLdBwj7DM","dynamics":[],"chunks":[]}