Daytona provides pseudo terminal (PTY) capabilities through the process module in sandboxes. A PTY is a process started with the PTY kind: it runs under a virtual terminal so programs behave as if connected to a real terminal, with terminal size, line discipline, and interactive prompts.
PTY processes are exposed through a sandbox’s PTY namespace and share the handle API of other processes, described in process execution.
PTY sessions are used when a program expects a real terminal.
Interactive development: REPLs, debuggers, and editors that read keystrokes and redraw the screen.
Terminals in web applications: a browser terminal connects to a PTY session, sends keystrokes, and resizes the session with the window.
Builds and tests: compilers, test runners, and deploy tools that show progress or colors only when attached to a terminal.
System administration: setup tools and package managers that ask questions before they continue.
Interrupts: a long-running process receives Ctrl+C through the terminal and stops cleanly.
Reconnects: a client that reconnects replays the output from a cursor and sees what it missed.
Shared sessions: a named session is reachable by its name from another client. Clients attached to one session at the same time share its shell, keystrokes, and output.
Terminal agents: an agent works in one interactive shell that keeps its working directory and variables between commands. It reads the output as a terminal shows it, including escape sequences.
Start a PTY session. Without a command, the session runs an interactive shell: the login shell of the user it runs as, or the first of bash, zsh, and sh found in the image. With a command, the session runs that command in the terminal instead. The terminal starts at 80 columns by 24 rows unless you set a size, and you can resize it later.
The SDKs and the CLI keep an exited session’s record and output until deleted.
# Without a command the PTY runs an interactive shell; the terminal defaults to 80x24
handle = sandbox.pty.start()
print(handle.id)
import { Daytona } from '@daytona/sdk'
constdaytona=newDaytona()
constsandbox= await daytona.v2.create()
// Without a command the PTY runs an interactive shell; the terminal defaults to 80x24
consthandle= await sandbox.pty.start()
console.log(handle.id)
Terminal window
# The CLI needs a command, so this starts bash; requires a terminal, and the PTY takes its size
daytonasandboxexec{sandboxId}--tty--bash
Flag
Type
Description
--timeout
string
Limits how long exec stays attached. When the limit elapses, the CLI exits with code 8 and the session keeps running. This is a global flag. The default is 10m.
The CLI runs the arguments after -- as a program, without a shell.
Wrap shell syntax in bash -c '...'.
When the session ends, the CLI exits with the exit code of the process.
The CLI cannot delete the session record and its output, so use an SDK or the API.
Terminal window
# Without shellCommand the PTY runs an interactive shell; terminal defaults to 80x24.
# The SDKs set keepLogs to until_cleanup; the API default for unnamed processes is on_exit_ttl.
Name a PTY session. A name aliases the session ID, so another client can reach the session without knowing its ID. The name belongs to the session only while it runs: when the session exits, the name is released for reuse, and the session stays reachable by its ID only.
Configure the shell, the user, and the timeout of a PTY session. A shell that cannot be found or a user that does not exist fails the start. When the timeout elapses, the session is killed and reports that it timed out. The Python SDK does not set these options for PTY sessions.
Connect to an existing PTY session by its ID. Connecting creates a handle without contacting the sandbox; the handle sends input to the session, reads its output, resizes it, and stops it. A live connection streams output produced after it opens; to see earlier output, replay it from a cursor.
Stop a PTY session and remove it. Stopping sends a signal to the session’s processes; removing deletes the session record and its output. Removing a session that is still running kills it first.
Delete a PTY session in one step: a running session gets a termination signal, then the session record and its output are removed. Deleting a non-PTY process fails and leaves it running.
Resize the terminal of a running PTY session. The program in the terminal receives a window size change signal and can redraw at the new size. The session record reports the new size.
Send input to a PTY session. Input reaches the terminal as if typed, so end each command with a newline. Control keys are bytes: send Ctrl+C as 0x03 and Ctrl+D as 0x04. A terminal has no separate end of input; to end input, send Ctrl+D.
Read one page of PTY output. A page holds up to 1,000 frames by default. To read past the first page, continue from a cursor as shown in replay output from a cursor.
Replay PTY output from a cursor. Every output frame carries a cursor, and a read with a cursor returns the frames after it, so a client that saved the last cursor it processed can resume without gaps or duplicates. Retention can evict old output; a cursor that points into evicted output fails, and the error carries the oldest cursor still available. See log retention.
Wait for a PTY session to exit. The result holds the exit code, the ending signal if any, and a reason: exited, killed by a signal, timed out, failed to start, or lost. If the wait time elapses first, the result reports a timeout with no exit code, and the session keeps running.
Run several commands in one interactive shell. The shell keeps its state between commands, such as the working directory and variables. Read output while you send input; the output stream ends after the shell exits and all of its output is delivered.
Interrupt a running command from the terminal. Ctrl+C sent as input goes through the terminal, which interrupts the foreground command; the shell itself keeps running. Signaling the session instead targets the whole session, including the shell. See kill PTY session.
Remove a PTY session when you no longer need it. The SDKs keep an exited session’s record and output until it is deleted, so delete it in a final block to remove it even when a step fails.