> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tokenfactory.nebius.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Running Commands

ConTree SDK provides multiple ways to execute commands in containers, from simple shell commands to complex workflows with file handling and custom I/O.

## Basic Command Execution

You can run commands using shell syntax or by specifying command and arguments separately:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    image = await client.images.use("busybox:latest")
    print(f"Using {image=}")

    result = await image.run(shell="echo 'Hello World'")
    print(f"Simple echo: {result.stdout=}, {result.stderr=}, {result.exit_code=}")

    result = await image.run(shell="pwd")
    print(f"Current directory: {result.stdout=}, {result.exit_code=}")

    result = await image.run(shell="ls -la")
    print(f"Directory listing: {result.stdout=}, {result.exit_code=}")

    result = await image.run(shell="cat -", stdin="Hello from stdin\n")
    print(f"Cat with stdin: {result.stdout=}, {result.exit_code=}")

    result = await image.run(shell="echo 'Error message' >&2; exit 1")
    print(f"Error command: {result.stdout=}, {result.stderr=}, {result.exit_code=}")
    ```

    See [`ContreeImage.run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImage.run) and [`ContreeSession.run()`](./reference/session#contree_sdk.sdk.objects.session.ContreeSession.run) for all options.
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    image = client.images.use("busybox:latest")
    print(f"Using {image=}")

    result = image.run(shell="echo 'Hello World'").wait()
    print(f"Simple echo: {result.stdout=}, {result.stderr=}, {result.exit_code=}")

    result = image.run(shell="pwd").wait()
    print(f"Current directory: {result.stdout=}, {result.exit_code=}")

    result = image.run(shell="ls -la").wait()
    print(f"Directory listing: {result.stdout=}, {result.exit_code=}")

    result = image.run(shell="cat -", stdin="Hello from stdin\n").wait()
    print(f"Cat with stdin: {result.stdout=}, {result.exit_code=}")

    result = image.run(shell="echo 'Error message' >&2; exit 1").wait()
    print(f"Error command: {result.stdout=}, {result.stderr=}, {result.exit_code=}")
    ```

    See [`ContreeImageSync.run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImageSync.run) and [`ContreeSessionSync.run()`](./reference/session#contree_sdk.sdk.objects.session.ContreeSessionSync.run) for all options.
  </Tab>
</Tabs>

## Command Execution Mode

You can execute commands by specifying the executable path and arguments separately:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    image = await client.images.use("alpine:3.20", strict=True)
    print(f"Pulled {image=}")

    print("\nExample 1: Simple command execution")
    result = await image.run("/bin/echo", args=["Hello from command parameter!"])
    print(f"Result: {result.stdout=}, {result.exit_code=}")

    print("\nExample 2: Command with arguments")
    result = await image.run("/bin/ls", args=["-la", "/tmp"])
    print(f"Result: {result.stdout=}, {result.exit_code=}")

    print("\nExample 3: Command with environment variables")
    result = await image.run("/bin/printenv", args=["MY_VAR"], env={"MY_VAR": "test_value"})
    print(f"Result: {result.stdout=}, {result.exit_code=}")
    ```

    See [`ContreeImage.run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImage.run) and [`ContreeSession.run()`](./reference/session#contree_sdk.sdk.objects.session.ContreeSession.run) for command execution details.
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    image = client.images.use("alpine:3.20", strict=True)
    print(f"Pulled {image=}")

    print("\nExample 1: Simple command execution")
    result = image.run("/bin/echo", args=["Hello from command parameter!"]).wait()
    print(f"Result: {result.stdout=}, {result.exit_code=}")

    print("\nExample 2: Command with arguments")
    result = image.run("/bin/ls", args=["-la", "/tmp"]).wait()
    print(f"Result: {result.stdout=}, {result.exit_code=}")

    print("\nExample 3: Command with environment variables")
    result = image.run("/bin/printenv", args=["MY_VAR"], env={"MY_VAR": "test_value"}).wait()
    print(f"Result: {result.stdout=}, {result.exit_code=}")
    ```

    See [`ContreeImageSync.run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImageSync.run) and [`ContreeSessionSync.run()`](./reference/session#contree_sdk.sdk.objects.session.ContreeSessionSync.run) for command execution details.
  </Tab>
</Tabs>

### Command vs Shell Mode

* **Command mode**: Use `command="/bin/ls"` with `args=["-la", "/tmp"]` for direct execution without shell interpretation
* **Shell mode**: Use `shell="ls -la /tmp"` for shell commands with pipes, redirects, and wildcards
* **Environment variables**: Pass `env={"VAR": "value"}` to set environment for command execution

## Working with Files

You can upload and use files in your commands by specifying local file paths or pre-uploaded file objects:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    image = await client.images.use("busybox:latest")
    print(f"Using {image=}")

    print("\nExample 1: Local file upload to image")
    with NamedTemporaryFile(mode="w", suffix=".txt") as test_file:
        test_file.write("some txt file\nsecond line\n\nlast line\n")
        test_file.flush()

        result = await image.run(shell=f"cat /{test_file.name.split('/')[-1]} | grep line", files=[test_file.name])
        print(f"Run with local file: {result.stdout=}, {result.exit_code=}")

    print("\nExample 2: Upload file via contree.files and use in image")
    with NamedTemporaryFile(mode="w", suffix=".sh") as script_file:
        script_file.write("#!/bin/sh\necho 'Hello from uploaded script'\necho 'Working directory:'\npwd\n")
        script_file.flush()

        uploaded_file = await client.files.upload(script_file.name)
        print(f"Uploaded file: {uploaded_file=}")

        result = await image.run(shell="sh /file.sh", files={"file.sh": uploaded_file})
        print(f"Run with uploaded file: {result.stdout=}, {result.stderr=}, {result.exit_code=}")

    print("\nExample 3: Bake files into a new image with apply_files")
    with NamedTemporaryFile(mode="w", suffix=".txt") as f:
        f.write("hello from baked file\n")
        f.flush()
        baked = await image.apply_files({"baked.txt": f.name})
        result = await baked.run(shell="cat /baked.txt")
        print(f"File is present in new image: {result.stdout=}")

    print("\nExample 4: Multiple files working together")
    with (
        NamedTemporaryFile(mode="w", suffix=".txt") as data_file,
        NamedTemporaryFile(mode="w", suffix=".sh") as script_file,
    ):
        data_file.write("apple\nbanana\ncherry\ndate\n")
        data_file.flush()

        script_file.write(
            "#!/bin/bash\necho 'Processing data:'\ncat /data.txt | grep -E '^[ab]'"
            "\necho 'Found items starting with a or b'"
        )
        script_file.flush()

        result = await image.run(
            shell="chmod +x /script.sh && sh /script.sh",
            files={"data.txt": data_file.name, "script.sh": script_file.name},
        )
        print(f"Multiple files result: {result.stdout=}, {result.stderr=}, {result.exit_code=}")
    ```
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    image = client.images.use("busybox:latest")
    print(f"Using {image=}")

    print("\nExample 1: Local file upload to image")
    with NamedTemporaryFile(mode="w", suffix=".txt") as test_file:
        test_file.write("some txt file\nsecond line\n\nlast line\n")
        test_file.flush()

        result = image.run(shell=f"cat /{test_file.name.split('/')[-1]} | grep line", files=[test_file.name]).wait()
        print(f"Run with local file: {result.stdout=}, {result.exit_code=}")

    print("\nExample 2: Upload file via contree.files and use in image")
    with NamedTemporaryFile(mode="w", suffix=".sh") as script_file:
        script_file.write("#!/bin/sh\necho 'Hello from uploaded script'\necho 'Working directory:'\npwd\n")
        script_file.flush()

        uploaded_file = client.files.upload(script_file.name)
        print(f"Uploaded file: {uploaded_file=}")

        result = image.run(shell="sh /file.sh", files={"file.sh": uploaded_file}).wait()
        print(f"Run with uploaded file: {result.stdout=}, {result.stderr=}, {result.exit_code=}")

    print("\nExample 3: Bake files into a new image with apply_files")
    with NamedTemporaryFile(mode="w", suffix=".txt") as f:
        f.write("hello from baked file\n")
        f.flush()
        baked = image.apply_files({"baked.txt": f.name})
        result = baked.run(shell="cat /baked.txt").wait()
        print(f"File is present in new image: {result.stdout=}")

    print("\nExample 4: Multiple files working together")
    with (
        NamedTemporaryFile(mode="w", suffix=".txt") as data_file,
        NamedTemporaryFile(mode="w", suffix=".sh") as script_file,
    ):
        data_file.write("apple\nbanana\ncherry\ndate\n")
        data_file.flush()

        script_file.write(
            "#!/bin/bash\necho 'Processing data:'\ncat /data.txt | grep -E '^[ab]'"
            "\necho 'Found items starting with a or b'"
        )
        script_file.flush()

        result = image.run(
            shell="chmod +x /script.sh && sh /script.sh",
            files={"data.txt": data_file.name, "script.sh": script_file.name},
        ).wait()
        print(f"Multiple files result: {result.stdout=}, {result.stderr=}, {result.exit_code=}")
    ```
  </Tab>
</Tabs>

### File Upload Methods

You can provide files to commands in several ways:

* **Local file paths**: `files=["/path/to/local/file.txt"]` - Upload files directly
* **File mapping**: `files={"dest.txt": "/local/source.txt"}` - Upload with custom names
* **Pre-uploaded files**: `files={"script.sh": uploaded_file_object}` - Use files uploaded via `client.files.upload()`

## Advanced I/O Handling

You can use Python I/O objects for more sophisticated input/output handling:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    image = await client.images.use("busybox:latest")
    print(f"Using {image=}")

    print("\nExample 1: StringIO for stdin and stdout")
    stdin_io = StringIO("apple\nbanana\ncherry\ndate\n")
    stdout_io = StringIO()

    result = await image.run(shell="grep 'a' | sort", stdin=stdin_io, stdout=stdout_io)
    print(f"StringIO result: exit_code={result.exit_code}")
    print(f"Output in StringIO: {stdout_io.getvalue()=}")
    print(f"result.stdout is the StringIO object: {result.stdout is stdout_io}")

    print("\nExample 2: PIPE for stderr capture")
    result = await image.run(shell="echo 'to stdout'; echo 'to stderr' >&2; exit 0", stderr=PIPE)
    print(f"PIPE stderr: {result.stdout=}")
    print(f"Stderr content: {result.stderr.read().decode()=}")
    print(f"Stderr type: {type(result.stderr).__name__}")

    print("\nExample 3: Output to bytes")
    result = await image.run(shell="echo 'Hello bytes world'", stdout=bytes)
    print(f"Bytes output: {result.stdout=}")
    print(f"Output type: {type(result.stdout).__name__}")

    print("\nExample 4: open() file object for input")
    with NamedTemporaryFile(mode="w", suffix=".txt") as temp_file:
        temp_file.write("line1\nline2\nline3\n")
        temp_file.flush()

        with open(temp_file.name) as file_obj:
            result = await image.run(shell="wc -l", stdin=file_obj)
            print(f"File object input: {result.stdout=}, {result.exit_code=}")

    print("\nExample 5: BytesIO for binary data")
    binary_data = BytesIO(b"binary\ndata\nlines\n")

    result = await image.run(shell="wc -l", stdin=binary_data)
    print(f"BytesIO input: {result.stdout=}, {result.exit_code=}")
    ```

    See [`run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImage.run) for I/O parameter details.
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    image = client.images.use("busybox:latest")
    print(f"Using {image=}")

    print("\nExample 1: StringIO for stdin and stdout")
    stdin_io = StringIO("apple\nbanana\ncherry\ndate\n")
    stdout_io = StringIO()

    result = image.run(shell="grep 'a' | sort", stdin=stdin_io, stdout=stdout_io).wait()
    print(f"StringIO result: exit_code={result.exit_code}")
    print(f"Output in StringIO: {stdout_io.getvalue()=}")
    print(f"result.stdout is the StringIO object: {result.stdout is stdout_io}")

    print("\nExample 2: PIPE for stderr capture")
    result = image.run(shell="echo 'to stdout'; echo 'to stderr' >&2; exit 0", stderr=PIPE).wait()
    print(f"PIPE stderr: {result.stdout=}")
    print(f"Stderr content: {result.stderr.read().decode()=}")
    print(f"Stderr type: {type(result.stderr).__name__}")

    print("\nExample 3: Output to bytes")
    result = image.run(shell="echo 'Hello bytes world'", stdout=bytes).wait()
    print(f"Bytes output: {result.stdout=}")
    print(f"Output type: {type(result.stdout).__name__}")

    print("\nExample 4: open() file object for input")
    with NamedTemporaryFile(mode="w", suffix=".txt") as temp_file:
        temp_file.write("line1\nline2\nline3\n")
        temp_file.flush()

        with open(temp_file.name) as file_obj:
            result = image.run(shell="wc -l", stdin=file_obj).wait()
            print(f"File object input: {result.stdout=}, {result.exit_code=}")

    print("\nExample 5: BytesIO for binary data")
    binary_data = BytesIO(b"binary\ndata\nlines\n")

    result = image.run(shell="wc -l", stdin=binary_data).wait()
    print(f"BytesIO input: {result.stdout=}, {result.exit_code=}")
    ```

    See [`run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImageSync.run) for I/O parameter details.
  </Tab>
