> ## 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.

# Getting Started

This guide will help you get up and running with ConTree SDK. By the end of this guide, you’ll understand how to create clients, work with images, and run your first commands.

## Configuration

The SDK resolves credentials in the following priority order:

1. **Explicit values** passed to `IAMAuth` / `JWTAuth` constructors via `ContreeConfig`.
2. **Environment variables**:

   * `NEBIUS_API_KEY` — IAM token
   * `NEBIUS_PROJECT_ID` — ConTree project ID
   * `CONTREE_BASE_URL` — ConTree instance URL (for `JWTAuth`)
3. **`auth.ini`** — if the `contree` CLI is installed, credentials written by `contree auth` are read automatically from `~/.config/contree/auth.ini`.

```bash theme={null}
export NEBIUS_API_KEY="your_token_here"
export NEBIUS_PROJECT_ID="your_project_id"
export CONTREE_BASE_URL="https://your-instance.of.contree"
```

The active `auth.ini` profile defaults to `default` and can be overridden with `CONTREE_PROFILE`. The config directory respects `$CONTREE_HOME` and `$XDG_CONFIG_HOME`.

Alternatively, you can pass auth directly when creating a client via `ContreeConfig(auth=IAMAuth(...))` or use `JWTAuth` for legacy token-based access.

## Creating a Client

The first step is to create a ConTree client. You can choose between async and sync versions depending on your application needs.

Here’s how to create a client and verify the connection by listing available images:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    # Get client
    client = Contree()

    # Get images (to verify that connection works)
    await client.images()
    ```

    See [`Contree`](./reference/client#contree_sdk.Contree) for all client options.
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    # Get client
    client = ContreeSync()

    # Get images (to verify that connection works)
    client.images()
    ```

    See [`ContreeSync`](./reference/client#contree_sdk.ContreeSync) for all client options.
  </Tab>
</Tabs>

## Working with Images

Images are the foundation of ConTree. The simplest way to reference an image is by tag using `images.use()`, which creates an image object without making an API call:

<Tabs>
  <Tab title="Async">
    ```python theme={null}
    image = await contree.images.use("ubuntu:latest")
    result = await image.run(shell="echo hello")
    ```
  </Tab>

  <Tab title="Sync">
    ```python theme={null}
    image = contree.images.use("ubuntu:latest")
    result = image.run(shell="echo hello").wait()
    ```
  </Tab>
</Tabs>

To resolve a tag or UUID upfront via an API call, use `images.use(strict=True)`. To import from an external registry (or return an existing image if already imported), use `images.oci()`.

See [Working with Images](./images) for a full overview of available methods, examples, and what you can pass as a reference.

## Running Commands

Once you have an image, you can run commands inside it. Each command execution creates a new version of the image with your changes.

### Basic Command Execution

You can run various shell commands and handle their output:

<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 [`run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImage.run) for all command execution 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 [`run()`](./reference/image#contree_sdk.sdk.objects.image.ContreeImageSync.run) for all command execution options.
  </Tab>
</Tabs>

### Understanding the Results

When you run a command, you get back a result object that contains:

* **`stdout`**: Standard output from the command
* **`stderr`**: Standard error from the command
* **`exit_code`**: The exit code (0 for success, non-zero for errors)
* **`uuid`**: The UUID of the new image version created by this command
