# Process

## ProcessHandle

```python
class ProcessHandle()
```

Serializable handle for one daemon process.

#### ProcessHandle.\_\_init\_\_

```python
def __init__(impl: AsyncProcessHandle, bridge: SyncBridge) -> None
```

#### ProcessHandle.sandbox\_id

```python
@property
def sandbox_id() -> str
```

#### ProcessHandle.process\_id

```python
@property
def process_id() -> str
```

#### ProcessHandle.id

```python
@property
def id() -> str
```

#### ProcessHandle.kind

```python
@property
def kind() -> Literal['exec', 'pty', 'code', 'session'] | None
```

#### ProcessHandle.attach

```python
def attach() -> None
```

Attach is optional in Python because no runtime WebSocket dependency is bundled.

#### ProcessHandle.delete

```python
def delete() -> None
```

Delete the process record and retained logs, stopping it first.

#### ProcessHandle.from\_json

```python
@classmethod
def from_json(value: Mapping[str, str]) -> ProcessHandle
```

Rehydrate a handle identity without making a network request.

#### ProcessHandle.get

```python
def get() -> ProcessInfo
```

Fetch current process metadata.

#### ProcessHandle.kill

```python
def kill(*,
         signal: SignalName = 'TERM',
         escalate_after: Optional[float] = None,
         escalate_to: SignalName = 'KILL') -> None
```

Send a signal and optional escalation signal.

#### ProcessHandle.logs

```python
def logs(*,
         cursor: Optional[str] = None,
         limit: Optional[int] = None,
         encoding: LogEncoding = 'text') -> LogPage
```

Read a cursor-replayable process log page.

#### ProcessHandle.ref

```python
def ref() -> ProcessHandleRef
```

Return a typed handle identity.

#### ProcessHandle.resize

```python
def resize(cols: int, rows: int) -> None
```

Resize a PTY process.

#### ProcessHandle.stdin

```python
def stdin(data: Union[str, bytes], *, eof: bool = False) -> None
```

Write stdin to an exec or PTY process created with stdin='open'.

#### ProcessHandle.stdin\_eof

```python
def stdin_eof() -> None
```

Close stdin for an exec or PTY process.

#### ProcessHandle.stream\_logs

```python
def stream_logs(*,
                cursor: Optional[str] = None,
                encoding: LogEncoding = 'text') -> Iterator[LogFrame]
```

Follow process logs with SSE while retaining cursor replay semantics.

#### ProcessHandle.to\_json

```python
def to_json() -> Dict[str, str]
```

Return a JSON-safe handle identity.

#### ProcessHandle.wait

```python
def wait(*, timeout: Optional[float] = None) -> WaitResult
```

Wait for terminal state using the daemon long-poll contract.

## AsyncProcessHandle

```python
class AsyncProcessHandle()
```

Serializable handle for one daemon process.

#### AsyncProcessHandle.\_\_init\_\_

```python
def __init__(sandbox_id: str,
             process_id: str,
             transport: Optional[AsyncTransport] = None,
             kind: Optional[ProcessKind] = None) -> None
```

#### AsyncProcessHandle.to\_json

```python
def to_json() -> Dict[str, str]
```

Return a JSON-safe handle identity.

#### AsyncProcessHandle.from\_json

```python
@classmethod
def from_json(value: Mapping[str, str]) -> AsyncProcessHandle
```

Rehydrate a handle identity without making a network request.

#### AsyncProcessHandle.ref

```python
def ref() -> ProcessHandleRef
```

Return a typed handle identity.

#### AsyncProcessHandle.bind

```python
def bind(transport: AsyncTransport) -> AsyncProcessHandle
```

Return this handle bound to a transport.

#### AsyncProcessHandle.get

```python
async def get() -> ProcessInfo
```

Fetch current process metadata.

#### AsyncProcessHandle.wait

```python
async def wait(*, timeout: Optional[float] = None) -> WaitResult
```

Wait for terminal state using the daemon long-poll contract.

`timeout` is the caller wait budget in seconds; `0` waits
unbounded.

#### AsyncProcessHandle.logs