</Tabs>

### Supported I/O Types

* **StringIO**: For text-based input/output
* **BytesIO**: For binary data handling
* **File objects**: Use `open()` file handles directly
* **PIPE**: Capture stderr/stdout as byte streams
* **bytes type**: Get output as bytes instead of strings

## Subprocess-like Interface (Sync Only)

You can use a subprocess-like interface for more control over process execution:

```python theme={null}
image = client.images.use("busybox:latest")
print(f"Using {image=}")

print("\nExample 1: Basic popen with wait()")
process = image.popen(["/bin/ls", "-la"], cwd="/bin")
process.wait()
print(f"Process completed: returncode={process.returncode}")
print(f"Output: {process.stdout[:100]}...")

print("\nExample 2: Shell command with stdout and stderr")
process = image.popen("echo 'Hello stdout' && echo 'Hello stderr' >&2", shell=True)
process.wait()
print(f"Stdout: {process.stdout=}")
print(f"Stderr: {process.stderr=}")

print("\nExample 3: Using communicate() for input/output")
process = image.popen(["/bin/grep", "apple"])
stdout, stderr = process.communicate(input="apple\nbanana\ncherry\napple pie\n")
print(f"Grep results: {stdout=}")
print(f"Return code: {process.returncode=}")

print("\nExample 4: Environment variables")
process = image.popen(
    "echo $MY_VAR && echo $ANOTHER_VAR", shell=True, env={"MY_VAR": "hello_world", "ANOTHER_VAR": "test_value"}
)
process.wait()
print(f"Environment output: {process.stdout=}")

print("\nExample 5: Error handling")
process = image.popen(["/bin/ls", "/nonexistent"])
process.wait()
print(f"Error case: returncode={process.returncode}")
print(f"Error output: {process.stderr=}")
```

