{"id":50996728,"url":"https://github.com/datalpia/laketower","last_synced_at":"2026-06-20T10:31:38.256Z","repository":{"id":277760383,"uuid":"927391938","full_name":"datalpia/laketower","owner":"datalpia","description":"Oversee your lakehouse","archived":false,"fork":false,"pushed_at":"2026-06-13T17:10:16.000Z","size":13185,"stargazers_count":12,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-13T17:27:41.814Z","etag":null,"topics":["apache-iceberg","arrow","data","deltalake","duckdb","lakehouse","sql"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datalpia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-04T21:56:23.000Z","updated_at":"2026-06-05T21:42:14.000Z","dependencies_parsed_at":"2026-01-14T03:07:00.066Z","dependency_job_id":null,"html_url":"https://github.com/datalpia/laketower","commit_stats":null,"previous_names":["datalpia/laketower"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/datalpia/laketower","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datalpia%2Flaketower","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datalpia%2Flaketower/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datalpia%2Flaketower/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datalpia%2Flaketower/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datalpia","download_url":"https://codeload.github.com/datalpia/laketower/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datalpia%2Flaketower/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34566920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache-iceberg","arrow","data","deltalake","duckdb","lakehouse","sql"],"created_at":"2026-06-20T10:31:35.165Z","updated_at":"2026-06-20T10:31:38.247Z","avatar_url":"https://github.com/datalpia.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🗼 Laketower\n\n\u003e Oversee your lakehouse\n\n[![PyPI](https://img.shields.io/pypi/v/laketower.svg)](https://pypi.org/project/laketower/)\n[![Python Versions](https://img.shields.io/pypi/pyversions/laketower?logo=python\u0026logoColor=white)](https://pypi.org/project/laketower/)\n[![CI/CD](https://github.com/datalpia/laketower/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/datalpia/laketower/actions/workflows/ci-cd.yml)\n[![License](https://img.shields.io/github/license/datalpia/laketower)](https://github.com/datalpia/laketower/blob/main/LICENSE)\n\nUtility application to explore and manage tables in your data lakehouse, especially tailored for data pipelines local development.\n\n## Features\n\n- Delta Lake table format support\n- Remote tables support (S3, ADLS)\n- Inspect table metadata\n- Inspect table schema\n- Inspect table history\n- Get table statistics\n- Import data into a table from CSV files\n- View table content with a simple query builder\n- Query all registered tables with DuckDB SQL dialect\n- Execute saved queries\n- Export query results to CSV files\n- Static and versionable YAML configuration\n- Web application\n- CLI application\n\n## Installation\n\nUsing `pip` (or any other Python package manager):\n\n```bash\npip install laketower\n```\n\nUsing `uvx`:\n\n```bash\nuvx laketower\n```\n\n## Usage\n\n### Configuration\n\nLaketower configuration is based on a static YAML configuration file allowing to:\n\n- List all tables to be registered\n\nFormat:\n\n```yaml\nsettings:\n  max_query_rows: 1000\n  web:\n    hide_tables: false\n\nstorage_credentials:\n  \u003ccredential_name\u003e:\n    s3:               # mutually exclusive with adls\n      access_key_id: \u003caccess-key-id\u003e\n      secret_access_key: \u003csecret-access-key\u003e\n      region: \u003cregion\u003e\n      endpoint_url: \u003cendpoint-url\u003e\n      allow_http: false\n    adls:             # mutually exclusive with s3\n      account_name: \u003caccount-name\u003e\n      access_key: \u003caccess-key\u003e\n      sas_key: \u003csas-key\u003e\n      tenant_id: \u003ctenant-id\u003e\n      client_id: \u003cclient-id\u003e\n      client_secret: \u003cclient-secret\u003e\n      msi_endpoint: \u003cmsi-endpoint\u003e\n      use_azure_cli: false\n\ntables:\n  - name: \u003ctable_name\u003e\n    uri: \u003clocal or remote path to table\u003e\n    format: {delta}\n    storage_credential: \u003ccredential_name\u003e   # optional, references storage_credentials\n\nqueries:\n  - name: \u003cquery_name\u003e\n    title: \u003cQuery name\u003e\n    description: \u003cQuery description\u003e\n    totals_row: true\n    parameters:\n      \u003cparam_name_1\u003e:\n        default: \u003cdefault_value\u003e\n    sql: \u003csql expression\u003e\n```\n\nCurrent limitations:\n\n- `tables.uri`:\n    - Local paths are supported (`./path/to/table`, `/abs/path/to/table`, `file:///abs/path/to/table`)\n    - Remote paths to S3 (`s3://\u003cbucket\u003e/\u003cpath\u003e`) and ADLS (`abfss://\u003ccontainer\u003e/\u003cpath\u003e`)\n- `tables.format`: only `delta` is allowed\n\nExample from the provided demo:\n\n```yaml\ntables:\n  - name: sample_table\n    uri: demo/sample_table\n    format: delta\n  - name: weather\n    uri: demo/weather\n    format: delta\n\nqueries:\n  - name: all_data\n    title: All data\n    sql: |\n      select\n        sample_table.*,\n        weather.*\n      from\n        sample_table,\n        weather\n      limit 10\n  - name: daily_avg_temperature\n    title: Daily average temperature\n    sql: |\n      select\n        date_trunc('day', time) as day,\n        round(avg(temperature_2m)) as avg_temperature\n      from\n        weather\n      group by\n        day\n      order by\n        day asc\n```\n\nSupport for environment variables substitution is also supported within the YAML\nconfiguration using a object containing a single key `env` with the name of the\nenvironment variable to be injected. The value of the variable can contain JSON\nand will be decoded in a best effort manner (default to string value). For instance:\n\n```yaml\n# export TABLE_URI=path/to/table\n\ntables:\n  - name: sample_table\n    uri:\n      env: TABLE_URI\n    format: delta\n```\n\nFor string values that only need partial substitution, use the `${VAR_NAME}`\ninline syntax instead. Multiple variables in a single value are supported:\n\n```yaml\n# export BUCKET=my-bucket\n# export PREFIX=my-prefix\n\ntables:\n  - name: sample_table\n    uri: s3://${BUCKET}/${PREFIX}/sample_table\n    format: delta\n```\n\nThe two syntaxes are independent: `{env: VAR}` replaces the entire value (any\ntype), while `${VAR}` interpolates within a string.\n\n#### Config Includes\n\nLarge or multi-environment setups can split the configuration across multiple\nYAML files using the `include` directive. Included files are deep-merged before\nthe main file, so the main file always wins on conflict.\n\n```yaml\n# queries.yml  (shared across environments)\nqueries:\n  - name: all_data\n    title: All data\n    sql: \"select * from my_table\"\n```\n\n```yaml\n# laketower.production.yml\ninclude:\n  - queries.yml\n\nstorage_credentials:\n  s3_creds:\n    s3:\n      access_key_id: ${AWS_ACCESS_KEY_ID}\n      secret_access_key: ${AWS_SECRET_ACCESS_KEY}\n\ntables:\n  - name: my_table\n    uri: s3://production-bucket/tables/my_table\n    format: delta\n    storage_credential: s3_creds\n```\n\nMerge semantics:\n\n- **Lists** (`tables`, `queries`, ...): included file items come first, main file items appended\n- **Dicts** (`settings`, `storage_credentials`, ...): recursively deep-merged, main file values win on conflict\n- **Scalars**: main file wins\n\nRules:\n\n- `include` paths are relative to the directory of the file declaring them\n- Multiple files are merged in order (first listed = lowest priority)\n- Environment variable substitution works in included files\n- Included files themselves do not support `include` (no recursive includes)\n\n#### Storage Credentials\n\nStorage credentials are defined once under the top-level `storage_credentials`\nkey as a named registry, then referenced by name from each table via the\n`storage_credential` field. This avoids repeating the same credentials across\nmultiple tables.\n\n##### Remote S3 Tables\n\nConfiguring S3 tables (AWS, MinIO, Cloudflare R2, Scaleway Object Storage, …):\n\n```yaml\nstorage_credentials:\n  my_s3:\n    s3:\n      access_key_id: access-key-id\n      secret_access_key: secret-access-key\n      region: s3-region\n      endpoint_url: http://s3.domain.com\n      allow_http: false\n\ntables:\n  - name: delta_table_s3\n    uri: s3://\u003cbucket\u003e/path/to/table\n    format: delta\n    storage_credential: my_s3\n```\n\nDepending on your object storage location and configuration, one might have to\nset part or all the available `s3` parameters. The only required ones\nare `access_key_id` and `secret_access_key`.\n\nAs a security best practice, avoid writing secrets directly in static\nconfiguration files. Use environment variable substitution instead:\n\n```yaml\nstorage_credentials:\n  my_s3:\n    s3:\n      access_key_id: access-key-id\n      secret_access_key:\n        env: S3_SECRET_ACCESS_KEY\n      region: s3-region\n      endpoint_url: http://s3.domain.com\n      allow_http: false\n\ntables:\n  - name: delta_table_s3\n    uri: s3://\u003cbucket\u003e/path/to/table\n    format: delta\n    storage_credential: my_s3\n```\n\n##### Remote ADLS Tables\n\nConfiguring Azure ADLS tables:\n\n```yaml\nstorage_credentials:\n  my_adls:\n    adls:\n      account_name: adls-account-name\n      access_key: adls-access-key\n      sas_key: adls-sas-key\n      tenant_id: adls-tenant-id\n      client_id: adls-client-id\n      client_secret: adls-client-secret\n      msi_endpoint: https://msi.azure.com\n      use_azure_cli: false\n\ntables:\n  - name: delta_table_adls\n    uri: abfss://\u003ccontainer\u003e/path/to/table\n    format: delta\n    storage_credential: my_adls\n```\n\nDepending on your object storage location and configuration, one might have to\nset part or all the available `adls` parameters. The only required one\nis `account_name`.\n\nAs a security best practice, avoid writing secrets directly in static\nconfiguration files. Use environment variable substitution instead:\n\n```yaml\nstorage_credentials:\n  my_adls:\n    adls:\n      account_name: adls-account-name\n      access_key:\n        env: ADLS_ACCESS_KEY\n\ntables:\n  - name: delta_table_adls\n    uri: abfss://\u003ccontainer\u003e/path/to/table\n    format: delta\n    storage_credential: my_adls\n```\n\n#### Predefined Query Parameters\n\nPredefined queries allows for specifying named parameters that can then be used\nwith an SQL statement using the `$param_name` syntax.\n\nWhen a query parameter is left blank by the user, it is treated as `NULL` by the\nSQL engine. Use `COALESCE` to provide a fallback so the filter becomes a no-op\ninstead of returning an error or empty results:\n\n```yaml\nqueries:\n  - name: daily_avg_temperature_params\n    title: Daily average temperature with parameters\n    parameters:\n      start_date:\n        default: \"2025-01-01\"\n      end_date:\n        default: \"2025-01-31\"\n    sql: |\n      select\n        date_trunc('day', time) as day,\n        round(avg(temperature_2m)) as avg_temperature\n      from\n        weather\n      where\n        day between coalesce($start_date::timestamp, timestamp '-infinity')\n                and coalesce($end_date::timestamp, timestamp 'infinity')\n      group by\n        day\n      order by\n        day asc\n```\n\nIn this example:\n\n- Blank `start_date` leads to `timestamp '-infinity'` (no lower bound)\n- Blank `end_date` leads to `timestamp 'infinity'` (no upper bound)\n- If both parameters are blank, all rows are returned\n\n### Web Application\n\nThe easiest way to get started is to launch the Laketower web application:\n\n```bash\n$ laketower -c demo/laketower.yml web\n```\n\nBy default, the web application will run on host `127.0.0.1` and port `8000`.\nIf some custom setup is required (especially for cloud deployment), this configuration\ncan be customized at runtime:\n\n```bash\n$ laketower -c demo/laketower.yml web --host 0.0.0.0 --port 5000\n```\n\n#### Screenshots\n\n![Laketower UI - Tables Overview](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_overview.png)\n![Laketower UI - Tables View](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_view.png)\n![Laketower UI - Tables Statistics](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_statistics.png)\n![Laketower UI - Tables History](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_history.png)\n![Laketower UI - Tables Import](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_import.png)\n![Laketower UI - Tables Query](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/tables_query.png)\n![Laketower UI - Queries View](https://raw.githubusercontent.com/datalpia/laketower/refs/heads/main/docs/static/queries_view.png)\n\n### CLI\n\nLaketower provides a CLI interface:\n\n```bash\n$ laketower --help\n\nusage: laketower [-h] [--version] [--config CONFIG] {web,config,tables,queries} ...\n\noptions:\n  -h, --help            show this help message and exit\n  --version             show program's version number and exit\n  --config, -c CONFIG   Path to the Laketower YAML configuration file (default: laketower.yml)\n\ncommands:\n  {web,config,tables,queries}\n    web                 Launch the web application\n    config              Work with configuration\n    tables              Work with tables\n    queries             Work with queries\n```\n\nBy default, a YAML configuration file named `laketower.yml` will be looked for.\nA custom path can be specified with the `-c` / `--config` argument.\n\n#### Show resolved YAML configuration\n\nPrint the fully resolved configuration after include merging, useful for debugging composed setups.\n\n```bash\n$ laketower -c demo/laketower.yml config show\n```\n\nPass `--with-env-vars-substitution` to also resolve environment variable references:\n\n```bash\n$ laketower -c demo/laketower.yml config show --with-env-vars-substitution\n```\n\n#### Validate YAML configuration\n\n```bash\n$ laketower -c demo/laketower.yml config validate\n\n╭────────────────────────╮\n│ Configuration is valid │\n╰────────────────────────╯\nConfig(\n    tables=[\n        ConfigTable(name='sample_table', uri='demo/sample_table', table_format=\u003cTableFormats.delta: 'delta'\u003e),\n        ConfigTable(name='weather', uri='demo/weather', table_format=\u003cTableFormats.delta: 'delta'\u003e)\n    ]\n)\n```\n\n#### List all registered tables\n\n```bash\n$ laketower -c demo/laketower.yml tables list\n\ntables\n├── sample_table\n│   ├── format: delta\n│   └── uri: demo/sample_table\n└── weather\n    ├── format: delta\n    └── uri: demo/weather\n```\n\n#### Display a given table metadata\n\n```bash\n$ laketower -c demo/laketower.yml tables metadata sample_table\n\nsample_table\n├── name: Demo table\n├── description: A sample demo Delta table\n├── format: delta\n├── uri: /Users/romain/Documents/dev/datalpia/laketower/demo/sample_table/\n├── id: c1cb1cf0-1f3f-47b5-a660-3cc800edd341\n├── version: 3\n├── created at: 2025-02-05 22:27:39.579000+00:00\n├── partitions:\n└── configuration: {}\n```\n\n#### Display a given table schema\n\n```bash\n$ laketower -c demo/laketower.yml tables schema weather\n\nweather\n├── time: timestamp[us, tz=UTC]\n├── city: string\n├── temperature_2m: float\n├── relative_humidity_2m: float\n└── wind_speed_10m: float\n```\n\n#### Display a given table history\n\n```bash\n$ uv run laketower -c demo/laketower.yml tables history weather\n\nweather\n├── version: 2\n│   ├── timestamp: 2025-02-05 22:27:46.425000+00:00\n│   ├── client version: delta-rs.0.23.1\n│   ├── operation: WRITE\n│   ├── operation parameters\n│   │   └── mode: Append\n│   └── operation metrics\n│       ├── execution_time_ms: 4\n│       ├── num_added_files: 1\n│       ├── num_added_rows: 168\n│       ├── num_partitions: 0\n│       └── num_removed_files: 0\n├── version: 1\n│   ├── timestamp: 2025-02-05 22:27:45.666000+00:00\n│   ├── client version: delta-rs.0.23.1\n│   ├── operation: WRITE\n│   ├── operation parameters\n│   │   └── mode: Append\n│   └── operation metrics\n│       ├── execution_time_ms: 4\n│       ├── num_added_files: 1\n│       ├── num_added_rows: 408\n│       ├── num_partitions: 0\n│       └── num_removed_files: 0\n└── version: 0\n    ├── timestamp: 2025-02-05 22:27:39.722000+00:00\n    ├── client version: delta-rs.0.23.1\n    ├── operation: CREATE TABLE\n    ├── operation parameters\n    │   ├── metadata: {\"configuration\":{},\"createdTime\":1738794459722,\"description\":\"Historical and forecast weather data from\n    │   │   open-meteo.com\",\"format\":{\"options\":{},\"provider\":\"parquet\"},\"id\":\"a9615fb1-25cc-4546-a0fe-1cb534c514b2\",\"name\":\"Weather\",\"partitionCol\n    │   │   umns\":[],\"schemaString\":\"{\\\"type\\\":\\\"struct\\\",\\\"fields\\\":[{\\\"name\\\":\\\"time\\\",\\\"type\\\":\\\"timestamp\\\",\\\"nullable\\\":true,\\\"metadata\\\":{}},\n    │   │   {\\\"name\\\":\\\"city\\\",\\\"type\\\":\\\"string\\\",\\\"nullable\\\":true,\\\"metadata\\\":{}},{\\\"name\\\":\\\"temperature_2m\\\",\\\"type\\\":\\\"float\\\",\\\"nullable\\\":\n    │   │   true,\\\"metadata\\\":{}},{\\\"name\\\":\\\"relative_humidity_2m\\\",\\\"type\\\":\\\"float\\\",\\\"nullable\\\":true,\\\"metadata\\\":{}},{\\\"name\\\":\\\"wind_speed_1\n    │   │   0m\\\",\\\"type\\\":\\\"float\\\",\\\"nullable\\\":true,\\\"metadata\\\":{}}]}\"}\n    │   ├── protocol: {\"minReaderVersion\":1,\"minWriterVersion\":2}\n    │   ├── mode: ErrorIfExists\n    │   └── location: file:///Users/romain/Documents/dev/datalpia/laketower/demo/weather\n    └── operation metrics\n```\n\n#### Get statistics of a given table\n\nGet basic statistics on all columns of a given table:\n\n```bash\n$ laketower -c demo/laketower.yml tables statistics weather\n\n┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓\n┃ column_name          ┃ count ┃ avg                ┃ std                ┃ min                    ┃ max                    ┃\n┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩\n│ time                 │ 576   │ None               │ None               │ 2025-01-26 01:00:00+01 │ 2025-02-12 00:00:00+01 │\n│ city                 │ 576   │ None               │ None               │ Grenoble               │ Grenoble               │\n│ temperature_2m       │ 576   │ 5.2623263956047595 │ 3.326529069892729  │ 0.0                    │ 15.1                   │\n│ relative_humidity_2m │ 576   │ 78.76909722222223  │ 15.701802163559918 │ 29.0                   │ 100.0                  │\n│ wind_speed_10m       │ 576   │ 7.535763886032833  │ 10.00898058743763  │ 0.0                    │ 42.4                   │\n└──────────────────────┴───────┴────────────────────┴────────────────────┴────────────────────────┴────────────────────────┘\n```\n\nSpecifying a table version yields according results:\n\n```bash\n$ laketower -c demo/laketower.yml tables statistics --version 0 weather\n\n┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━┓\n┃ column_name          ┃ count ┃ avg  ┃ std  ┃ min  ┃ max  ┃\n┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━╇━━━━━━╇━━━━━━┩\n│ time                 │ 0     │ None │ None │ None │ None │\n│ city                 │ 0     │ None │ None │ None │ None │\n│ temperature_2m       │ 0     │ None │ None │ None │ None │\n│ relative_humidity_2m │ 0     │ None │ None │ None │ None │\n│ wind_speed_10m       │ 0     │ None │ None │ None │ None │\n└──────────────────────┴───────┴──────┴──────┴──────┴──────┘\n```\n\n#### Import data into a given table\n\nImport a CSV dataset into a table in append mode:\n\n```bash\n$ laketower -c demo/laketower.yml tables import weather --file data.csv --mode append --format csv --delimiter ',' --encoding 'utf-8'\n```\n\n`--mode` argument can be one of:\n- `append`: append rows to the table (default)\n- `overwrite`: replace all rows with the ones from the input file\n\n`--format` argument can be one of:\n- `csv`: CSV file format (default)\n- `xlsx`: Excel file format (requires `laketower[excel]`, imports the first sheet)\n\n`--delimiter` argument can be:\n- Any single character (only valid for CSV file format)\n- Default is _comma_ (`','`)\n\n`--encoding` argument can be:\n- Any [standard Python encoding](https://docs.python.org/3/library/codecs.html#standard-encodings),\n- Default is `'utf-8'`\n- Only applies to CSV file format\n\n#### View a given table\n\nUsing a simple query builder, the content of a table can be displayed.\nOptional arguments:\n\n- `--cols \u003ccol1\u003e \u003ccol2\u003e`: select which columns to display\n- `--sort-asc \u003ccol\u003e`: sort by a column name in ascending order\n- `--sort-desc \u003ccol\u003e`: sort by a column name in descending order\n- `--limit \u003cnum\u003e` (default 10): limit the number of rows\n- `--version`: time-travel to table revision number\n\n```bash\n$ laketower -c demo/laketower.yml tables view weather\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n┃ time                      ┃ city     ┃ temperature_2m     ┃ relative_humidity_2m ┃ wind_speed_10m    ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n│ 2025-02-05 01:00:00+01:00 │ Grenoble │ 2.0                │ 84.0                 │ 4.0               │\n│ 2025-02-05 02:00:00+01:00 │ Grenoble │ 2.0999999046325684 │ 83.0                 │ 1.5               │\n│ 2025-02-05 03:00:00+01:00 │ Grenoble │ 1.600000023841858  │ 86.0                 │ 1.100000023841858 │\n│ 2025-02-05 04:00:00+01:00 │ Grenoble │ 1.899999976158142  │ 80.0                 │ 4.199999809265137 │\n│ 2025-02-05 05:00:00+01:00 │ Grenoble │ 1.899999976158142  │ 81.0                 │ 3.299999952316284 │\n│ 2025-02-05 06:00:00+01:00 │ Grenoble │ 1.399999976158142  │ 88.0                 │ 4.300000190734863 │\n│ 2025-02-05 07:00:00+01:00 │ Grenoble │ 1.7000000476837158 │ 87.0                 │ 5.5               │\n│ 2025-02-05 08:00:00+01:00 │ Grenoble │ 1.5                │ 82.0                 │ 4.699999809265137 │\n│ 2025-02-05 09:00:00+01:00 │ Grenoble │ 1.899999976158142  │ 80.0                 │ 2.200000047683716 │\n│ 2025-02-05 10:00:00+01:00 │ Grenoble │ 2.9000000953674316 │ 80.0                 │ 0.800000011920929 │\n└───────────────────────────┴──────────┴────────────────────┴──────────────────────┴───────────────────┘\n```\n\n```bash\n$ laketower -c demo/laketower.yml tables view weather --cols time city temperature_2m --limit 5 --sort-desc time\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓\n┃ time                      ┃ city     ┃ temperature_2m    ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩\n│ 2025-02-12 00:00:00+01:00 │ Grenoble │ 5.099999904632568 │\n│ 2025-02-12 00:00:00+01:00 │ Grenoble │ 5.099999904632568 │\n│ 2025-02-11 23:00:00+01:00 │ Grenoble │ 4.900000095367432 │\n│ 2025-02-11 23:00:00+01:00 │ Grenoble │ 4.900000095367432 │\n│ 2025-02-11 22:00:00+01:00 │ Grenoble │ 4.900000095367432 │\n└───────────────────────────┴──────────┴───────────────────┘\n```\n\n```bash\n$ laketower -c demo/laketower.yml tables view weather --version 1\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓\n┃ time                      ┃ city     ┃ temperature_2m    ┃ relative_humidity_2m ┃ wind_speed_10m     ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩\n│ 2025-01-26 01:00:00+01:00 │ Grenoble │ 7.0               │ 87.0                 │ 8.899999618530273  │\n│ 2025-01-26 02:00:00+01:00 │ Grenoble │ 6.099999904632568 │ 87.0                 │ 6.199999809265137  │\n│ 2025-01-26 03:00:00+01:00 │ Grenoble │ 6.0               │ 86.0                 │ 2.700000047683716  │\n│ 2025-01-26 04:00:00+01:00 │ Grenoble │ 6.099999904632568 │ 82.0                 │ 3.0999999046325684 │\n│ 2025-01-26 05:00:00+01:00 │ Grenoble │ 5.5               │ 87.0                 │ 3.299999952316284  │\n│ 2025-01-26 06:00:00+01:00 │ Grenoble │ 5.199999809265137 │ 91.0                 │ 2.200000047683716  │\n│ 2025-01-26 07:00:00+01:00 │ Grenoble │ 4.800000190734863 │ 86.0                 │ 3.0                │\n│ 2025-01-26 08:00:00+01:00 │ Grenoble │ 4.900000095367432 │ 83.0                 │ 1.100000023841858  │\n│ 2025-01-26 09:00:00+01:00 │ Grenoble │ 4.0               │ 92.0                 │ 3.0999999046325684 │\n│ 2025-01-26 10:00:00+01:00 │ Grenoble │ 5.0               │ 86.0                 │ 6.400000095367432  │\n└───────────────────────────┴──────────┴───────────────────┴──────────────────────┴────────────────────┘\n```\n\n#### Query all registered tables\n\nQuery any registered tables using DuckDB SQL dialect!\n\n```bash\n$ laketower -c demo/laketower.yml tables query \"select date_trunc('day', time) as day, avg(temperature_2m) as mean_temperature from weather group by day order by day desc limit 3\"\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓\n┃ day                       ┃ mean_temperature   ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩\n│ 2025-02-12 00:00:00+01:00 │ 5.099999904632568  │\n│ 2025-02-11 00:00:00+01:00 │ 4.833333373069763  │\n│ 2025-02-10 00:00:00+01:00 │ 2.1083333243926368 │\n└───────────────────────────┴────────────────────┘\n3 rows returned\nExecution time: 33.72ms\n```\n\nUse named parameters within a giving query (note: escape `$` prefixes properly!):\n\n```bash\n$ laketower -c demo/laketower.yml tables query \"select date_trunc('day', time) as day, avg(temperature_2m) as mean_temperature from weather where day between \\$start_date and \\$end_date group by day order by day desc\" -p start_date 2025-01-29 -p end_date 2025-01-31\n\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓\n┃ day                       ┃ mean_temperature   ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩\n│ 2025-01-31 00:00:00+01:00 │ 5.683333257834117  │\n│ 2025-01-30 00:00:00+01:00 │ 8.900000015894571  │\n│ 2025-01-29 00:00:00+01:00 │ 7.770833313465118  │\n└───────────────────────────┴────────────────────┘\n4 rows returned\nExecution time: 30.59ms\n```\n\nExport query results to CSV:\n\n```bash\n$ laketower -c demo/laketower.yml tables query --output results.csv \"select date_trunc('day', time) as day, avg(temperature_2m) as mean_temperature from weather group by day order by day desc limit 3\"\n\nQuery results written to: results.csv\n```\n\n#### List saved queries\n\n```bash\n$ laketower -c demo/laketower.yml queries list\n\nqueries\n├── all_data\n└── daily_avg_temperature\n```\n\n#### Execute saved queries\n\n```bash\n$ laketower -c demo/laketower.yml queries view daily_avg_temperature\n\n┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓\n┃ #     ┃ day                       ┃ avg_temperature ┃\n┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩\n│ 1     │ 2025-01-26 00:00:00+01:00 │ 8.0             │\n│ 2     │ 2025-01-27 00:00:00+01:00 │ 13.0            │\n│ 3     │ 2025-01-28 00:00:00+01:00 │ 7.0             │\n│ 4     │ 2025-01-29 00:00:00+01:00 │ 8.0             │\n│ 5     │ 2025-01-30 00:00:00+01:00 │ 9.0             │\n│ 6     │ 2025-01-31 00:00:00+01:00 │ 6.0             │\n│ 7     │ 2025-02-01 00:00:00+01:00 │ 4.0             │\n│ 8     │ 2025-02-02 00:00:00+01:00 │ 4.0             │\n│ 9     │ 2025-02-03 00:00:00+01:00 │ 4.0             │\n│ 10    │ 2025-02-04 00:00:00+01:00 │ 3.0             │\n│ 11    │ 2025-02-05 00:00:00+01:00 │ 3.0             │\n│ 12    │ 2025-02-06 00:00:00+01:00 │ 2.0             │\n│ 13    │ 2025-02-07 00:00:00+01:00 │ 6.0             │\n│ 14    │ 2025-02-08 00:00:00+01:00 │ 7.0             │\n│ 15    │ 2025-02-09 00:00:00+01:00 │ 5.0             │\n│ 16    │ 2025-02-10 00:00:00+01:00 │ 2.0             │\n│ 17    │ 2025-02-11 00:00:00+01:00 │ 5.0             │\n│ 18    │ 2025-02-12 00:00:00+01:00 │ 5.0             │\n├───────┼───────────────────────────┼─────────────────┤\n│ Total │ -                         │ 101.0           │\n└───────┴───────────────────────────┴─────────────────┘\n18 rows returned\nExecution time: 27.02ms\n```\n\nExecuting a predefined query with parameters (here `start_date` and `end_date`):\n\n```bash\n$ laketower -c demo/laketower.yml queries view daily_avg_temperature_params -p start_date 2025-02-01 -p end_date 2025-02-05\n\n┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓\n┃ # ┃ day                       ┃ avg_temperature ┃\n┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩\n│ 1 │ 2025-02-01 00:00:00+01:00 │ 4.0             │\n│ 2 │ 2025-02-02 00:00:00+01:00 │ 4.0             │\n│ 3 │ 2025-02-03 00:00:00+01:00 │ 4.0             │\n│ 4 │ 2025-02-04 00:00:00+01:00 │ 3.0             │\n│ 5 │ 2025-02-05 00:00:00+01:00 │ 3.0             │\n│ 6 │ 2025-02-06 00:00:00+01:00 │ 2.0             │\n└───┴───────────────────────────┴─────────────────┘\n6 rows returned\nExecution time: 29.70ms\n```\n\n## License\n\nLicensed under [Apache License 2.0](LICENSE)\n\nCopyright (c) 2025 - present Romain Clement / Datalpia\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatalpia%2Flaketower","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatalpia%2Flaketower","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatalpia%2Flaketower/lists"}