```python
async def logs(*,
               cursor: Optional[str] = None,
               limit: Optional[int] = None,
               encoding: LogEncoding = 'text') -> LogPage
```

Read a cursor-replayable process log page.

#### AsyncProcessHandle.stream\_logs

```python
async def stream_logs(*,
                      cursor: Optional[str] = None,
                      encoding: LogEncoding = 'text') -> AsyncIterator[LogFrame]
```

Follow process logs with SSE while retaining cursor replay semantics.

#### AsyncProcessHandle.stdin

```python
async def stdin(data: Union[str, bytes], *, eof: bool = False) -> None
```

Write stdin to an exec or PTY process created with stdin='open'.

#### AsyncProcessHandle.stdin\_eof

```python
async def stdin_eof() -> None
```

Close stdin for an exec or PTY process.

#### AsyncProcessHandle.kill

```python
async def kill(*,
               signal: SignalName = 'TERM',
               escalate_after: Optional[float] = None,
               escalate_to: SignalName = 'KILL') -> None
```

Send a signal and optional escalation signal.

#### AsyncProcessHandle.resize

```python
async def resize(cols: int, rows: int) -> None
```

Resize a PTY process.

#### AsyncProcessHandle.attach

```python
def attach() -> None
```

Attach is optional in Python because no runtime WebSocket dependency is bundled.

#### AsyncProcessHandle.delete

```python
async def delete() -> None
```

Delete the process record and retained logs, stopping it first.

Raises `UnsupportedOperationError` for a running code cell and for a
session command that has not stopped within 5 s: delete its session.

## ProcessService

```python
class ProcessService()
```

Sandbox process namespace.

#### ProcessService.\_\_init\_\_

```python
def __init__(impl: AsyncProcessService, bridge: SyncBridge) -> None
```

#### ProcessService.connect

```python
def connect(process_id: Union[str, Mapping[str, str]]) -> ProcessHandle
```

Create a bound process handle without fetching metadata.

#### ProcessService.connect\_session

```python
def connect_session(session_id: str | Mapping[str, object]) -> Session
```

Bind a session id or serialized identity without making a request.

#### ProcessService.create\_session

```python
def create_session(*,
                   cwd: Optional[str] = None,
                   env: Optional[Mapping[str, str]] = None,
                   shell: Optional[str] = None,
                   login: Optional[bool] = None,
                   name: Optional[str] = None) -> Session
```

Create one persistent shell; cwd and env apply to all its commands.

#### ProcessService.get

```python
def get(process_id: str) -> ProcessInfo
```

Fetch current process metadata by id or live name alias.

#### ProcessService.list

```python
def list(*,
         state: Optional[ProcessStateFilter] = None,
         kind: Optional[ProcessKind] = None,
         session_id: Optional[str] = None,
         name: Optional[str] = None,
         pid: Optional[int] = None) -> ListResult[ProcessInfo]
```

#### ProcessService.run

```python
def run(command: Optional[str] = None,
        *,
        argv: Optional[Sequence[str]] = None,
        cwd: Optional[str] = None,
        env: Optional[Mapping[str, str]] = None,
        user: Optional[str] = None,
        shell: Optional[str] = None,
        login: Optional[bool] = None,
        stdin: StdinMode = 'closed',
        timeout: Optional[float] = None,
        execution_timeout: Optional[float] = None,
        name: Optional[str] = None,
        terminal: Optional[TerminalSize] = None,
        keep_logs: Optional[KeepLogs] = None) -> ProcessResult
```

Start a process, wait for its shell to exit, and collect its output.

#### ProcessService.start

```python
def start(command: Optional[str] = None,
          *,
          argv: Optional[Sequence[str]] = None,
          name: Optional[str] = None,
          cwd: Optional[str] = None,
          env: Optional[Mapping[str, str]] = None,
          user: Optional[str] = None,
          shell: Optional[str] = None,
          login: Optional[bool] = None,
          stdin: StdinMode = 'closed',
          execution_timeout: Optional[float] = None,
          terminal: Optional[TerminalSize] = None,
          keep_logs: Optional[KeepLogs] = None) -> ProcessHandle
```

Start a detached process and return a handle immediately.

