Metadata-Version: 2.4
Name: sky-squawk
Version: 0.1.0
Summary: A SkyPilot-backed drop-in replacement for the Docker Python SDK
Author: LJH
License: MIT
Project-URL: Homepage, https://github.com/MotifTechnologies/Squawk
Project-URL: Bug Tracker, https://github.com/MotifTechnologies/Squawk/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: skypilot
Dynamic: license-file

# 🦜 Squawk

**Squawk** is a python library that provides a drop-in mock for the Docker SDK, backed by [SkyPilot](https://github.com/skypilot-org/skypilot). It allows you to orchestrate "containers" (which are translated into SkyPilot clusters) across any cloud provider using the Docker API patterns.

---

## 🚀 Key Features

- **Multi-Cloud Orchestration**: Leverage SkyPilot to run your workloads on AWS, GCP, Azure, Lambda Labs, and more.
- **Docker-Mock API**: Use `client.containers.run` just like you would with the official Docker SDK.
- **Execution Timeouts**: Native support for "real" execution timeouts that automatically tear down clusters to save costs.
- **Volume Mapping**: Seamlessly mount local files to remote clusters using SkyPilot's high-performance file mounts.

---

## 🛠 Installation

### 1. Install uv
Squawk targets **Linux** environments. Check if you have `uv` installed:

```bash
# Check for uv
command -v uv || (echo "uv not found, installing..." && curl -LsSf https://astral.sh/uv/install.sh | sh)
```

### 2. Install sky-squawk
You can install the latest stable version from PyPI:

```bash
pip install sky-squawk
```

### 3. Setup Squawk & skypilot in the pod (for development)
```bash
# (optional)Run the code below if you use sky inside pod(as a master pod for controlling benchmarks)
rsync ~/.sky/config.yaml target_pod:/root/.sky/config.yaml
ssh target_pod

# Clone and enter the project
cd squawk

# Initialize and install dependencies automatically
uv sync

# Activate the environment
source .venv/bin/activate
```

---

## 📖 API Reference

### `squawk.mock.docker.from_env()`
Returns an initialized `DockerClient` instance.

---

### `client.containers`

The primary manager for your SkyPilot "containers".

#### `run(image, command=None, **kwargs)`
Launches a SkyPilot cluster and executes a task.

| Argument | Type | Description |
| :--- | :--- | :--- |
| `image` | `str` | The container image name (e.g., `"ubuntu:20.04"`). *Note: SkyPilot implementation might vary based on cloud providers.* |
| `command` | `str` | The command to execute on the cluster. |
| `detach` | `bool` | If `True`, returns the `Container` object immediately after launch. Default: `False`. |
| `name` | `str` | (Optional) Name for the cluster. If omitted, Squawk generates a name with the `sky-gemini-` prefix. |
| `timeout` | `int` | (Optional) Maximum execution time in seconds. After this duration, the command is terminated and the cluster is torn down. |
| `volumes` | `dict` | (Optional) Mapping of `{remote_path: local_path}` to synchronize files between your machine and the cluster. |
| `infra` | `str` | (Optional) The target infrastructure (e.g., `"kubernetes"`, `"aws"`, `"gcp"`). **Default: `"kubernetes"`**. |

**Example:**
```python
container = client.containers.run(
    image="ubuntu:20.04",
    command="python train.py",
    timeout=3600, # 1 hour limit
    volumes={"/data": "./local_data"},
    infra="aws", # Explicitly target AWS
    detach=True
)
```

#### `list(all=False)`
Lists active SkyPilot clusters. Returns a list of `Container` objects.

#### `get(id_or_name)`
Retrieves a specific `Container` object by its cluster name. Throws an exception if not found.

---

### `Container` Object

Represents a SkyPilot cluster.

#### `name` / `id`
The unique identifier (cluster name) of the container.

#### `status`
The current state of the cluster (e.g., `UP`, `STOPPED`, `INIT`).

#### `logs(stream=False)`
Retrieves execution logs. 
- If `stream=True`, it follows the logs in real-time.
- If `stream=False`, it provides the path to the local log cache.

#### `wait()`
Blocks until the container's task is completed. Returns a dictionary containing the exit status (e.g., `{"StatusCode": 0}`).

#### `stop()`
Stops the cluster (billing for compute stops, but resources are preserved).

#### `remove(force=False)`
Tears down the cluster and deletes all associated cloud resources. Equivalent to `sky down`.

---

## 💡 Pro Tips

### Getting Command Results
Just like the Docker SDK, `client.containers.run()` behaves differently based on the `detach` flag:

1. **Synchronous (Default)**: Returns the logs as a string after the command finishes.
   ```python
   logs = client.containers.run("ubuntu", "echo hello")
   print(logs.decode()) # b"Task completed. Check logs for output."
   ```

2. **Asynchronous**: Returns a `Container` object immediately.
   ```python
   container = client.containers.run("ubuntu", "echo hello", detach=True)
   container.wait() # Wait for completion
   ```

---

## 🧪 Running Tests

We use `pytest` with mocks to ensure the API mapping is correct without incurring cloud costs during units tests.

```bash
pytest tests/test_containers.py
```

---

## 📜 Design Philosophy

Squawk aims to bridge the gap between docker-based local development and cloud-scale orchestration. By mimicking the Docker SDK, it allows developers to write code that is infrastructure-agnostic. 

- **Prefixing**: All automatically named clusters start with `squawk-` followed by a UUID to distinguish them from other SkyPilot resources (e.g., `squawk-550e8400-e29b-41d4-a716-446655440000`).
- **Minimal Code Editing**: makes it easy to migrate existing docker-based code to skypilot orchestration.
- **Silent Execution**: Internal SkyPilot SDK messages are suppressed to match the clean output behavior of the Docker SDK.
- **Safe Execution**: squawk helps you to run unexpected llm-generated code safely by automatically launching/tearing down the new cluster after completion.
