Metadata-Version: 2.4
Name: infilake
Version: 0.1.0
Summary: Agent-friendly CLI harness for infilake-dw data warehouse platform
Author: infilake-dw team
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: click>=8.1.0
Requires-Dist: requests>=2.31.0
Requires-Dist: prompt-toolkit>=3.0.0
Requires-Dist: supabase>=2.28.0
Requires-Dist: sqlglot>=28.0.0
Requires-Dist: python-dateutil>=2.9.0
Provides-Extra: mcp
Requires-Dist: mcp>=1.27.0; extra == "mcp"
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# infilake

Agent-friendly command line interface for the `infilake-dw` data warehouse
platform. The package installs two equivalent commands:

- `infilake`
- `cli-anything-infilake`

The CLI talks to the FastAPI backend, stores local configuration under the
current user's home directory, and supports both interactive terminal use and
machine-readable JSON output for agents and scripts.

## Requirements

- Python 3.11+
- A running `infilake-dw` backend
- Supabase URL and anon key for email/password login, or a warehouse API key

The default API endpoint is:

```bash
http://localhost:8000/api/v1
```

Use `--api-url` for a single command or `infilake config set --api-url ...` to
persist a different backend URL.

## Installation

Install the published package from PyPI:

```bash
python -m pip install 'infilake[mcp]'
```

Or install a development checkout from the repository root:

```bash
python -m pip install -e './cli[mcp]'
```

After installation:

```bash
infilake --help
cli-anything-infilake --help
```

For development without installing the package:

```bash
PYTHONPATH=cli python -m cli_anything.infilake --help
```

## Quick Start

```bash
# Configure backend and Supabase auth
infilake config set \
  --api-url http://localhost:8000/api/v1 \
  --supabase-url "$SUPABASE_URL" \
  --supabase-anon-key "$SUPABASE_ANON_KEY"

# Log in with Supabase email/password
infilake auth login

# List warehouses and set a default target
infilake wh list
infilake wh use <name-or-uuid>

# Run SQL against the default warehouse
infilake q execute "SELECT 1 AS hello"

# Start the interactive REPL
infilake
```

API-key mode is also supported:

```bash
infilake auth use-key <warehouse-api-key> --name automation
infilake auth whoami
```

## Local State

The CLI writes state to `~/.cli-anything-infilake/`:

- `config.json`: non-secret configuration such as API URL, Supabase public
  anon key, default warehouse, pager, and TLS verification settings.
- `session.json`: JWT session or API key credentials. The file is written with
  user-only permissions where supported by the OS.

Useful commands:

```bash
infilake config show
infilake config set --api-url http://localhost:8000/api/v1
infilake config reset
infilake auth whoami
infilake auth logout
```

## Global Options

Global options must appear before the command group:

```bash
infilake [OPTIONS] COMMAND [ARGS]...
```

| Option | Description |
| --- | --- |
| `--json` | Print machine-readable JSON. |
| `--api-url URL` | Override the configured API URL for this invocation. |
| `-w, --warehouse NAME_OR_UUID` | Override the configured default warehouse. |
| `-v, --verbose` | Print HTTP method and URL to stderr. |
| `--no-color` | Disable colored output. |
| `--version` | Print CLI version. |

Examples:

```bash
infilake --json wh list
infilake -w analytics q execute "SELECT count(*) FROM public.events"
infilake --api-url https://api.example.com/api/v1 wh list
```

## Command Overview

| Group | Purpose |
| --- | --- |
| `auth` | Log in, log out, refresh JWTs, inspect identity, or switch to API-key mode. |
| `config` | Show, update, or reset local CLI configuration. |
| `wh` | Create, list, inspect, update, pause, resume, restore, delete, and test warehouses. |
| `q` | Execute SQL, dry-run SQL, cancel queries, and manage saved queries. |
| `tbl` | Manage schemas, tables, columns, snapshots, exports, imports, and table maintenance. |
| `udf` | Manage user-defined functions, versions, tests, logs, completions, and module whitelist settings. |
| `key` | Create, list, toggle, and delete warehouse-scoped API keys. |
| `engine` | Deploy, build, start, stop, remove, inspect, and test the query engine. |
| `pipe` | Import SQL pipelines, inspect DAGs, run pipelines or steps, manage triggers, and inspect runs. |
| `agent` | Install, list, diagnose, upgrade, and uninstall Claude Code, Codex CLI, or Pi integrations. |

Every group and subcommand has built-in help:

```bash
infilake wh --help
infilake q execute --help
infilake tbl create --help
infilake pipe trigger create --help
infilake agent install --help
```

## Agent Skills and MCP Integrations

The CLI packages four Infilake workflows and can install them together with a
secret-safe `infilake-mcp` registration. Preview changes before installation:

```bash
infilake agent install . --integration claude --dry-run
infilake agent install . --integration codex --integration-options='--skills' --dry-run
infilake agent install . --integration pi --dry-run
```

Install, inspect, diagnose, and remove an integration:

```bash
infilake agent install . --integration codex
infilake agent list .
infilake agent doctor . --integration codex
infilake agent uninstall . --integration codex --dry-run
infilake agent uninstall . --integration codex --yes
```

| Agent | Project workflows | Project MCP configuration | Additional prerequisite |
| --- | --- | --- | --- |
| Claude Code | `.claude/skills/<name>/SKILL.md` | `.mcp.json` | `claude` executable |
| Codex CLI | `.agents/skills/<name>/SKILL.md` | `.codex/config.toml` | `codex` executable |
| Pi Coding Agent | `.pi/prompts/<name>.md` | `.mcp.json`; optional `.pi/mcp.json` direct-tool override | `pi install npm:pi-mcp-adapter` |

Use `--components skills` or `--components mcp` for a partial installation,
and `--scope user` for user-level discovery paths. Pi uses the adapter's proxy
tool by default. A small allowlist can be exposed directly with, for example,
`--integration-options='--direct-tools=table_list,query_execute'`.

Credentials are never copied into generated configuration or the installation
manifest. Export them in the launching shell instead:

```bash
export INFILAKE_API_URL='http://localhost:8000/api/v1'
read -rsp 'Infilake API Key: ' INFILAKE_API_KEY
export INFILAKE_API_KEY
```

`infilake-mcp` resolves explicit flags first, then `INFILAKE_API_URL` and
`INFILAKE_API_KEY`, then the non-sensitive default API URL. Stdio startup fails
closed when no API key binding is available. Do not place a key value in
`--integration-options`, MCP JSON/TOML, shell history, or an installation
manifest.

## Warehouse Workflow

Create a warehouse:

```bash
infilake wh create \
  --name analytics \
  --s3-bucket infilake-data \
  --s3-access-key "$S3_ACCESS_KEY_ID" \
  --s3-secret "$S3_SECRET_ACCESS_KEY" \
  --s3-endpoint http://localhost:9000 \
  --s3-region us-east-1 \
  --s3-provider-type custom
```

Common warehouse commands:

```bash
infilake wh list
infilake wh get analytics
infilake wh use analytics
infilake wh test-connection analytics
infilake wh storage-get analytics
infilake wh quota
infilake wh pause analytics
infilake wh resume analytics
infilake wh delete-summary analytics
```

The default warehouse is resolved by this precedence:

1. Command-specific warehouse argument, when a command accepts one
2. Global `-w/--warehouse`
3. Saved default from `infilake wh use <name-or-uuid>`

## Query Workflow

Run inline SQL:

```bash
infilake q execute "SELECT * FROM public.events LIMIT 10"
```

Run SQL from a file:

```bash
infilake q execute --file query.sql
```

Pipe SQL through stdin:

```bash
printf 'SELECT 1 AS ok' | infilake q execute
```

Validate without executing:

```bash
infilake q dry-run --file query.sql
infilake q execute --dry-run "SELECT * FROM public.events"
```

Use saved queries:

```bash
infilake q saved create --name daily-count --file daily_count.sql --category ops
infilake q saved list --category ops
infilake q saved run <query-id> --limit 100
infilake q saved update <query-id> --favorite
```

## Table Workflow

Schemas:

```bash
infilake tbl schema list
infilake tbl schema create analytics
```

Create a table with column flags:

```bash
infilake tbl create analytics.events \
  --column id:uuid:pk \
  --column occurred_at:timestamp \
  --column payload:json \
  --comment "Application events"
```

Create a table from JSON:

```bash
infilake tbl create analytics.events --file table.json
```

Inspect and move data:

```bash
infilake tbl list
infilake tbl definition analytics.events
infilake tbl ddl analytics.events
infilake tbl data analytics.events --page 1 --page-size 50
infilake tbl export analytics.events --output events.csv --max-rows 1000
infilake tbl insert analytics.events --file row.json
```

Change table metadata and columns:

```bash
infilake tbl rename analytics.events --new-name app_events
infilake tbl comment analytics.app_events --comment "Application event stream"
infilake tbl column add analytics.app_events --name source --type text --nullable
infilake tbl column comment analytics.app_events source --comment "Event source"
infilake tbl column alter-type analytics.app_events source --type varchar
infilake tbl column drop analytics.app_events source
```

Snapshots and maintenance:

```bash
infilake tbl snapshot list analytics.app_events
infilake tbl snapshot diff analytics.app_events 42
infilake tbl maintenance expire-snapshots --older-than-days 30
infilake tbl maintenance cleanup-files --older-than-days 30
infilake tbl maintenance checkpoint
```

Maintenance commands default to dry-run where supported. Use `--execute` when
you intend to apply the operation.

## UDF Workflow

Create and manage UDFs:

```bash
infilake udf create \
  --name normalize_email \
  --file udf_normalize_email.py \
  --return-type text \
  --param email:text \
  --description "Normalize email addresses"

infilake udf list --status draft
infilake udf get <udf-id>
infilake udf enable <udf-id>
infilake udf versions <udf-id>
infilake udf logs <udf-id>
```

Test UDFs:

```bash
infilake udf test <udf-id> --mode manual --arg '"User@Example.COM"'
infilake udf test <udf-id> \
  --mode table_sample \
  --table analytics.users \
  --mapping email=email \
  --sample-rows 10
```

Manage the per-warehouse disabled module list:

```bash
infilake udf whitelist get
infilake udf whitelist set --disabled-modules os,subprocess
infilake udf whitelist set --disabled-modules ""
```

## API Keys

Warehouse-scoped API keys can be created by an authenticated user and then used
for non-interactive automation.

```bash
infilake key create \
  --name ci-runner \
  --role viewer \
  --allowed-schema analytics \
  --expires-at 2026-12-31T23:59:59Z

infilake key list
infilake key toggle <key-id> --inactive
infilake key delete <key-id>
```

The plaintext key is returned only once by `key create`. Save it immediately,
then use it with:

```bash
infilake auth use-key <warehouse-api-key> --name ci-runner
```

## Engine Workflow

Engine commands operate on the resolved warehouse:

```bash
infilake engine deploy
infilake engine build
infilake engine start
infilake engine status
infilake engine test-connection
infilake engine stop
infilake engine remove --yes
```

Use `-w/--warehouse` to target a specific warehouse for one command:

```bash
infilake -w analytics engine status
```

## Pipeline Workflow

Import and inspect a pipeline:

```bash
infilake pipe import-preview --file pipeline.yaml
infilake pipe import --file pipeline.yaml --project-id <project-id>
infilake pipe list
infilake pipe get <pipeline-id>
infilake pipe dag <pipeline-id>
```

Run a pipeline or one entry-point step:

```bash
infilake pipe run <pipeline-id> --param run_date=2026-05-23
infilake pipe step-trigger <pipeline-id> extract_events --param run_date=2026-05-23
```

Manage triggers and runs:

```bash
infilake pipe trigger create <pipeline-id> \
  --type cron \
  --scope pipeline \
  --cron "0 * * * *" \
  --timezone UTC

infilake pipe trigger list <pipeline-id>
infilake pipe runs <pipeline-id> --status RUNNING
infilake pipe run-get <run-id>
infilake pipe run-dag <run-id>
infilake pipe run-cancel <run-id>
```

## REPL

Run `infilake` with no subcommand to open the interactive REPL. The REPL reuses
the same command registry, so commands are entered without the leading
`infilake`:

```text
help
help q execute
? tbl create
wh list
q execute "SELECT 1"
tbl list
exit
```

## Output and Exit Behavior

- Human-friendly output is used by default.
- `--json` prints structured JSON for successful output and formatted errors.
- Destructive commands prompt for confirmation unless `--yes` is passed or
  JSON mode suppresses interactive prompts.
- JWT sessions are refreshed automatically when close to expiry.
- API-key mode sends `X-Api-Key`; JWT mode sends `Authorization: Bearer ...`.

## Project Structure

```text
cli/
|-- setup.py
|-- README.md
`-- cli_anything/
    `-- infilake/
        |-- __main__.py
        |-- infilake_cli.py
        |-- commands/
        |   |-- agent.py
        |   |-- _ctx.py
        |   |-- engine.py
        |   |-- pipe.py
        |   `-- tbl.py
        |-- core/
        |   |-- api_keys.py
        |   |-- auth.py
        |   |-- client.py
        |   |-- config.py
        |   |-- engine.py
        |   |-- pipelines.py
        |   |-- queries.py
        |   |-- session.py
        |   |-- tables.py
        |   |-- udfs.py
        |   `-- warehouse.py
        |-- agent/
        |-- agent_assets/
        |-- tests/
        `-- utils/