## AsyncProcessService

```python
class AsyncProcessService()
```

Sandbox process namespace.

#### AsyncProcessService.\_\_init\_\_

```python
def __init__(sandbox_id: str,
             transport: AsyncTransport,
             language: Optional[str] = None) -> None
```

#### AsyncProcessService.create\_session

```python
async def create_session(*,
                         cwd: Optional[str] = None,
                         env: Optional[Mapping[str, str]] = None,
                         shell: Optional[str] = None,
                         login: Optional[bool] = None,
                         name: Optional[str] = None) -> AsyncSession
```

Create one persistent shell; cwd and env apply to all its commands.

`shell` must be a POSIX shell (bash, sh, dash, zsh, ksh) on Linux
and macOS; another shell is refused when the session is created. On
Windows, `pwsh` or `powershell`.

#### AsyncProcessService.connect\_session

```python
def connect_session(session_id: str | Mapping[str, object]) -> AsyncSession
```

Bind a session id or serialized identity without making a request.

#### AsyncProcessService.start

```python
async def start(command: Optional[str] = None,
                *,
                argv: Optional[Sequence[str]] = None,
                name: Optional[str] = None,
                cwd: Optional[str] = None,
                env: Optional[Mapping[str, str]] = None,
                user: Optional[str] = None,
                shell: Optional[str] = None,
                login: Optional[bool] = None,
                stdin: StdinMode = 'closed',
                execution_timeout: Optional[float] = None,
                terminal: Optional[TerminalSize] = None,
                keep_logs: Optional[KeepLogs] = None) -> AsyncProcessHandle
```

Start a detached process and return a handle immediately.

Unlike `run`, this returns as soon as the daemon has started the
process. Use the returned `ProcessHandle` to stream logs
(`handle.stream_logs()`), wait for exit (`handle.wait()`), or kill
(`handle.kill()`). This is the right choice for long-running servers —
call `start()` once, then poll the port or stream logs to confirm the
server is ready.

**Shell selection.** A string `command` runs through the sandbox shell
(`bash`, else `sh`; pin another with `shell=`). Quote globs and brackets
(`pip install -e '.[test]'`). Use `argv=` to bypass the shell for
untrusted input. For persistent shell state, use `create_session`.

:param command: Shell command string; mutually exclusive with `argv`.
:param argv: Argument vector for shell-free execution.
:param cwd: Working directory inside the sandbox.
:param env: Extra environment variables merged into the process environment.
:param shell: Shell binary to use (e.g. `"bash"`); overrides auto-detection.
:param execution_timeout: Server-side deadline in seconds. The daemon kills
    the process tree when this expires.
:returns: Bound `ProcessHandle` — logs, wait, and kill are available
    immediately.

Example — start an HTTP server and wait for it to be ready::

    handle = await sandbox.process.start("python3 -m http.server 8000")
    # poll or stream logs; the process keeps running in the background

#### AsyncProcessService.run

```python
async def run(command: Optional[str] = None,
              *,
              argv: Optional[Sequence[str]] = None,
              cwd: Optional[str] = None,
              env: Optional[Mapping[str, str]] = None,
              user: Optional[str] = None,
              shell: Optional[str] = None,
              login: Optional[bool] = None,
              stdin: StdinMode = 'closed',
              timeout: Optional[float] = None,
              execution_timeout: Optional[float] = None,
              name: Optional[str] = None,
              terminal: Optional[TerminalSize] = None,
              keep_logs: Optional[KeepLogs] = None) -> ProcessResult
```

Start a process, wait for its shell to exit, and collect its output.

The common case is one round trip: the daemon starts the process, parks
the request until it exits (or `timeout` expires), and returns the
output inline. A process that outlives the wait window or produces more
output than fits in one page falls back to split calls automatically.

The result holds the output the daemon still has when the call returns:
its per-process log is bounded, so very large output loses its oldest
frames, and a result that timed out collects only the first few log
pages.

**Shell selection.** A string `command` runs through the sandbox shell
(`bash`, else `sh`; pin another with `shell=`). Quote globs and brackets
(`pip install -e '.[test]'`) so the command means the same under any
shell. Use `argv=` to bypass the shell entirely, which is the safe
form for untrusted arguments. For persistent shell state, use `create_session`.