See [`ContreeProcessSync`](./reference/subprocess#contree_sdk.sdk.objects.subprocess.ContreeProcessSync) for the full subprocess API.

### Popen Features

* **Process control**: Use `wait()`, `communicate()`, and check `returncode`
* **Environment variables**: Pass custom `env` dictionary
* **Working directory**: Set `cwd` parameter
* **Shell commands**: Enable with `shell=True`
* **Error handling**: Check `returncode` and `stderr` for failures

## Command Parameters

### Core Parameters

* **`shell`**: Execute as shell command (e.g., `"ls -la | grep txt"`)
* **`command`**: Executable path (e.g., `"/bin/ls"`)
* **`args`**: Command arguments as tuple (e.g., `("-la", "/tmp")`)
* **`stdin`**: Input data (string, bytes, or I/O object)
* **`env`**: Environment variables as dictionary

### I/O Parameters

* **`stdout`**: Redirect stdout (StringIO, BytesIO, file path, or `bytes`)
* **`stderr`**: Redirect stderr (StringIO, BytesIO, PIPE, or `bytes`)
* **`files`**: Upload files (list of paths or dict mapping)

### Execution Parameters

* **`cwd`**: Working directory inside container
* **`disposable`**: Whether to persist changes (default: True for runs, False for sessions)
* **`tag`**: Tag to assign to the resulting image after execution (e.g. `tag="myapp:v2"`)

## Result Objects

Command execution returns result objects with:

* **`stdout`**: Command output as string (or specified type)
* **`stderr`**: Error output as string (or specified type)
* **`exit_code`**: Process exit code (0 = success)
* **`uuid`**: UUID of the resulting image state