```

## Development

Run CLI tests from the `cli` directory:

```bash
cd cli
python -m pytest tests/agent cli_anything/infilake/tests
```

Run a command from source:

```bash
PYTHONPATH=cli python -m cli_anything.infilake --help
```

The broader repository test commands are documented in the root `README.md` and
`AGENTS.md`.

## Publishing to a Python Package Registry

The distribution name is `infilake`. Publishing it makes the following install
command available from the selected registry:

```bash
uv tool install 'infilake[mcp]'
```

Changing `setup.py` or building the package locally does not publish it. Until
at least one release has been uploaded to the configured registry, `uv` reports
that there are no versions of `infilake[mcp]`.

### 1. Prepare the release

Choose a new PEP 440 version and update all three version declarations:

- `cli/setup.py`: `version`
- `cli/cli_anything/infilake/__init__.py`: `VERSION`
- `cli/cli_anything/infilake/agent/assets.py`: `ASSET_VERSION`

The examples below use `0.1.0`; replace it with the release being published.
PyPI and TestPyPI do not allow an existing distribution filename or release
version to be overwritten, so every retry after a successful upload requires a
new version.

Run the CLI tests from the repository root:

```bash
cd cli
python -m pytest tests/agent cli_anything/infilake/tests
cd ..
```

### 2. Build and validate the artifacts

Install the release tooling and build both a source distribution and wheel into
a version-specific directory. A version-specific directory prevents an older
artifact from being included accidentally by a wildcard upload.

```bash
python -m pip install --upgrade build twine
mkdir -p cli/dist/0.1.0
python -m build cli --outdir cli/dist/0.1.0
python -m twine check cli/dist/0.1.0/*
```

The build must produce:

```text
cli/dist/0.1.0/infilake-0.1.0.tar.gz
cli/dist/0.1.0/infilake-0.1.0-py3-none-any.whl
```

Inspect the wheel before publishing and confirm that the `infilake-*.dist-info`
metadata, console entry points, and `agent_assets/skills/` files are present:

```bash
python -m zipfile -l cli/dist/0.1.0/infilake-0.1.0-py3-none-any.whl
```

Test the package directly from the checkout before relying on a registry:

```bash
uv tool install --force './cli[mcp]'
infilake --version
infilake --help
infilake-mcp --help
```

### 3. Test with TestPyPI

Create a TestPyPI account and API token, then upload the validated artifacts:

```bash
python -m twine upload --repository testpypi cli/dist/0.1.0/*
```

When prompted, use `__token__` as the username and the TestPyPI API token as
the password. Do not commit tokens to this repository or place them directly in
shell commands. TestPyPI is a separate registry and requires a separate account
and token from production PyPI.

Confirm that TestPyPI serves the exact release. `--no-deps` avoids trying to
resolve all runtime dependencies from the intentionally incomplete TestPyPI
index:

```bash
python -m pip download \
  --no-deps \
  --index-url https://test.pypi.org/simple/ \
  'infilake==0.1.0'
```

### 4. Publish to PyPI

After the tests and TestPyPI verification pass, upload the same artifacts to
production PyPI:

```bash
python -m twine upload cli/dist/0.1.0/*
```

When prompted, use `__token__` as the username and the production PyPI API
token as the password. For automated releases, prefer PyPI Trusted Publishing
with short-lived OpenID Connect credentials instead of storing a long-lived API
token in CI.

Verify the published release with a clean `uv` tool environment:

```bash
uv tool install --refresh-package infilake 'infilake[mcp]==0.1.0'
infilake --version
infilake-mcp --help
```

If `uv` reports `there are no versions of infilake[mcp]`, check that the release
exists at `https://pypi.org/project/infilake/`, that the requested version was
uploaded, and that `uv` is using the expected registry. Immediately after an
upload, use `--refresh-package infilake` to bypass stale index metadata.

### Private registry

Upload to a private registry by supplying its upload endpoint:

```bash
python -m twine upload \
  --repository-url https://registry.example.com/python/ \
  cli/dist/0.1.0/*
```

Install from the corresponding PEP 503-compatible `simple` index:

```bash
uv tool install \
  --default-index https://registry.example.com/python/simple/ \
  'infilake[mcp]==0.1.0'
```