**Background processes.** The call returns when the shell exits. If the
command forks a background child that holds its output descriptors open
(e.g. `python3 -m http.server 8000 &`), the daemon waits at most ~2
seconds for output to drain and then returns; output the child writes
later is not part of the result. For a long-running server prefer
`start`, which returns a `ProcessHandle` immediately, or
redirect: `nohup cmd > server.log 2>&1 &`.

:param command: Shell command string; mutually exclusive with `argv`.
:param argv: Argument vector for shell-free execution.
:param cwd: Working directory inside the sandbox.
:param env: Extra environment variables merged into the process environment.
:param shell: Shell binary to use (e.g. `"bash"`); overrides auto-detection.
:param timeout: Caller wait budget in seconds. Omit to wait until the process
    ends. Does not kill the process on expiry.
:param execution_timeout: Server-side deadline in seconds. The daemon kills
    the process tree when this expires.
:returns: `daytona.v2.types.ProcessResult` with `stdout`, `stderr`,
    `output`, `exit_code`, and `reason`.

Example::

    result = await sandbox.process.run("pip install httpx")
    if result.exit_code != 0:
        raise RuntimeError(result.stderr)

#### AsyncProcessService.connect

```python
def connect(process_id: Union[str, Mapping[str, str]]) -> AsyncProcessHandle
```

Create a bound process handle without fetching metadata.

#### AsyncProcessService.get

```python
async def get(process_id: str) -> ProcessInfo
```

Fetch current process metadata by id or live name alias.

#### AsyncProcessService.list

```python
async def list(*,
               state: Optional[ProcessStateFilter] = None,
               kind: Optional[ProcessKind] = None,
               session_id: Optional[str] = None,
               name: Optional[str] = None,
               pid: Optional[int] = None) -> ListResult[ProcessInfo]
```

## PtyService

```python
class PtyService()
```

PTY convenience namespace.

#### PtyService.\_\_init\_\_

```python
def __init__(impl: AsyncPtyService, bridge: SyncBridge) -> None
```

#### PtyService.connect

```python
def connect(process_id: str) -> ProcessHandle
```

Create a bound PTY handle.

#### PtyService.delete

```python
def delete(process_id: str) -> None
```

#### PtyService.list

```python
def list() -> ListResult[ProcessInfo]
```

#### PtyService.start

```python
def start(command: Optional[str] = None,
          *,
          cols: int = 80,
          rows: int = 24,
          cwd: Optional[str] = None,
          env: Optional[Mapping[str, str]] = None,
          name: Optional[str] = None) -> ProcessHandle
```

Start a detached PTY process.

## AsyncPtyService

```python
class AsyncPtyService()
```

PTY convenience namespace.

#### AsyncPtyService.\_\_init\_\_

```python
def __init__(process: AsyncProcessService) -> None
```

#### AsyncPtyService.start

```python
async def start(command: Optional[str] = None,
                *,
                cols: int = 80,
                rows: int = 24,
                cwd: Optional[str] = None,
                env: Optional[Mapping[str, str]] = None,
                name: Optional[str] = None) -> AsyncProcessHandle
```

Start a detached PTY process.

#### AsyncPtyService.connect

```python
def connect(process_id: str) -> AsyncProcessHandle
```

Create a bound PTY handle.

#### AsyncPtyService.list

```python
async def list() -> ListResult[ProcessInfo]
```

#### AsyncPtyService.delete

```python
async def delete(process_id: str) -> None
```

## Session

```python
class Session()
```

One persistent shell whose commands run one at a time, in order.

#### Session.\_\_init\_\_

```python
def __init__(impl: AsyncSession, bridge: SyncBridge) -> None
```

#### Session.sandbox\_id

```python
@property
def sandbox_id() -> str
```

#### Session.id

```python
@property
def id() -> str
```

#### Session.delete

```python
def delete() -> None
```

End this shell and remove it and all its commands.

#### Session.from\_json

```python
@classmethod
def from_json(value: Mapping[str, object]) -> Session
```

