[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EMR3WHWZ82EEX486JB9NAD":3,"skill-same:01M6EMR3WHWZ82EEX486JB9NAD":93},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":61,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":63,"updatedAt":64,"install":65,"resources":78},"01M6EMR3WHWZ82EEX486JB9NAD","creating-bauplan-pipelines",null,"Creates bauplan data pipeline projects with SQL and Python models. Use when starting a new pipeline, defining DAG transformations, writing models, or setting up bauplan project structure from scratch.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbauplanlabs\u002Fcreating-bauplan-pipelines\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"creating bauplan pipelines","pipelines","read","From Scratch","project","domain","structure","up","use","write","writing","projects","Bash","pipeline","data","data pipeline","sql","project structure","dag","python","2026-11-10 10:12:30",false,"---\nname: creating-bauplan-pipelines\ndescription: \"Creates bauplan data pipeline projects with SQL and Python models. Use when starting a new pipeline, defining DAG transformations, writing models, or setting up bauplan project structure from scratch.\"\nallowed-tools:\n  - Bash(bauplan:*)\n  - Read\n  - Write\n  - Glob\n  - Grep\n  - WebFetch(domain:docs.bauplanlabs.com)\n---\n\n# Creating a New Bauplan Data Pipeline\n\nThis skill guides you through creating a new bauplan data pipeline project from scratch, including the project configuration and SQL\u002FPython transformation models.\n\n## CRITICAL: Branch Safety\n\n> **NEVER run pipelines on `main` branch.** Always use a development branch.\n\nBranch naming convention: `\u003Cusername>.\u003Cbranch_name>` (e.g., `john.feature-pipeline`). Get your username with `bauplan info`. See [Workflow Checklist](#workflow-checklist) for exact commands.\n\n## Prerequisites\n\nBefore creating the pipeline, verify that:\n1. **You have a development branch** (not `main`)\n2. Source tables exist in the bauplan lakehouse (the default namespace is `bauplan`)\n3. You understand the schema of the source tables\n\n## Pipeline as a DAG\n\nA bauplan pipeline is a DAG of functions (models). Key rules:\n\n1. **Models**: SQL or Python functions that transform data\n2. **Source Tables**: Existing lakehouse tables - entry points to your DAG\n3. **Inputs**: Each model can take **multiple tables** via `bauplan.Model()` references\n4. **Outputs**: Each model produces **exactly one table**:\n   - SQL: output name = filename (`trips.sql` → `trips`)\n   - Python: output name = function name (`def clean_trips()` → `clean_trips`)\n5. **Topology**: Implicitly defined by input references - bauplan determines execution order\n\n**Expectations**: Data quality functions that take tables as input and return a **boolean**.\n\n### Example DAG\n\n```\n[lakehouse: taxi_fhvhv] ──→ [trips.sql] ──→ [clean_trips] ──→ [daily_summary]\n                                                ↑\n[lakehouse: taxi_zones] ────────────────────────┘\n```\n\nIn this example:\n- `taxi_fhvhv` and `taxi_zones` are source tables (already in lakehouse)\n- `trips.sql` reads from `taxi_fhvhv` (SQL model, first node)\n- `clean_trips` takes `trips` and `taxi_zones` as inputs (Python model, multiple inputs)\n- `daily_summary` takes `clean_trips` as input (Python model, single input)\n\n## Required User Input\n\nBefore writing a pipeline, you MUST gather the following information from the user:\n\n1. **Pipeline purpose** (required): What transformations should the DAG perform? What is the business logic or goal?\n2. **Source tables** (required): Which tables from the lakehouse should be used as inputs? Verify they exist with `bauplan table get`\n3. **Output tables** (required): Which tables should be materialized at the end of the pipeline? These are the final outputs visible to downstream consumers\n4. **Materialization strategy** (optional): Should output tables use `REPLACE` (default) or `APPEND`?\n5. **Strict mode** (optional): Should the pipeline run in strict mode? If yes, all CLI commands will use `--strict` flag, which fails on issues like output column mismatches during dry-run, allowing immediate error detection and correction.\n\nIf the user hasn't provided this information, ask before proceeding with implementation.\n\n### Strict Mode (--strict flag)\n\nWhen strict mode is enabled, append `--strict` to all `bauplan run` commands:\n\n```bash\n# Without strict mode (default)\nbauplan run --dry-run\nbauplan run\n\n# With strict mode enabled\nbauplan run --dry-run --strict\nbauplan run --strict\n```\n\n**Benefits of strict mode:**\n- Fails immediately on output column mismatches\n- Fails immediately if an expectation fails\n- Allows you to rectify declaration errors before pipeline completion\n- Recommended when iterating on pipeline development\n\n## Project Structure\n\nA bauplan project is a folder containing:\n\n```\nmy-project\u002F\n  bauplan_project.yml    # Required: project configuration\n  model.sql              # Optional: a single SQL model, one per file\n  models.py              # Optional: Python models (one file can have >1 models, or be split into multiple files)\n  expectations.py        # Optional: data quality tests (if any)\n```\n\n## bauplan_project.yml\n\nEvery project is a separate folder which requires this configuration file:\n\n```yaml\nproject:\n  id: \u003Cunique-uuid>       # Generate a unique UUID\n  name: \u003Cproject_name>    # Descriptive name for the project\n```\n\n## When to Use SQL vs Python Models\n\n> **IMPORTANT**: SQL models should be LIMITED to **first nodes** in the pipeline graph only.\n\n- **SQL models**: Use ONLY for nodes that read directly from source tables in the lakehouse (tables outside your pipeline graph)\n- **Python models**: Preferred for ALL other transformations in the pipeline\n\nThis ensures consistency and allows for better control over transformations, output schema validation, and documentation.\n\n## SQL Models (First Nodes Only)\n\nSQL models are `.sql` files where:\n- The **filename** becomes the output table name\n- The **FROM clause** defines input tables\n- Optional: Add materialization strategy as a comment\n\nUse SQL models only when reading from existing lakehouse tables:\n\n```sql\n-- trips.sql\n-- First node: reads from taxi_fhvhv table in the lakehouse\nSELECT\n    pickup_datetime,\n    PULocationID,\n    trip_miles\nFROM taxi_fhvhv\nWHERE pickup_datetime >= '2022-12-01'\n```\n\nOutput table: `trips` (from filename)\nInput table: `taxi_fhvhv` (from FROM clause, exists in lakehouse)\n\n## Python Models (Preferred)\n\nPython models use decorators to define transformations. They should be used for all pipeline nodes except first nodes reading from the lakehouse.\n\n### Key Decorators\n\n- `@bauplan.model()` - Registers function as a model\n- `@bauplan.model(columns=[...])` - Specify expected output columns for validation (Optional but recommended)\n- `@bauplan.model(materialization_strategy='REPLACE')` - Persist output to lakehouse\n- `@bauplan.python('3.11', pip={'pandas': '1.5.3'})` - Specify Python version and packages\n\n### Best Practice: Output Columns Validation\n\n> **IMPORTANT**: whenever possible, specify the `columns` parameter in `@bauplan.model()` to define the expected output schema. This enables automatic validation of your model's output.\n\nFirst, check the schema of your source tables to understand input columns. Then specify the output columns based on your transformation:\n\n```python\n# If input has columns: [id, name, age, city]\n# And transformation drops 'city' column\n# Then output columns should be: [id, name, age]\n\n@bauplan.model(columns=['id', 'name', 'age'])\n```\n\n### Best Practice: Docstrings with Output Schema\n\n> **IMPORTANT**: Every Python model should have a docstring describing the transformation and showing the output table structure as an ASCII table (if the table is too wide, show only key columns, if values are too large, truncate them in the cells).\n\n```python\n@bauplan.model(columns=['id', 'name', 'age'])\n@bauplan.python('3.11')\ndef clean_users(data=bauplan.Model('raw_users')):\n    \"\"\"\n    Cleans user data by removing invalid entries and dropping the city column.\n\n    | id  | name    | age |\n    |-----|---------|-----|\n    | 1   | Alice   | 30  |\n    | 2   | Bob     | 25  |\n    \"\"\"\n    # transformation logic\n    return data.drop_columns(['city'])\n```\n\n### I\u002FO Pushdown with `columns` and `filter`\n\n> **IMPORTANT**: whenever possible, use `columns` and `filter` parameters in `bauplan.Model()` to restrict the data read. This enables I\u002FO pushdown, dramatically reducing the amount of data transferred and improving performance. Do not read columns you don't need.\n\n```python\nbauplan.Model(\n    'table_name',\n    columns=['col1', 'col2', 'col3'],   # Only read these columns\n    filter=\"date >= '2022-01-01'\"       # Pre-filter at storage level\n)\n```\n\n**Whenever possible, specify:**\n- `columns`: List only the columns your model actually needs\n- `filter`: SQL-like filter expression to restrict rows at the storage level, if appropriate\n\n### Basic Python Model\n\n```python\nimport bauplan\n\n@bauplan.model(\n    columns=['pickup_datetime', 'PULocationID', 'trip_miles'],\n    materialization_strategy='REPLACE'\n)\n@bauplan.python('3.11', pip={'polars': '1.15.0'})\ndef clean_trips(\n    # Use columns and filter for I\u002FO pushdown\n    data=bauplan.Model(\n        'trips',\n        columns=['pickup_datetime', 'PULocationID', 'trip_miles'],\n        filter=\"trip_miles > 0\"\n    )\n):\n    \"\"\"\n    Filters trips to include only those with positive mileage.\n\n    | pickup_datetime     | PULocationID | trip_miles |\n    |---------------------|--------------|------------|\n    | 2022-12-01 08:00:00 | 123          | 5.2        |\n    \"\"\"\n    import polars as pl\n\n    df = pl.from_arrow(data)\n    df = df.filter(pl.col('trip_miles') > 0.0)\n\n    return df.to_arrow()\n```\n\n### Python Model with Multiple Inputs\n\nModels can take multiple tables as input - just add more `bauplan.Model()` parameters:\n\n```python\ndef model_with_joins(\n    table_a=bauplan.Model('source_a', columns=['id', 'value']),\n    table_b=bauplan.Model('source_b', columns=['id', 'name'])\n):\n    # Join, transform, return Arrow table\n    return table_a.join(table_b, 'id', 'id')\n```\n\nSee [examples.md](examples.md#multi-input-model) for complete multi-input examples with Polars.\n\n## Workflow Checklist\n\nCopy this checklist and track your progress:\n\n```\nPipeline Creation Progress:\n- [ ] Step 1: Get username → bauplan info\n- [ ] Step 2: Checkout main → bauplan branch checkout main\n- [ ] Step 3: Create dev branch → bauplan branch create \u003Cusername>.\u003Cbranch_name>\n- [ ] Step 4: Checkout dev branch → bauplan branch checkout \u003Cusername>.\u003Cbranch_name>\n- [ ] Step 5: Verify source tables → bauplan table get \u003Cnamespace>.\u003Ctable_name>, Optional for data preview: bauplan query \"SELECT * FROM \u003Cnamespace>.\u003Ctable_name> LIMIT 3\"\n- [ ] Step 6: Create project folder with bauplan_project.yml\n- [ ] Step 7: Write SQL model(s) \u002F Python model(s) for transformations respecting the guidelines\n- [ ] Step 8: Verify materialization decorators (see Materialization Checklist below)\n- [ ] Step 9: Dry run → bauplan run --dry-run [--strict if strict mode]\n- [ ] Step 10: Run pipeline → bauplan run [--strict if strict mode]\n```\n\n> **CRITICAL**: Never run on `main` branch. Steps 2-4 ensure you're on a development branch.\n\n### Materialization Checklist\n\nAfter writing models, verify that each model has the correct `materialization_strategy` based on user requirements:\n\n| Model Type | No Materialization (intermediate) | Materialized Output |\n|------------|-----------------------------------|---------------------|\n| **Python** | `@bauplan.model()` (no strategy) | `@bauplan.model(materialization_strategy='REPLACE')` or `'APPEND'` |\n| **SQL**    | No comment needed | Add comment: `-- bauplan: materialization_strategy=REPLACE` or `APPEND` |\n\n**Verify for each model:**\n- [ ] Intermediate tables (not final outputs): NO `materialization_strategy` specified\n- [ ] Final output tables requested by user: `materialization_strategy='REPLACE'` (default) or `'APPEND'`\n- [ ] If user specified APPEND for any table: confirm `materialization_strategy='APPEND'` is set\n\nExample Python decorator for materialized output:\n```python\n@bauplan.model(materialization_strategy='REPLACE', columns=['col1', 'col2'])\n```\n\nExample SQL comment for materialized output:\n```sql\n-- bauplan: materialization_strategy=REPLACE\nSELECT * FROM source_table\n```\n\n## Advanced Examples\n\nSee [examples.md](examples.md) for:\n- APPEND materialization strategy\n- DuckDB queries in Python models\n- Data quality expectations\n- Multi-stage pipelines\n","# Creating a New Bauplan Data Pipeline\n\nThis skill guides you through creating a new bauplan data pipeline project from scratch, including the project configuration and SQL\u002FPython transformation models.\n\n## CRITICAL: Branch Safety\n\n> **NEVER run pipelines on `main` branch.** Always use a development branch.\n\nBranch naming convention: `\u003Cusername>.\u003Cbranch_name>` (e.g., `john.feature-pipeline`). Get your username with `bauplan info`. See [Workflow Checklist](#workflow-checklist) for exact commands.\n\n## Prerequisites\n\nBefore creating the pipeline, verify that:\n1. **You have a development branch** (not `main`)\n2. Source tables exist in the bauplan lakehouse (the default namespace is `bauplan`)\n3. You understand the schema of the source tables\n\n## Pipeline as a DAG\n\nA bauplan pipeline is a DAG of functions (models). Key rules:\n\n1. **Models**: SQL or Python functions that transform data\n2. **Source Tables**: Existing lakehouse tables - entry points to your DAG\n3. **Inputs**: Each model can take **multiple tables** via `bauplan.Model()` references\n4. **Outputs**: Each model produces **exactly one table**:\n   - SQL: output name = filename (`trips.sql` → `trips`)\n   - Python: output name = function name (`def clean_trips()` → `clean_trips`)\n5. **Topology**: Implicitly defined by input references - bauplan determines execution order\n\n**Expectations**: Data quality functions that take tables as input and return a **boolean**.\n\n### Example DAG\n\n```\n[lakehouse: taxi_fhvhv] ──→ [trips.sql] ──→ [clean_trips] ──→ [daily_summary]\n                                                ↑\n[lakehouse: taxi_zones] ────────────────────────┘\n```\n\nIn this example:\n- `taxi_fhvhv` and `taxi_zones` are source tables (already in lakehouse)\n- `trips.sql` reads from `taxi_fhvhv` (SQL model, first node)\n- `clean_trips` takes `trips` and `taxi_zones` as inputs (Python model, multiple inputs)\n- `daily_summary` takes `clean_trips` as input (Python model, single input)\n\n## Required User Input\n\nBefore writing a pipeline, you MUST gather the following information from the user:\n\n1. **Pipeline purpose** (required): What transformations should the DAG perform? What is the business logic or goal?\n2. **Source tables** (required): Which tables from the lakehouse should be used as inputs? Verify they exist with `bauplan table get`\n3. **Output tables** (required): Which tables should be materialized at the end of the pipeline? These are the final outputs visible to downstream consumers\n4. **Materialization strategy** (optional): Should output tables use `REPLACE` (default) or `APPEND`?\n5. **Strict mode** (optional): Should the pipeline run in strict mode? If yes, all CLI commands will use `--strict` flag, which fails on issues like output column mismatches during dry-run, allowing immediate error detection and correction.\n\nIf the user hasn't provided this information, ask before proceeding with implementation.\n\n### Strict Mode (--strict flag)\n\nWhen strict mode is enabled, append `--strict` to all `bauplan run` commands:\n\n```bash\n# Without strict mode (default)\nbauplan run --dry-run\nbauplan run\n\n# With strict mode enabled\nbauplan run --dry-run --strict\nbauplan run --strict\n```\n\n**Benefits of strict mode:**\n- Fails immediately on output column mismatches\n- Fails immediately if an expectation fails\n- Allows you to rectify declaration errors before pipeline completion\n- Recommended when iterating on pipeline development\n\n## Project Structure\n\nA bauplan project is a folder containing:\n\n```\nmy-project\u002F\n  bauplan_project.yml    # Required: project configuration\n  model.sql              # Optional: a single SQL model, one per file\n  models.py              # Optional: Python models (one file can have >1 models, or be split into multiple files)\n  expectations.py        # Optional: data quality tests (if any)\n```\n\n## bauplan_project.yml\n\nEvery project is a separate folder which requires this configuration file:\n\n```yaml\nproject:\n  id: \u003Cunique-uuid>       # Generate a unique UUID\n  name: \u003Cproject_name>    # Descriptive name for the project\n```\n\n## When to Use SQL vs Python Models\n\n> **IMPORTANT**: SQL models should be LIMITED to **first nodes** in the pipeline graph only.\n\n- **SQL models**: Use ONLY for nodes that read directly from source tables in the lakehouse (tables outside your pipeline graph)\n- **Python models**: Preferred for ALL other transformations in the pipeline\n\nThis ensures consistency and allows for better control over transformations, output schema validation, and documentation.\n\n## SQL Models (First Nodes Only)\n\nSQL models are `.sql` files where:\n- The **filename** becomes the output table name\n- The **FROM clause** defines input tables\n- Optional: Add materialization strategy as a comment\n\nUse SQL models only when reading from existing lakehouse tables:\n\n```sql\n-- trips.sql\n-- First node: reads from taxi_fhvhv table in the lakehouse\nSELECT\n    pickup_datetime,\n    PULocationID,\n    trip_miles\nFROM taxi_fhvhv\nWHERE pickup_datetime >= '2022-12-01'\n```\n\nOutput table: `trips` (from filename)\nInput table: `taxi_fhvhv` (from FROM clause, exists in lakehouse)\n\n## Python Models (Preferred)\n\nPython models use decorators to define transformations. They should be used for all pipeline nodes except first nodes reading from the lakehouse.\n\n### Key Decorators\n\n- `@bauplan.model()` - Registers function as a model\n- `@bauplan.model(columns=[...])` - Specify expected output columns for validation (Optional but recommended)\n- `@bauplan.model(materialization_strategy='REPLACE')` - Persist output to lakehouse\n- `@bauplan.python('3.11', pip={'pandas': '1.5.3'})` - Specify Python version and packages\n\n### Best Practice: Output Columns Validation\n\n> **IMPORTANT**: whenever possible, specify the `columns` parameter in `@bauplan.model()` to define the expected output schema. This enables automatic validation of your model's output.\n\nFirst, check the schema of your source tables to understand input columns. Then specify the output columns based on your transformation:\n\n```python\n# If input has columns: [id, name, age, city]\n# And transformation drops 'city' column\n# Then output columns should be: [id, name, age]\n\n@bauplan.model(columns=['id', 'name', 'age'])\n```\n\n### Best Practice: Docstrings with Output Schema\n\n> **IMPORTANT**: Every Python model should have a docstring describing the transformation and showing the output table structure as an ASCII table (if the table is too wide, show only key columns, if values are too large, truncate them in the cells).\n\n```python\n@bauplan.model(columns=['id', 'name', 'age'])\n@bauplan.python('3.11')\ndef clean_users(data=bauplan.Model('raw_users')):\n    \"\"\"\n    Cleans user data by removing invalid entries and dropping the city column.\n\n    | id  | name    | age |\n    |-----|---------|-----|\n    | 1   | Alice   | 30  |\n    | 2   | Bob     | 25  |\n    \"\"\"\n    # transformation logic\n    return data.drop_columns(['city'])\n```\n\n### I\u002FO Pushdown with `columns` and `filter`\n\n> **IMPORTANT**: whenever possible, use `columns` and `filter` parameters in `bauplan.Model()` to restrict the data read. This enables I\u002FO pushdown, dramatically reducing the amount of data transferred and improving performance. Do not read columns you don't need.\n\n```python\nbauplan.Model(\n    'table_name',\n    columns=['col1', 'col2', 'col3'],   # Only read these columns\n    filter=\"date >= '2022-01-01'\"       # Pre-filter at storage level\n)\n```\n\n**Whenever possible, specify:**\n- `columns`: List only the columns your model actually needs\n- `filter`: SQL-like filter expression to restrict rows at the storage level, if appropriate\n\n### Basic Python Model\n\n```python\nimport bauplan\n\n@bauplan.model(\n    columns=['pickup_datetime', 'PULocationID', 'trip_miles'],\n    materialization_strategy='REPLACE'\n)\n@bauplan.python('3.11', pip={'polars': '1.15.0'})\ndef clean_trips(\n    # Use columns and filter for I\u002FO pushdown\n    data=bauplan.Model(\n        'trips',\n        columns=['pickup_datetime', 'PULocationID', 'trip_miles'],\n        filter=\"trip_miles > 0\"\n    )\n):\n    \"\"\"\n    Filters trips to include only those with positive mileage.\n\n    | pickup_datetime     | PULocationID | trip_miles |\n    |---------------------|--------------|------------|\n    | 2022-12-01 08:00:00 | 123          | 5.2        |\n    \"\"\"\n    import polars as pl\n\n    df = pl.from_arrow(data)\n    df = df.filter(pl.col('trip_miles') > 0.0)\n\n    return df.to_arrow()\n```\n\n### Python Model with Multiple Inputs\n\nModels can take multiple tables as input - just add more `bauplan.Model()` parameters:\n\n```python\ndef model_with_joins(\n    table_a=bauplan.Model('source_a', columns=['id', 'value']),\n    table_b=bauplan.Model('source_b', columns=['id', 'name'])\n):\n    # Join, transform, return Arrow table\n    return table_a.join(table_b, 'id', 'id')\n```\n\nSee [examples.md](examples.md#multi-input-model) for complete multi-input examples with Polars.\n\n## Workflow Checklist\n\nCopy this checklist and track your progress:\n\n```\nPipeline Creation Progress:\n- [ ] Step 1: Get username → bauplan info\n- [ ] Step 2: Checkout main → bauplan branch checkout main\n- [ ] Step 3: Create dev branch → bauplan branch create \u003Cusername>.\u003Cbranch_name>\n- [ ] Step 4: Checkout dev branch → bauplan branch checkout \u003Cusername>.\u003Cbranch_name>\n- [ ] Step 5: Verify source tables → bauplan table get \u003Cnamespace>.\u003Ctable_name>, Optional for data preview: bauplan query \"SELECT * FROM \u003Cnamespace>.\u003Ctable_name> LIMIT 3\"\n- [ ] Step 6: Create project folder with bauplan_project.yml\n- [ ] Step 7: Write SQL model(s) \u002F Python model(s) for transformations respecting the guidelines\n- [ ] Step 8: Verify materialization decorators (see Materialization Checklist below)\n- [ ] Step 9: Dry run → bauplan run --dry-run [--strict if strict mode]\n- [ ] Step 10: Run pipeline → bauplan run [--strict if strict mode]\n```\n\n> **CRITICAL**: Never run on `main` branch. Steps 2-4 ensure you're on a development branch.\n\n### Materialization Checklist\n\nAfter writing models, verify that each model has the correct `materialization_strategy` based on user requirements:\n\n| Model Type | No Materialization (intermediate) | Materialized Output |\n|------------|-----------------------------------|---------------------|\n| **Python** | `@bauplan.model()` (no strategy) | `@bauplan.model(materialization_strategy='REPLACE')` or `'APPEND'` |\n| **SQL**    | No comment needed | Add comment: `-- bauplan: materialization_strategy=REPLACE` or `APPEND` |\n\n**Verify for each model:**\n- [ ] Intermediate tables (not final outputs): NO `materialization_strategy` specified\n- [ ] Final output tables requested by user: `materialization_strategy='REPLACE'` (default) or `'APPEND'`\n- [ ] If user specified APPEND for any table: confirm `materialization_strategy='APPEND'` is set\n\nExample Python decorator for materialized output:\n```python\n@bauplan.model(materialization_strategy='REPLACE', columns=['col1', 'col2'])\n```\n\nExample SQL comment for materialized output:\n```sql\n-- bauplan: materialization_strategy=REPLACE\nSELECT * FROM source_table\n```\n\n## Advanced Examples\n\nSee [examples.md](examples.md) for:\n- APPEND materialization strategy\n- DuckDB queries in Python models\n- Data quality expectations\n- Multi-stage pipelines\n",{"name":5,"description":7,"allowed-tools":49},[50,51,52,53,54,55],"Bash(bauplan:*)","Read","Write","Glob","Grep","WebFetch(domain:docs.bauplanlabs.com)","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fbauplanlabs\u002Fcreating-bauplan-pipelines",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":66,"prompt":76,"zipAvailable":77},[67,70,73],{"tool":68,"command":69},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill creating-bauplan-pipelines",{"tool":71,"command":72},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill creating-bauplan-pipelines",{"tool":74,"command":75},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill creating-bauplan-pipelines","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbauplanlabs\u002Fcreating-bauplan-pipelines\u002FSKILL.md",true,[79,85,89],{"path":80,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":83,"sourceHtmlUrl":84},"agents\u002Fopenai.yaml","REFERENCE","参考文档",85,"https:\u002F\u002Fgithub.com\u002FHigorAlves\u002Forc\u002Fblob\u002Fmain\u002Fcodex\u002Forc\u002Fskills\u002Forc-env\u002Fagents\u002Fopenai.yaml",{"path":86,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":87,"sourceHtmlUrl":88},"examples.md",14126,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbauplanlabs\u002Fcreating-bauplan-pipelines\u002Fexamples.md",{"path":90,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":91,"sourceHtmlUrl":92},"skill-report.json",25264,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbauplanlabs\u002Fcreating-bauplan-pipelines\u002Fskill-report.json",[94,108,118,127,133,140],{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":104,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[99],{"categoryNo":100,"categoryName":101,"taxonomyType":102,"taxonomyTypeDesc":103},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[105,106,107],"model","model hierarchy","model hierarchy skill",{"skillNo":109,"name":110,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":114,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[113],{"categoryNo":100,"categoryName":101,"taxonomyType":102,"taxonomyTypeDesc":103},[115,116,117],"MCP","zoom","zoom mcp",{"skillNo":119,"name":120,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[124,125,126,116],"sdk","zoom apps sdk","apps",{"skillNo":128,"name":129,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[129],{"skillNo":134,"name":135,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":136,"categories":137,"keywords":139,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[138],{"categoryNo":100,"categoryName":101,"taxonomyType":102,"taxonomyTypeDesc":103},[135],{"skillNo":141,"name":142,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":145,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[142]]