# Get started

This guide walks through the main features of the AIR SDK.

## Create a client

To run the AIR SDK you firstly need to instantiate a client, providing the AIR API key and the AIR server URL.

```python
import air

client = air.AIR(api_key="air_k1_...", base_url="http://localhost:8000")
```

Optionally set `local_dir` to control where project files are synced locally
(defaults to `~/ai-scientist` or the `AIR_LOCAL_DIR` environment variable):

```python
client = air.AIR(api_key="air_k1_...", base_url="http://localhost:8000", local_dir="~/my-research")
```

If `AIR_API_KEY` and `AIR_BASE_URL` are set as environment variables you can
omit both arguments:

```python
client = air.AIR()
```

The client can also be used as a context manager so the underlying HTTP
connection is closed automatically:

```python
with air.AIR() as client:
    ...
```

## Standalone tools

These endpoints do not require a project.

### Standalone paper review

Review a paper PDF with the Skepthical engine without requiring a project:

```python
result = client.review(
    "/server/path/to/paper.pdf",
    thoroughness="High",          # "Standard" (default) or "High"
    figures_review=True,
    verify_statements=True,
    review_maths=False,
    review_numerics=False,
    emails=["you@example.com"],   # optional email recipients
)
```

### One-shot execution

`one_shot` runs a free-form task where the backend drives an AI agent loop
and all generated code executes **locally** on your machine inside an isolated
virtual environment.

```python
result = client.one_shot(
    task="Plot the CMB power spectrum using CAMB",
    model="gpt-4.1-2025-04-14",
    max_rounds=25,
)

print(result.output)
print("Files created:", [f.path for f in result.files_created])
print("Work directory:", result.work_dir)
```

By default, output is streamed to stdout. Pass a custom callback or `None` to
change that behaviour:

```python
# Silent -- no streaming output
result = client.one_shot(task="...", on_output=None)

# Custom callback
result = client.one_shot(task="...", on_output=lambda s: my_logger.info(s))
```

The local work directory defaults to `~/ai-scientist/<task_id>`. Override it
with `work_dir` or the `AIR_WORK_DIR` environment variable.

### Deep research

`deep_research` runs a multi-step research task with a dedicated planner,
researcher, and engineer agent. Generated code also executes **locally**:

```python
result = client.deep_research(
    "Reproduce Figure 3 from arxiv:2301.12345 and extend it to z=2",
    max_plan_steps=5,
    work_dir="~/my-tasks",
)

print(result.output)
print("Files created:", [f.path for f in result.files_created])
```

### ArXiv download

Extract arXiv URLs from a piece of text and download the papers:

```python
result = client.arxiv("See https://arxiv.org/abs/2301.12345 for details.")
print(result)
```

### Text enhancement

Enhance text with contextual information from arXiv papers:

```python
enhanced = client.enhance(
    "My research with https://arxiv.org/abs/2301.12345",
    max_workers=2,
    max_depth=10,
)
print(enhanced)
```

### OCR

Process a server-side PDF with OCR:

```python
ocr_result = client.ocr("/path/on/server/paper.pdf")
print(ocr_result)
```

### Keyword extraction

Provide keywords from an input text:

```python
keywords = client.keywords("dark matter and gravitational lensing", n=5, kw_type="aas")
print(keywords)
```

`kw_type` selects the keyword vocabulary -- `"unesco"` (default) or `"aas"` (American Astronomical Society).

## Research projects

Projects let you run the full AIR research pipeline: **idea &rarr; literature
&rarr; methods &rarr; results &rarr; paper &rarr; review**.

### Create a project

```python
project = client.create_project(
    "my-research",
    data_description="We study the effects of dark energy on large-scale structure.",
)
```

Pass `local_dir` to override the sync directory for this project, and
`auto_pull=False` to disable automatic local file sync after each step:

```python
project = client.create_project(
    "my-research",
    data_description="We study...",
    local_dir="~/my-research",
    auto_pull=False,
)
```

### Run the pipeline

Each step blocks until the backend finishes (with a configurable timeout):

```python
idea = project.idea()                 # generate a research idea
lit  = project.literature()           # run literature search
meth = project.methods()              # develop methods
res  = project.results()              # run analysis with local code execution
tex  = project.paper(journal="AAS")   # write the paper
rev  = project.review()               # get a referee report
```

Every method returns the content of its main output file as a string.

The `results()` step runs code **locally** on your machine (same as `one_shot`)
and automatically uploads generated plots to the server so `paper()` can embed
them.  See the `results()` docstring for advanced options (`max_attempts`,
`max_steps`, `venv_path`, etc.).

When `auto_pull=True` (the default), key input and output files are
automatically downloaded to `local_dir` after each pipeline step.

### Sync files locally

```python
# Download all project files to local_dir
paths = project.pull_files()

# Download only key files for iteration 0 (faster)
paths = project.pull_files(key_only=True, iteration=0)

# Upload a local file or directory to the project
project.push_files("local/data.csv")
project.push_files("local/data/", remote_path="Iteration0/input_files/data/")
```

### Access project files

```python
# List all files in the project
files = project.list_files()
for f in files:
    print(f["relative_path"], f["size"])

# Read a specific file
idea_text = project.get_file("Iteration0/input_files/idea.md")

# Write a file into the project
project.write_file("notes.md", "# My notes\n...")
```

### Manage projects

```python
# List all projects
print(client.list_projects())

# Re-open an existing project
project = client.get_project("my-research")

# Delete a project
client.delete_project("my-research")
# or from the project object:
project.delete()
```