Rehydrate an unbound identity without making a request.

#### Session.get

```python
def get() -> ProcessInfo
```

Fetch session metadata, including the shell's live cwd.

#### Session.run

```python
def run(command: str,
        *,
        stdin: StdinMode = 'closed',
        timeout: Optional[float] = None,
        execution_timeout: Optional[float] = None,
        name: Optional[str] = None,
        keep_logs: Optional[KeepLogs] = None) -> ProcessResult
```

Run a command in this shell and collect output; timeouts are seconds.

#### Session.start

```python
def start(command: str,
          *,
          stdin: StdinMode = 'closed',
          execution_timeout: Optional[float] = None,
          name: Optional[str] = None,
          keep_logs: Optional[KeepLogs] = None) -> ProcessHandle
```

Queue a command and return its handle without waiting for exit.

#### Session.to\_json

```python
def to_json() -> _SessionIdentity
```

Return a JSON-safe identity for `process.connect_session()`.

## AsyncSession

```python
class AsyncSession()
```

One persistent shell whose commands run one at a time, in order.

Directory changes, exports and functions carry over between commands.
Set cwd and env when calling `process.create_session()`. Interrupt a
running command with `handle.kill(signal="INT")`; the session survives.
Sessions do not survive a sandbox stop/start. On Windows, interrupts stop
external programs but cannot interrupt PowerShell loops or cmdlets, and
commands cannot take `stdin="open"`. After `set -x` or `set -v` in a
session, later commands' stderr also traces the daemon's own lines that
run each command.

#### AsyncSession.\_\_init\_\_

```python
def __init__(sandbox_id: str,
             session_id: str,
             transport: Optional[AsyncTransport] = None) -> None
```

#### AsyncSession.to\_json

```python
def to_json() -> _SessionIdentity
```

Return a JSON-safe identity for `process.connect_session()`.

#### AsyncSession.from\_json

```python
@classmethod
def from_json(value: Mapping[str, object]) -> AsyncSession
```

Rehydrate an unbound identity without making a request.

#### AsyncSession.run

```python
async def run(command: str,
              *,
              stdin: StdinMode = 'closed',
              timeout: Optional[float] = None,
              execution_timeout: Optional[float] = None,
              name: Optional[str] = None,
              keep_logs: Optional[KeepLogs] = None) -> ProcessResult
```

Run a command in this shell and collect output; timeouts are seconds.

`timeout` bounds the caller's wait without stopping the command;
`execution_timeout` stops the command without ending the session. A
command that has not stopped 5 s after its timeout (the shell could
not interrupt it and it runs no process to kill) ends the session
instead. In dash, BusyBox `sh` and mksh an interrupt leaves only the
innermost shell function or sourced file, as it does in bash older than
4.4 (macOS's `/bin/bash`) when a DEBUG trap is set.

#### AsyncSession.start

```python
async def start(command: str,
                *,
                stdin: StdinMode = 'closed',
                execution_timeout: Optional[float] = None,
                name: Optional[str] = None,
                keep_logs: Optional[KeepLogs] = None) -> AsyncProcessHandle
```

Queue a command and return its handle without waiting for exit.

Interrupt it with `handle.kill(signal="INT")`; the shell survives.
`execution_timeout` is a server-side deadline in seconds; the clock
starts when the command starts, after any queued commands ahead of it.

#### AsyncSession.get

```python
async def get() -> ProcessInfo
```

Fetch session metadata, including the shell's live cwd.

#### AsyncSession.delete

```python
async def delete() -> None
```

End this shell and remove it and all its commands.

## ProcessInfo

```python
@dataclass(frozen=True)
class ProcessInfo()
```

Serializable daemon process DTO.

**Attributes**:

- `id` _str_
- `kind` _ProcessInfoKind_
- `state` _ProcessState_
- `name` _Optional\[str\] = None_
- `pid` _Optional\[int\] = None_
- `system` _bool = False_
- `session_id` _Optional\[str\] = None_
- `shell_command` _Optional\[str\] = None_
- `argv` _Optional\[List\[str\]\] = None_
- `code` _Optional\[str\] = None_
- `language` _Optional\[str\] = None_
- `shell` _Optional\[str\] = None_
- `resolved_shell` _Optional\[str\] = None_
- `login` _Optional\[bool\] = None_
- `cwd` _Optional\[str\] = None_
- `user` _Optional\[str\] = None_
- `stdin` _Optional\[ProcessStdinMode\] = None_
- `execution_timeout` _Optional\[float\] = None_
- `terminal` _Optional\[TerminalSize\] = None_
- `keep_logs` _Optional\[ProcessKeepLogs\] = None_
- `exit_code` _Optional\[int\] = None_
- `signal` _Optional\[str\] = None_
- `reason` _Optional\[WaitReason\] = None_
- `created_at` _Optional\[str\] = None_
- `started_at` _Optional\[str\] = None_
- `exited_at` _Optional\[str\] = None_
- `truncated_head` _bool = False_
- `first_available_cursor` _Optional\[str\] = None_
- `last_cursor` _Optional\[str\] = None_
- `raw_kind` _Optional\[str\] = None_
- `raw_state` _Optional\[str\] = None_
- `raw_stdin` _Optional\[str\] = None_
- `raw_keep_logs` _Optional\[str\] = None_
- `raw_reason` _Optional\[str\] = None_

## ProcessHandleRef

```python
@dataclass(frozen=True)
class ProcessHandleRef()
```

JSON-safe process handle identity.

**Attributes**:

- `sandbox_id` _str_
- `process_id` _str_
- `kind` _Optional\[ProcessKind\] = None_

## WaitResult

```python
@dataclass(frozen=True)
class WaitResult()
```

Result returned by process wait.

**Attributes**:

- `exit_code` _Optional\[int\] = None_
- `signal` _Optional\[str\] = None_
- `reason` _Optional\[WaitReason\] = None_
- `raw_reason` _Optional\[str\] = None_

## LogFrame

```python
@dataclass(frozen=True)
class LogFrame()
```

One replayable process ledger frame.

**Attributes**:

- `cursor` _str_
- `channel` _str_
- `data` _str_
- `timestamp` _Optional\[int\] = None_

## LogPage

```python
@dataclass(frozen=True)
class LogPage()
```

A cursor-addressed process log page.

**Attributes**:

- `items` _List\[LogFrame\]_
- `next_cursor` _Optional\[str\] = None_
- `truncated_head` _bool = False_
- `first_available_cursor` _Optional\[str\] = None_

## ProcessResult

```python
@dataclass(frozen=True)
class ProcessResult()
```

Process run result with collected output.

**Attributes**:

- `process_id` _str_
- `exit_code` _Optional\[int\]_
- `signal` _Optional\[str\]_
- `reason` _Optional\[WaitReason\]_
- `stdout` _str = ''_
- `stderr` _str = ''_
- `output` _str = ''_
- `raw_reason` _Optional\[str\] = None_

## TerminalSize

```python
@dataclass(frozen=True)
class TerminalSize()
```

PTY terminal dimensions.

**Attributes**:

- `cols` _int_
- `rows` _int_

## ProcessKind

```python
ProcessKind = Literal['exec', 'pty', 'code', 'session']
```

## ProcessInfoKind

```python
ProcessInfoKind = Literal['exec', 'pty', 'code', 'session', 'unknown']
```

## ProcessStateFilter

```python
ProcessStateFilter = Literal['running', 'terminal', 'all']
```

## ProcessState

```python
ProcessState = Literal['starting', 'provisioning', 'running', 'terminal', 'unknown']
```

## KeepLogs

```python
KeepLogs = Literal['until_cleanup', 'on_exit_ttl', 'none']
```

## StdinMode

```python
StdinMode = Literal['closed', 'open']
```

## ProcessKeepLogs

```python
ProcessKeepLogs = Literal['until_cleanup', 'on_exit_ttl', 'none', 'unknown']
```

## ProcessStdinMode

```python
ProcessStdinMode = Literal['closed', 'open', 'unknown']
```

## WaitReason

```python
WaitReason = Literal['exited', 'signaled', 'timed_out', 'lost', 'failed', 'unknown']
```