From c405d167dcc48baef26816332432e94321348162 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Fri, 27 Feb 2026 12:43:29 +0530
Subject: [PATCH 01/13] add skills

add presubmit workflow for skills

fix workflow

Update skills-validate.yml

fix workflows

ignore skills dir for license headers

update docs

fix header check

fix copyright year

test failure for validation workflow

revert skill testing failure

revert license file changes

add year pattern regex

test header check years

Update header-check.yml

Update settings

fix env var propagation

address comment
---
 .../workflows/skills-validate-fallback.yml    |  37 +
 .github/workflows/skills-validate.yml         |  56 ++
 CLOUD-SQL-POSTGRESQL.md                       |  12 +-
 README.md                                     |  49 +-
 gemini-extension.json                         |  28 +-
 skills/cloudsql-postgres/SKILL.md             | 704 ++++++++++++++++++
 .../assets/database_overview.yaml             |  17 +
 .../cloudsql-postgres/assets/execute_sql.yaml |  17 +
 .../assets/get_column_cardinality.yaml        |  17 +
 .../assets/get_query_plan.yaml                |  33 +
 .../assets/list_active_queries.yaml           |  17 +
 .../list_autovacuum_configurations.yaml       |  24 +
 .../assets/list_available_extensions.yaml     |  17 +
 .../assets/list_database_stats.yaml           |  17 +
 .../assets/list_indexes.yaml                  |  17 +
 .../assets/list_installed_extensions.yaml     |  17 +
 .../assets/list_invalid_indexes.yaml          |  32 +
 .../cloudsql-postgres/assets/list_locks.yaml  |  17 +
 .../assets/list_memory_configurations.yaml    |  36 +
 .../assets/list_pg_settings.yaml              |  17 +
 .../assets/list_publication_tables.yaml       |  17 +
 .../assets/list_query_stats.yaml              |  17 +
 .../assets/list_replication_slots.yaml        |  33 +
 .../cloudsql-postgres/assets/list_roles.yaml  |  17 +
 .../assets/list_schemas.yaml                  |  17 +
 .../assets/list_sequences.yaml                |  17 +
 .../assets/list_stored_procedure.yaml         |  17 +
 .../assets/list_table_stats.yaml              |  17 +
 .../cloudsql-postgres/assets/list_tables.yaml |  17 +
 .../assets/list_tablespaces.yaml              |  17 +
 .../assets/list_top_bloated_tables.yaml       |  47 ++
 .../assets/list_triggers.yaml                 |  17 +
 .../cloudsql-postgres/assets/list_views.yaml  |  17 +
 .../assets/long_running_transactions.yaml     |  17 +
 .../assets/replication_stats.yaml             |  17 +
 .../scripts/database_overview.js              |  54 ++
 .../cloudsql-postgres/scripts/execute_sql.js  |  53 ++
 .../scripts/get_column_cardinality.js         |  54 ++
 .../scripts/get_query_plan.js                 |  54 ++
 .../scripts/list_active_queries.js            |  54 ++
 .../scripts/list_autovacuum_configurations.js |  54 ++
 .../scripts/list_available_extensions.js      |  54 ++
 .../scripts/list_database_stats.js            |  54 ++
 .../cloudsql-postgres/scripts/list_indexes.js |  54 ++
 .../scripts/list_installed_extensions.js      |  54 ++
 .../scripts/list_invalid_indexes.js           |  54 ++
 .../cloudsql-postgres/scripts/list_locks.js   |  54 ++
 .../scripts/list_memory_configurations.js     |  54 ++
 .../scripts/list_pg_settings.js               |  54 ++
 .../scripts/list_publication_tables.js        |  54 ++
 .../scripts/list_query_stats.js               |  54 ++
 .../scripts/list_replication_slots.js         |  54 ++
 .../cloudsql-postgres/scripts/list_roles.js   |  54 ++
 .../cloudsql-postgres/scripts/list_schemas.js |  54 ++
 .../scripts/list_sequences.js                 |  54 ++
 .../scripts/list_stored_procedure.js          |  54 ++
 .../scripts/list_table_stats.js               |  54 ++
 .../cloudsql-postgres/scripts/list_tables.js  |  54 ++
 .../scripts/list_tablespaces.js               |  54 ++
 .../scripts/list_top_bloated_tables.js        |  54 ++
 .../scripts/list_triggers.js                  |  54 ++
 .../cloudsql-postgres/scripts/list_views.js   |  54 ++
 skills/cloudsql-postgres/scripts/load_env.js  |  75 ++
 .../scripts/long_running_transactions.js      |  54 ++
 .../scripts/replication_stats.js              |  54 ++
 65 files changed, 3055 insertions(+), 67 deletions(-)
 create mode 100644 .github/workflows/skills-validate-fallback.yml
 create mode 100644 .github/workflows/skills-validate.yml
 create mode 100644 skills/cloudsql-postgres/SKILL.md
 create mode 100644 skills/cloudsql-postgres/assets/database_overview.yaml
 create mode 100644 skills/cloudsql-postgres/assets/execute_sql.yaml
 create mode 100644 skills/cloudsql-postgres/assets/get_column_cardinality.yaml
 create mode 100644 skills/cloudsql-postgres/assets/get_query_plan.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_active_queries.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_available_extensions.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_database_stats.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_indexes.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_installed_extensions.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_locks.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_memory_configurations.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_pg_settings.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_publication_tables.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_query_stats.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_replication_slots.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_roles.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_schemas.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_sequences.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_stored_procedure.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_table_stats.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_tables.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_tablespaces.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_triggers.yaml
 create mode 100644 skills/cloudsql-postgres/assets/list_views.yaml
 create mode 100644 skills/cloudsql-postgres/assets/long_running_transactions.yaml
 create mode 100644 skills/cloudsql-postgres/assets/replication_stats.yaml
 create mode 100755 skills/cloudsql-postgres/scripts/database_overview.js
 create mode 100755 skills/cloudsql-postgres/scripts/execute_sql.js
 create mode 100755 skills/cloudsql-postgres/scripts/get_column_cardinality.js
 create mode 100755 skills/cloudsql-postgres/scripts/get_query_plan.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_active_queries.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_available_extensions.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_database_stats.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_indexes.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_installed_extensions.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_invalid_indexes.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_locks.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_memory_configurations.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_pg_settings.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_publication_tables.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_query_stats.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_replication_slots.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_roles.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_schemas.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_sequences.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_stored_procedure.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_table_stats.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_tables.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_tablespaces.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_triggers.js
 create mode 100755 skills/cloudsql-postgres/scripts/list_views.js
 create mode 100644 skills/cloudsql-postgres/scripts/load_env.js
 create mode 100755 skills/cloudsql-postgres/scripts/long_running_transactions.js
 create mode 100755 skills/cloudsql-postgres/scripts/replication_stats.js

diff --git a/.github/workflows/skills-validate-fallback.yml b/.github/workflows/skills-validate-fallback.yml
new file mode 100644
index 0000000..b49eb62
--- /dev/null
+++ b/.github/workflows/skills-validate-fallback.yml
@@ -0,0 +1,37 @@
+# Copyright 2026 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: lint
+
+on:
+  push:
+    paths-ignore:
+      - "skills/**"
+  pull_request:
+    paths-ignore:
+      - "skills/**"
+  pull_request_target:
+    types: [labeled]
+    paths-ignore:
+      - "skills/**"
+  workflow_dispatch:
+
+jobs:
+  skills-validate:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Skip Skill Validation
+        run: |
+          echo "No changes detected in 'skills/' directory. Skipping validation."
+          echo "This job ensures the required 'skills-validate' status check passes."
diff --git a/.github/workflows/skills-validate.yml b/.github/workflows/skills-validate.yml
new file mode 100644
index 0000000..c831e21
--- /dev/null
+++ b/.github/workflows/skills-validate.yml
@@ -0,0 +1,56 @@
+# Copyright 2026 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Validate Skills
+
+on:
+  push:
+    paths:
+      - "skills/**"
+  pull_request:
+    paths:
+      - "skills/**"
+  pull_request_target:
+    types: [labeled]
+    paths:
+      - "skills/**"
+
+jobs:
+  skills-validate:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.11"
+
+      - name: Install skills-ref
+        run: |
+          pip install "git+https://github.com/agentskills/agentskills.git#subdirectory=skills-ref"
+
+      - name: Validate Skills
+        run: |
+          failed=0
+          for skill_dir in skills/*/; do
+            if [ -d "$skill_dir" ]; then
+              echo "Validating $skill_dir..."
+              if ! skills-ref validate "$skill_dir"; then
+                echo "Validation failed for $skill_dir"
+                failed=1
+              fi
+            fi
+          done
+          exit $failed
diff --git a/CLOUD-SQL-POSTGRESQL.md b/CLOUD-SQL-POSTGRESQL.md
index c09d3ed..877fd18 100644
--- a/CLOUD-SQL-POSTGRESQL.md
+++ b/CLOUD-SQL-POSTGRESQL.md
@@ -39,9 +39,9 @@ This section covers administrative operations like managing clusters, instances,
 
 ---
 
-# Additional Tools
+# Additional Skills
 
-This section provides context on additional tools that can be recommended to the user based on their queries.
+This section provides context on additional skills that can be recommended to the user based on their queries.
 
 #### Observability Extension
 
@@ -58,7 +58,7 @@ This section provides context on additional tools that can be recommended to the
 
 ## Connecting to New Resources
 
-When you create a new Cloud SQL for PostgreSQL instance, or database using the available tools, the connection is not automatically established. You will need to perform the following steps:
+When you create a new Cloud SQL for PostgreSQL instance, or database using the available skills, the connection is not automatically established. You will need to perform the following steps:
 
 1.  **(Optional) Save your conversation:** To avoid losing your progress, save the current session by running the command: `/chat save <your-tag>`
 2.  **Stop the CLI:** Terminate the Gemini CLI.
@@ -77,12 +77,12 @@ Users may have set project environment variables:
 *   `CLOUD_SQL_POSTGRES_INSTANCE`: The ID of the Cloud SQL for PostgreSQL instance.
 *   `CLOUD_SQL_POSTGRES_DATABASE`: The name of the database.
 
-Instead of prompting the user for these values for specific tool calls, prompt the user to verify reuse a specific value.
+Instead of prompting the user for these values for specific skill calls, prompt the user to verify reuse a specific value.
 Make sure to not use the environment variable name like `CLOUD_SQL_POSTGRES_PROJECT`, `${CLOUD_SQL_POSTGRES_PROJECT}`, or `$CLOUD_SQL_POSTGRES_PROJECT`. The value can be found by using command: `echo $CLOUD_SQL_POSTGRES_PROJECT`.
 
 ## Use Full Table Name Format "DATABASE_NAME.SCHEMA_NAME.TABLE_NAME"
 
-**ALWAYS** use the full table name format, `DATABASE_NAME.SCHEMA_NAME.TABLE_NAME` in the generated SQL when using the `execute_sql` or `cloud_sql_postgresql__execute_sql` tool.
+**ALWAYS** use the full table name format, `DATABASE_NAME.SCHEMA_NAME.TABLE_NAME` in the generated SQL when executing the `execute_sql` script.
 * Default to using "public" for the schema name.
 * Use command `echo $CLOUD_SQL_POSTGRES_DATABASE` to get the current database value.
 
@@ -92,7 +92,7 @@ When working with AI features like vector embeddings in Cloud SQL, leverage the
 
 Embeddings can be generated using the `embedding()` function. For example: `embedding(<model_name>, <text_column_or_variable>)`.
 
-As an agent, if you do not know which model to use, you should use your tools to search for available and appropriate text embedding models compatible with the `google_ml_integration` extension (e.g., by searching for "Cloud SQL google_ml_integration supported models").
+As an agent, if you do not know which model to use, you should use your skills to search for available and appropriate text embedding models compatible with the `google_ml_integration` extension (e.g., by searching for "Cloud SQL google_ml_integration supported models").
 
 When performing similarity searches, remember to cast the result of the `embedding` function to the `vector` type. For example:
 `ORDER BY description_vector <-> embedding(<model_name>, $1)::vector`
diff --git a/README.md b/README.md
index 1bea7d5..3aff45c 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 > [!NOTE]
 > This extension is currently in beta (pre-v1.0), and may see breaking changes until the first stable release (v1.0).
 
-This Gemini CLI extension provides a set of tools to interact with [Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres) instances. It allows you to manage your databases, execute queries, explore schemas, and troubleshoot issues directly from the [Gemini CLI](https://google-gemini.github.io/gemini-cli/), using natural language prompts.
+This Gemini CLI extension provides a set of skills to interact with [Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres) instances. It allows you to manage your databases, execute queries, explore schemas, and troubleshoot issues directly from the [Gemini CLI](https://google-gemini.github.io/gemini-cli/), using natural language prompts.
 
 Learn more about [Gemini CLI Extensions](https://github.com/google-gemini/gemini-cli/blob/main/docs/extensions/index.md).
 > [!IMPORTANT]
@@ -58,7 +58,7 @@ You will be prompted to configure the following settings during installation. Th
 *   `CLOUD_SQL_POSTGRES_IP_TYPE`: (Optional) Type of the IP address: `PUBLIC`, `PRIVATE`, or `PSC`. Defaults to `PUBLIC`.
 
 > [!NOTE]
-> This configuration is primarily for the Data Plane tools (querying). The Admin toolset does not strictly require these to be pre-set if you provide them in your prompts, but it is recommended for a smoother experience.
+> This configuration is primarily for the Data Plane skills (querying). The Admin skillset does not strictly require these to be pre-set if you provide them in your prompts, but it is recommended for a smoother experience.
 
 To view or update your configuration:
 
@@ -87,7 +87,7 @@ export CLOUD_SQL_POSTGRES_IP_TYPE="PUBLIC" # Optional: `PUBLIC`, `PRIVATE`, `PSC
 > [!NOTE]
 > * Ensure [Application Default Credentials](https://cloud.google.com/docs/authentication/gcloud) are available in your environment.
 > * If your Cloud SQL for PostgreSQL instance uses private IPs, you must run Gemini CLI in the same Virtual Private Cloud (VPC) network.
-> * See [Troubleshooting](#troubleshooting) for debugging your configuration. 
+> * See [Troubleshooting](#troubleshooting) for debugging your configuration.
 
 ### Start Gemini CLI
 
@@ -116,43 +116,12 @@ Interact with Cloud SQL for PostgreSQL using natural language:
 * **Generate Code:**
   * "Generate a Python dataclass to represent the 'customers' table."
 
-## Supported Tools
-
-* **Admin:**
-    * `clone_instance`: Creates a clone for an existing Cloud SQL for PostgreSQL instance.
-    * `create_backup`: Creates a backup on a Cloud SQL instance.
-   	* `create_instance`: Use this tool to create an Postgres instance.
-   	* `create_user`: Use this tool to create Postgres-BUILT-IN or IAM-based users.
-    * `create_database`: Creates a new database in a Cloud SQL instance.
-   	* `get_instance`: Use this tool to get details about an Postgres instance.
-   	* `list_instances`: Use this tool to list instances in a given project and location.
-    * `list_databases`: Lists all databases for a Cloud SQL instance.
-    * `restore_backup`: Restores a backup of a Cloud SQL instance.
-    * `wait_for_operation`: Use this tool to poll the operations API until the operation is done.
-
-* **Data:**
-    * `list_tables`: Use this tool to lists tables in the database.
-    * `database_overview`: Use this tool to fetches the current state of the PostgreSQL server.
-    * `execute_sql`: Use this tool to executes a SQL query.
-    * `list_active_queries`: Use this tool to list currently running queries.
-    * `list_available_extensions`: Use this tool to list available extensions for installation.
-    * `list_installed_extensions`: Use this tool to list installed extensions.
-    * `get_query_plan`: Use this tool to get query plan.
-    * `list_autovacuum_configurations`: Use this tool to list autovacuum configurations and its value.
-    * `list_database_stats`: Use this tool to lists the key performance and activity statistics for each database in the postgreSQL instance.
-    * `list_indexes`: Use this tool to list available user indexes in a PostgreSQL database.
-    * `list_memory_configurations`: Use this tool to list memory configurations and its value.
-    * `list_pg_settings`: Use this tool to list configuration parameters for the PostgreSQL server.
-    * `list_publication_tables`: Use this tool to list publication tables in a PostgreSQL database.
-    * `list_replication_slots`: Use this tool to list replication slots.
-    * `list_roles`: Use this tool to lists all the user-created roles in PostgreSQL database.
-    * `list_schemas`: Use this tool to lists schemas in the database.
-    * `list_sequences`: Use this tool to list sequences in a PostgreSQL database.
-    * `list_tablespaces`: Use this tool to lists tablespaces in the database.
-    * `list_top_bloated_tables`: Use this tool to list top bloated tables.
-    * `list_triggers`: Use this tool to lists triggers in the database.
-    * `list_views`: Use this tool to lists views in the database from pg_views with a default limit of 50 rows.
-    * `list_invalid_indexes`: Use this tool to list invalid indexes.
+## Supported Skills
+
+This extension provides the following skills:
+
+* [Cloud SQL for PostgreSQL Admin](skills/cloudsql-postgres-admin/SKILL.md) - Manage Cloud SQL instances, databases, and users.
+* [Cloud SQL for PostgreSQL](skills/cloudsql-postgres/SKILL.md) - Query databases and manage extensions.
 
 ## Additional Extensions
 
diff --git a/gemini-extension.json b/gemini-extension.json
index 3c10d49..77b4cbb 100644
--- a/gemini-extension.json
+++ b/gemini-extension.json
@@ -2,24 +2,6 @@
   "name": "cloud-sql-postgresql",
   "version": "0.1.10",
   "description": "Create, connect, and interact with a Cloud SQL for PostgreSQL database and data.",
-  "mcpServers": {
-    "cloud_sql_postgresql_admin": {
-      "command": "${extensionPath}${/}toolbox",
-      "args": [
-        "--prebuilt",
-        "cloud-sql-postgres-admin",
-        "--stdio"
-      ]
-    },
-    "cloud_sql_postgresql": {
-      "command": "${extensionPath}${/}toolbox",
-      "args": [
-        "--prebuilt",
-        "cloud-sql-postgres",
-        "--stdio"
-      ]
-    }
-  },
   "contextFileName": "CLOUD-SQL-POSTGRESQL.md",
   "settings": [
     {
@@ -45,17 +27,21 @@
     {
       "name": "User",
       "description": "(Optional) Username of the database user (Default: IAM user)",
-      "envVar": "CLOUD_SQL_POSTGRES_USER"
+      "envVar": "CLOUD_SQL_POSTGRES_USER",
+      "required": false
     },
     {
       "name": "Password",
       "description": "(Optional) Password of the database user  (Default: IAM user)",
-      "envVar": "CLOUD_SQL_POSTGRES_PASSWORD"
+      "envVar": "CLOUD_SQL_POSTGRES_PASSWORD",
+      "required": false
     },
     {
       "name": "IP Type",
       "description": "(Optional) Type of the IP address: PUBLIC, PRIVATE, or PSC (Default: Public)",
-      "envVar": "CLOUD_SQL_POSTGRES_IP_TYPE"
+      "envVar": "CLOUD_SQL_POSTGRES_IP_TYPE",
+      "default": "PUBLIC",
+      "required": false
     }
   ]
 }
diff --git a/skills/cloudsql-postgres/SKILL.md b/skills/cloudsql-postgres/SKILL.md
new file mode 100644
index 0000000..ee1d33f
--- /dev/null
+++ b/skills/cloudsql-postgres/SKILL.md
@@ -0,0 +1,704 @@
+---
+name: cloudsql-postgres
+description: skill for running tool operations in CloudSql postgres
+---
+
+## Usage
+
+All scripts can be executed using Node.js. Replace `<param_name>` and `<param_value>` with actual values.
+
+**Bash:**
+`node scripts/<script_name>.js '{"<param_name>": "<param_value>"}'`
+
+**PowerShell:**
+`node scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
+
+## Scripts
+
+
+### database_overview
+
+Fetches the current state of the PostgreSQL server, returning the version, whether it's a replica, uptime duration, maximum connection limit, number of current connections, number of active connections, and the percentage of connections in use.
+
+
+
+---
+
+### execute_sql
+
+Use this tool to execute sql.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "sql": {
+      "description": "The sql to execute.",
+      "type": "string"
+    }
+  },
+  "required": [
+    "sql"
+  ],
+  "type": "object"
+}
+```
+
+---
+
+### get_column_cardinality
+
+Estimates the number of unique values (cardinality) quickly for one or all columns in a specific PostgreSQL table by using the database's internal statistics, returning the results in descending order of estimated cardinality. Please run ANALYZE on the table before using this tool to get accurate results. The tool returns the column_name and the estimated_cardinality. If the column_name is not provided, the tool returns all columns along with their estimated cardinality.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "column_name": {
+      "description": "Optional: The column name for which the cardinality is to be found. If not provided, cardinality for all columns will be returned.",
+      "type": "string"
+    },
+    "schema_name": {
+      "default": "public",
+      "description": "Optional: The schema name in which the table is present.",
+      "type": "string"
+    },
+    "table_name": {
+      "description": "Required: The table name in which the column is present.",
+      "type": "string"
+    }
+  },
+  "required": [
+    "table_name"
+  ],
+  "type": "object"
+}
+```
+
+---
+
+### get_query_plan
+
+Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—without executing it. This returns the optimizer's estimated plan, costs, and rows (no ANALYZE, no extra options). Use in production safely for plan inspection, regression checks, and query tuning workflows.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "query": {
+      "description": "The SQL statement for which you want to generate plan (omit the EXPLAIN keyword).",
+      "type": "string"
+    }
+  },
+  "required": [
+    "query"
+  ],
+  "type": "object"
+}
+```
+
+---
+
+### list_active_queries
+
+List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "exclude_application_names": {
+      "default": "",
+      "description": "Optional: A comma-separated list of application names to exclude from the query results. This is useful for filtering out queries from specific applications (e.g., 'psql', 'pgAdmin', 'DBeaver'). The match is case-sensitive. Whitespace around commas and names is automatically handled. If this parameter is omitted, no applications are excluded.",
+      "type": "string"
+    },
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "min_duration": {
+      "default": "1 minute",
+      "description": "Optional: Only show queries running at least this long (e.g., '1 minute', '1 second', '2 seconds').",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_autovacuum_configurations
+
+List PostgreSQL autovacuum-related configurations (name and current setting) from pg_settings.
+
+
+
+---
+
+### list_available_extensions
+
+Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description.
+
+
+
+---
+
+### list_database_stats
+
+
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "database_name": {
+      "default": "",
+      "description": "Optional: A specific database name pattern to search for.",
+      "type": "string"
+    },
+    "database_owner": {
+      "default": "",
+      "description": "Optional: A specific database owner name pattern to search for.",
+      "type": "string"
+    },
+    "default_tablespace": {
+      "default": "",
+      "description": "Optional: A specific default tablespace name pattern to search for.",
+      "type": "string"
+    },
+    "include_templates": {
+      "default": false,
+      "description": "Optional: Whether to include template databases in the results.",
+      "type": "boolean"
+    },
+    "limit": {
+      "default": 10,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "order_by": {
+      "default": "",
+      "description": "Optional: The field to order the results by. Valid values are 'size' and 'commit'.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_indexes
+
+Lists available user indexes in the database, excluding system schemas (pg_catalog, information_schema). For each index, the following properties are returned: schema name, table name, index name, index type (access method), a boolean indicating if it's a unique index, a boolean indicating if it's for a primary key, the index definition, index size in bytes, the number of index scans, the number of index tuples read, the number of table tuples fetched via index scans, and a boolean indicating if the index has been used at least once.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "index_name": {
+      "default": "",
+      "description": "Optional: a text to filter results by index name. The input is used within a LIKE clause.",
+      "type": "string"
+    },
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return. Default is 50",
+      "type": "integer"
+    },
+    "only_unused": {
+      "default": false,
+      "description": "Optional: If true, only returns indexes that have never been used.",
+      "type": "boolean"
+    },
+    "schema_name": {
+      "default": "",
+      "description": "Optional: a text to filter results by schema name. The input is used within a LIKE clause.",
+      "type": "string"
+    },
+    "table_name": {
+      "default": "",
+      "description": "Optional: a text to filter results by table name. The input is used within a LIKE clause.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_installed_extensions
+
+List all installed PostgreSQL extensions with their name, version, schema, owner, and description.
+
+
+
+---
+
+### list_invalid_indexes
+
+Lists all invalid PostgreSQL indexes which are taking up disk space but are unusable by the query planner. Typically created by failed CREATE INDEX CONCURRENTLY operations.
+
+
+
+---
+
+### list_locks
+
+Identifies all locks held by active processes showing the process ID, user, query text, and an aggregated list of all transactions and specific locks (relation, mode, grant status) associated with each process.
+
+
+
+---
+
+### list_memory_configurations
+
+List PostgreSQL memory-related configurations (name and current setting) from pg_settings.
+
+
+
+---
+
+### list_pg_settings
+
+
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "setting_name": {
+      "default": "",
+      "description": "Optional: A specific configuration parameter name pattern to search for.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_publication_tables
+
+
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "publication_names": {
+      "default": "",
+      "description": "Optional: Filters by a comma-separated list of publication names.",
+      "type": "string"
+    },
+    "schema_names": {
+      "default": "",
+      "description": "Optional: Filters by a comma-separated list of schema names.",
+      "type": "string"
+    },
+    "table_names": {
+      "default": "",
+      "description": "Optional: Filters by a comma-separated list of table names.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_query_stats
+
+Lists performance statistics for executed queries ordered by total time, filtering by database name pattern if provided. This tool requires the pg_stat_statements extension to be installed. The tool returns the database name, query text, execution count, timing metrics (total, min, max, mean), rows affected, and buffer cache I/O statistics (hits and reads).
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "database_name": {
+      "default": "",
+      "description": "Optional: The database name to list query stats for.",
+      "type": "string"
+    },
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of results to return. Defaults to 50.",
+      "type": "integer"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_replication_slots
+
+List key details for all PostgreSQL replication slots (e.g., type, database, active status) and calculates the size of the outstanding WAL that is being prevented from removal by the slot.
+
+
+
+---
+
+### list_roles
+
+Lists all the user-created roles in the instance . It returns the role name, Object ID, the maximum number of concurrent connections the role can make, along with boolean indicators for: superuser status, privilege inheritance from member roles, ability to create roles, ability to create databases, ability to log in, replication privilege, and the ability to bypass row-level security, the password expiration timestamp, a list of direct members belonging to this role, and a list of other roles/groups that this role is a member of.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return. Default is 10",
+      "type": "integer"
+    },
+    "role_name": {
+      "default": "",
+      "description": "Optional: a text to filter results by role name. The input is used within a LIKE clause.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_schemas
+
+Lists all schemas in the database ordered by schema name and excluding system and temporary schemas. It returns the schema name, schema owner, grants, number of functions, number of tables and number of views within each schema.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 10,
+      "description": "Optional: The maximum number of schemas to return.",
+      "type": "integer"
+    },
+    "owner": {
+      "default": "",
+      "description": "Optional: A specific schema owner name pattern to search for.",
+      "type": "string"
+    },
+    "schema_name": {
+      "default": "",
+      "description": "Optional: A specific schema name pattern to search for.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_sequences
+
+Lists sequences in the database. Returns sequence name, schema name, sequence owner, data type of the sequence, starting value, minimum value, maximum value of the sequence, the value by which the sequence is incremented, and the last value generated by the sequence in the current session
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return. Default is 50",
+      "type": "integer"
+    },
+    "schema_name": {
+      "default": "",
+      "description": "Optional: A specific schema name pattern to search for.",
+      "type": "string"
+    },
+    "sequence_name": {
+      "default": "",
+      "description": "Optional: A specific sequence name pattern to search for.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_stored_procedure
+
+Retrieves stored procedure metadata returning schema name, procedure name, procedure owner, language, definition, and description, filtered by optional role name (procedure owner), schema name, and limit (default 20).
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 20,
+      "description": "Optional: The maximum number of stored procedures to return. Defaults to 20.",
+      "type": "integer"
+    },
+    "role_name": {
+      "description": "Optional: The owner name to filter the stored procedures by. Defaults to NULL.",
+      "type": "string"
+    },
+    "schema_name": {
+      "description": "Optional: The schema name to filter the stored procedures by. Defaults to NULL.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_table_stats
+
+Lists the user table statistics in the database ordered by number of
+        sequential scans with a default limit of 50 rows. Returns the following
+        columns: schema name, table name, table size in bytes, number of
+        sequential scans, number of index scans, idx_scan_ratio_percent (showing
+        the percentage of total scans that utilized an index, where a low ratio
+        indicates missing or ineffective indexes), number of live rows, number
+        of dead rows, dead_row_ratio_percent (indicating potential table bloat),
+        total number of rows inserted, updated, and deleted, the timestamps
+        for the last_vacuum, last_autovacuum, and last_autoanalyze operations.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of results to return",
+      "type": "integer"
+    },
+    "owner": {
+      "description": "Optional: A specific owner to filter by",
+      "type": "string"
+    },
+    "schema_name": {
+      "default": "public",
+      "description": "Optional: A specific schema name to filter by",
+      "type": "string"
+    },
+    "sort_by": {
+      "description": "Optional: The column to sort by",
+      "type": "string"
+    },
+    "table_name": {
+      "description": "Optional: A specific table name to filter by",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_tables
+
+Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "output_format": {
+      "default": "detailed",
+      "description": "Optional: Use 'simple' for names only or 'detailed' for full info.",
+      "type": "string"
+    },
+    "table_names": {
+      "default": "",
+      "description": "Optional: A comma-separated list of table names. If empty, details for all tables will be listed.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_tablespaces
+
+
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "tablespace_name": {
+      "default": "",
+      "description": "Optional: a text to filter results by tablespace name. The input is used within a LIKE clause.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_top_bloated_tables
+
+List the top tables by dead-tuple (approximate bloat signal), returning schema, table, live/dead tuples, percentage, and last vacuum/analyze times.
+
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "The maximum number of results to return.",
+      "type": "integer"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_triggers
+
+Lists all non-internal triggers in a database. Returns trigger name, schema name, table name, whether its enabled or disabled, timing (e.g BEFORE/AFTER of the event), the  events that cause the trigger to fire such as INSERT, UPDATE, or DELETE, whether the trigger activates per ROW or per STATEMENT, the handler function executed by the trigger and full definition.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "schema_name": {
+      "default": "",
+      "description": "Optional: A specific schema name pattern to search for.",
+      "type": "string"
+    },
+    "table_name": {
+      "default": "",
+      "description": "Optional: A specific table name pattern to search for.",
+      "type": "string"
+    },
+    "trigger_name": {
+      "default": "",
+      "description": "Optional: A specific trigger name pattern to search for.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### list_views
+
+Lists views in the database from pg_views with a default limit of 50 rows. Returns schemaname, viewname, ownername and the definition.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 50,
+      "description": "Optional: The maximum number of rows to return.",
+      "type": "integer"
+    },
+    "schema_name": {
+      "default": "",
+      "description": "Optional: A specific schema name to search for.",
+      "type": "string"
+    },
+    "view_name": {
+      "default": "",
+      "description": "Optional: A specific view name to search for.",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### long_running_transactions
+
+Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string.
+
+#### Parameters
+
+```json
+{
+  "properties": {
+    "limit": {
+      "default": 20,
+      "description": "Optional: The maximum number of long-running transactions to return. Defaults to 20.",
+      "type": "integer"
+    },
+    "min_duration": {
+      "default": "5 minutes",
+      "description": "Optional: Only show transactions running at least this long (e.g., '1 minute', '15 minutes', '30 seconds').",
+      "type": "string"
+    }
+  },
+  "type": "object"
+}
+```
+
+---
+
+### replication_stats
+
+Lists each replica's process ID, user name, application name, backend_xmin (standby's xmin horizon reported by hot_standby_feedback), client IP address, connection state, and sync_state, along with lag sizes in bytes for sent_lag (primary to sent), write_lag (sent to written), flush_lag (written to flushed), replay_lag (flushed to replayed), and the overall total_lag (primary to replayed).
+
+
+
+---
+
diff --git a/skills/cloudsql-postgres/assets/database_overview.yaml b/skills/cloudsql-postgres/assets/database_overview.yaml
new file mode 100644
index 0000000..58e4d20
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/database_overview.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: database_overview
+type: postgres-database-overview
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/execute_sql.yaml b/skills/cloudsql-postgres/assets/execute_sql.yaml
new file mode 100644
index 0000000..d30572e
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/execute_sql.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: execute_sql
+type: postgres-execute-sql
+source: cloudsql-pg-source
+description: Use this tool to execute sql.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/get_column_cardinality.yaml b/skills/cloudsql-postgres/assets/get_column_cardinality.yaml
new file mode 100644
index 0000000..554989d
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/get_column_cardinality.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: get_column_cardinality
+type: postgres-get-column-cardinality
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/get_query_plan.yaml b/skills/cloudsql-postgres/assets/get_query_plan.yaml
new file mode 100644
index 0000000..72a3041
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/get_query_plan.yaml
@@ -0,0 +1,33 @@
+kind: tools
+name: get_query_plan
+type: postgres-sql
+source: cloudsql-pg-source
+description: Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—without executing it. This returns the optimizer's estimated plan, costs, and rows (no ANALYZE, no extra options). Use in production safely for plan inspection, regression checks, and query tuning workflows.
+statement: |
+  EXPLAIN (FORMAT JSON) {{.query}};
+authRequired: []
+parameters: []
+templateParameters:
+- name: query
+  type: string
+  description: The SQL statement for which you want to generate plan (omit the EXPLAIN keyword).
+  required: true
+  allowedValues: []
+  excludedValues: []
+  authServices: []
+  authSources: []
+  embeddedBy: ""
+  valueFromParam: ""
+  default: null
+  escape: null
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_active_queries.yaml b/skills/cloudsql-postgres/assets/list_active_queries.yaml
new file mode 100644
index 0000000..8cbbd3a
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_active_queries.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_active_queries
+type: postgres-list-active-queries
+source: cloudsql-pg-source
+description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml b/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
new file mode 100644
index 0000000..131c223
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
@@ -0,0 +1,24 @@
+kind: tools
+name: list_autovacuum_configurations
+type: postgres-sql
+source: cloudsql-pg-source
+description: List PostgreSQL autovacuum-related configurations (name and current setting) from pg_settings.
+statement: |
+  SELECT name,
+      setting
+  FROM   pg_settings
+  WHERE  category = 'Autovacuum';
+authRequired: []
+parameters: []
+templateParameters: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_available_extensions.yaml b/skills/cloudsql-postgres/assets/list_available_extensions.yaml
new file mode 100644
index 0000000..bc1e93b
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_available_extensions.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_available_extensions
+type: postgres-list-available-extensions
+source: cloudsql-pg-source
+description: Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_database_stats.yaml b/skills/cloudsql-postgres/assets/list_database_stats.yaml
new file mode 100644
index 0000000..4c14b32
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_database_stats.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_database_stats
+type: postgres-list-database-stats
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_indexes.yaml b/skills/cloudsql-postgres/assets/list_indexes.yaml
new file mode 100644
index 0000000..bc289cb
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_indexes.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_indexes
+type: postgres-list-indexes
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_installed_extensions.yaml b/skills/cloudsql-postgres/assets/list_installed_extensions.yaml
new file mode 100644
index 0000000..b2bfac2
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_installed_extensions.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_installed_extensions
+type: postgres-list-installed-extensions
+source: cloudsql-pg-source
+description: List all installed PostgreSQL extensions with their name, version, schema, owner, and description.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml b/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
new file mode 100644
index 0000000..343a0e4
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
@@ -0,0 +1,32 @@
+kind: tools
+name: list_invalid_indexes
+type: postgres-sql
+source: cloudsql-pg-source
+description: Lists all invalid PostgreSQL indexes which are taking up disk space but are unusable by the query planner. Typically created by failed CREATE INDEX CONCURRENTLY operations.
+statement: |
+  SELECT
+      nspname AS schema_name,
+      indexrelid::regclass AS index_name,
+      indrelid::regclass AS table_name,
+      pg_size_pretty(pg_total_relation_size(indexrelid)) AS index_size,
+      indisready,
+      indisvalid,
+      pg_get_indexdef(pg_class.oid) AS index_def
+  FROM pg_index
+  JOIN pg_class ON pg_class.oid = pg_index.indexrelid
+  JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
+  WHERE indisvalid = FALSE;
+authRequired: []
+parameters: []
+templateParameters: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_locks.yaml b/skills/cloudsql-postgres/assets/list_locks.yaml
new file mode 100644
index 0000000..4fb9e11
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_locks.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_locks
+type: postgres-list-locks
+source: cloudsql-pg-source
+description: Identifies all locks held by active processes showing the process ID, user, query text, and an aggregated list of all transactions and specific locks (relation, mode, grant status) associated with each process.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_memory_configurations.yaml b/skills/cloudsql-postgres/assets/list_memory_configurations.yaml
new file mode 100644
index 0000000..ac32e75
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_memory_configurations.yaml
@@ -0,0 +1,36 @@
+kind: tools
+name: list_memory_configurations
+type: postgres-sql
+source: cloudsql-pg-source
+description: List PostgreSQL memory-related configurations (name and current setting) from pg_settings.
+statement: |
+  (
+      SELECT
+      name,
+      pg_size_pretty((setting::bigint * 1024)::bigint) setting
+      FROM pg_settings
+      WHERE name IN ('work_mem', 'maintenance_work_mem')
+  )
+  UNION ALL
+  (
+      SELECT
+      name,
+      pg_size_pretty((((setting::bigint) * 8) * 1024)::bigint)
+      FROM pg_settings
+      WHERE name IN ('shared_buffers', 'wal_buffers', 'effective_cache_size', 'temp_buffers')
+  )
+  ORDER BY 1 DESC;
+authRequired: []
+parameters: []
+templateParameters: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_pg_settings.yaml b/skills/cloudsql-postgres/assets/list_pg_settings.yaml
new file mode 100644
index 0000000..3b89368
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_pg_settings.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_pg_settings
+type: postgres-list-pg-settings
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_publication_tables.yaml b/skills/cloudsql-postgres/assets/list_publication_tables.yaml
new file mode 100644
index 0000000..2d2d451
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_publication_tables.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_publication_tables
+type: postgres-list-publication-tables
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_query_stats.yaml b/skills/cloudsql-postgres/assets/list_query_stats.yaml
new file mode 100644
index 0000000..52ff91c
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_query_stats.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_query_stats
+type: postgres-list-query-stats
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_replication_slots.yaml b/skills/cloudsql-postgres/assets/list_replication_slots.yaml
new file mode 100644
index 0000000..870eebe
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_replication_slots.yaml
@@ -0,0 +1,33 @@
+kind: tools
+name: list_replication_slots
+type: postgres-sql
+source: cloudsql-pg-source
+description: List key details for all PostgreSQL replication slots (e.g., type, database, active status) and calculates the size of the outstanding WAL that is being prevented from removal by the slot.
+statement: |
+  SELECT
+  slot_name,
+  slot_type,
+  plugin,
+  database,
+  temporary,
+  active,
+  restart_lsn,
+  confirmed_flush_lsn,
+  xmin,
+  catalog_xmin,
+  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal
+  FROM pg_replication_slots;
+authRequired: []
+parameters: []
+templateParameters: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_roles.yaml b/skills/cloudsql-postgres/assets/list_roles.yaml
new file mode 100644
index 0000000..05b4e5d
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_roles.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_roles
+type: postgres-list-roles
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_schemas.yaml b/skills/cloudsql-postgres/assets/list_schemas.yaml
new file mode 100644
index 0000000..d76f1b7
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_schemas.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_schemas
+type: postgres-list-schemas
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_sequences.yaml b/skills/cloudsql-postgres/assets/list_sequences.yaml
new file mode 100644
index 0000000..1e99528
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_sequences.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_sequences
+type: postgres-list-sequences
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_stored_procedure.yaml b/skills/cloudsql-postgres/assets/list_stored_procedure.yaml
new file mode 100644
index 0000000..0e9d9ee
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_stored_procedure.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_stored_procedure
+type: postgres-list-stored-procedure
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_table_stats.yaml b/skills/cloudsql-postgres/assets/list_table_stats.yaml
new file mode 100644
index 0000000..b97908c
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_table_stats.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_table_stats
+type: postgres-list-table-stats
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_tables.yaml b/skills/cloudsql-postgres/assets/list_tables.yaml
new file mode 100644
index 0000000..49d7cb0
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_tables.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_tables
+type: postgres-list-tables
+source: cloudsql-pg-source
+description: Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_tablespaces.yaml b/skills/cloudsql-postgres/assets/list_tablespaces.yaml
new file mode 100644
index 0000000..e3a4cd6
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_tablespaces.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_tablespaces
+type: postgres-list-tablespaces
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml b/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
new file mode 100644
index 0000000..f2cca0a
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
@@ -0,0 +1,47 @@
+kind: tools
+name: list_top_bloated_tables
+type: postgres-sql
+source: cloudsql-pg-source
+description: |
+  List the top tables by dead-tuple (approximate bloat signal), returning schema, table, live/dead tuples, percentage, and last vacuum/analyze times.
+statement: |
+  SELECT
+      schemaname AS schema_name,
+      relname AS relation_name,
+      n_live_tup AS live_tuples,
+      n_dead_tup AS dead_tuples,
+      TRUNC((n_dead_tup::NUMERIC / NULLIF(n_live_tup + n_dead_tup, 0)) * 100, 2) AS dead_tuple_percentage,
+      last_vacuum,
+      last_autovacuum,
+      last_analyze,
+      last_autoanalyze
+  FROM pg_stat_user_tables
+  ORDER BY n_dead_tup DESC
+  LIMIT COALESCE($1::int, 50);
+authRequired: []
+parameters:
+- name: limit
+  type: integer
+  description: The maximum number of results to return.
+  required: null
+  allowedValues: []
+  excludedValues: []
+  authServices: []
+  authSources: []
+  embeddedBy: ""
+  valueFromParam: ""
+  default: 50
+  minValue: null
+  maxValue: null
+templateParameters: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_triggers.yaml b/skills/cloudsql-postgres/assets/list_triggers.yaml
new file mode 100644
index 0000000..4307890
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_triggers.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_triggers
+type: postgres-list-triggers
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_views.yaml b/skills/cloudsql-postgres/assets/list_views.yaml
new file mode 100644
index 0000000..ea8fa2e
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/list_views.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: list_views
+type: postgres-list-views
+source: cloudsql-pg-source
+description: ""
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/long_running_transactions.yaml b/skills/cloudsql-postgres/assets/long_running_transactions.yaml
new file mode 100644
index 0000000..f88d46e
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/long_running_transactions.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: long_running_transactions
+type: postgres-long-running-transactions
+source: cloudsql-pg-source
+description: Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string.
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/replication_stats.yaml b/skills/cloudsql-postgres/assets/replication_stats.yaml
new file mode 100644
index 0000000..197d3fc
--- /dev/null
+++ b/skills/cloudsql-postgres/assets/replication_stats.yaml
@@ -0,0 +1,17 @@
+kind: tools
+name: replication_stats
+type: postgres-replication-stats
+source: cloudsql-pg-source
+description: Lists each replica's process ID, user name, application name, backend_xmin (standby's xmin horizon reported by hot_standby_feedback), client IP address, connection state, and sync_state, along with lag sizes in bytes for sent_lag (primary to sent), write_lag (sent to written), flush_lag (written to flushed), replay_lag (flushed to replayed), and the overall total_lag (primary to replayed).
+authRequired: []
+---
+kind: sources
+name: cloudsql-pg-source
+type: cloud-sql-postgres
+project: ${CLOUD_SQL_POSTGRES_PROJECT}
+region: ${CLOUD_SQL_POSTGRES_REGION}
+instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
+ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
+database: ${CLOUD_SQL_POSTGRES_DATABASE}
+user: ${CLOUD_SQL_POSTGRES_USER}
+password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/scripts/database_overview.js b/skills/cloudsql-postgres/scripts/database_overview.js
new file mode 100755
index 0000000..b3b050d
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/database_overview.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "database_overview";
+const toolsFileName = "database_overview.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/execute_sql.js b/skills/cloudsql-postgres/scripts/execute_sql.js
new file mode 100755
index 0000000..fb01efe
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/execute_sql.js
@@ -0,0 +1,53 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "execute_sql";
+const toolsFileName = "execute_sql.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/get_column_cardinality.js b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
new file mode 100755
index 0000000..5bf2bea
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "get_column_cardinality";
+const toolsFileName = "get_column_cardinality.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/get_query_plan.js b/skills/cloudsql-postgres/scripts/get_query_plan.js
new file mode 100755
index 0000000..e95a906
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/get_query_plan.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "get_query_plan";
+const toolsFileName = "get_query_plan.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_active_queries.js b/skills/cloudsql-postgres/scripts/list_active_queries.js
new file mode 100755
index 0000000..35e4f95
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_active_queries.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_active_queries";
+const toolsFileName = "list_active_queries.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
new file mode 100755
index 0000000..737129e
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_autovacuum_configurations";
+const toolsFileName = "list_autovacuum_configurations.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_available_extensions.js b/skills/cloudsql-postgres/scripts/list_available_extensions.js
new file mode 100755
index 0000000..4ec3142
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_available_extensions.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_available_extensions";
+const toolsFileName = "list_available_extensions.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_database_stats.js b/skills/cloudsql-postgres/scripts/list_database_stats.js
new file mode 100755
index 0000000..94f5da8
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_database_stats.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_database_stats";
+const toolsFileName = "list_database_stats.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_indexes.js b/skills/cloudsql-postgres/scripts/list_indexes.js
new file mode 100755
index 0000000..0e490d4
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_indexes.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_indexes";
+const toolsFileName = "list_indexes.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_installed_extensions.js b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
new file mode 100755
index 0000000..e568b53
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_installed_extensions";
+const toolsFileName = "list_installed_extensions.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
new file mode 100755
index 0000000..409c154
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_invalid_indexes";
+const toolsFileName = "list_invalid_indexes.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_locks.js b/skills/cloudsql-postgres/scripts/list_locks.js
new file mode 100755
index 0000000..352623a
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_locks.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_locks";
+const toolsFileName = "list_locks.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_memory_configurations.js b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
new file mode 100755
index 0000000..3f30626
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_memory_configurations";
+const toolsFileName = "list_memory_configurations.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_pg_settings.js b/skills/cloudsql-postgres/scripts/list_pg_settings.js
new file mode 100755
index 0000000..5a169b0
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_pg_settings.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_pg_settings";
+const toolsFileName = "list_pg_settings.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_publication_tables.js b/skills/cloudsql-postgres/scripts/list_publication_tables.js
new file mode 100755
index 0000000..79eb5bf
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_publication_tables.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_publication_tables";
+const toolsFileName = "list_publication_tables.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_query_stats.js b/skills/cloudsql-postgres/scripts/list_query_stats.js
new file mode 100755
index 0000000..7f74a1d
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_query_stats.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_query_stats";
+const toolsFileName = "list_query_stats.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_replication_slots.js b/skills/cloudsql-postgres/scripts/list_replication_slots.js
new file mode 100755
index 0000000..6f7ee52
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_replication_slots.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_replication_slots";
+const toolsFileName = "list_replication_slots.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_roles.js b/skills/cloudsql-postgres/scripts/list_roles.js
new file mode 100755
index 0000000..c044adf
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_roles.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_roles";
+const toolsFileName = "list_roles.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_schemas.js b/skills/cloudsql-postgres/scripts/list_schemas.js
new file mode 100755
index 0000000..d0a4fa0
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_schemas.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_schemas";
+const toolsFileName = "list_schemas.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_sequences.js b/skills/cloudsql-postgres/scripts/list_sequences.js
new file mode 100755
index 0000000..8d4123a
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_sequences.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_sequences";
+const toolsFileName = "list_sequences.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_stored_procedure.js b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
new file mode 100755
index 0000000..380487a
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_stored_procedure";
+const toolsFileName = "list_stored_procedure.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_table_stats.js b/skills/cloudsql-postgres/scripts/list_table_stats.js
new file mode 100755
index 0000000..5c7330d
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_table_stats.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_table_stats";
+const toolsFileName = "list_table_stats.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_tables.js b/skills/cloudsql-postgres/scripts/list_tables.js
new file mode 100755
index 0000000..fe701e9
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_tables.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_tables";
+const toolsFileName = "list_tables.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_tablespaces.js b/skills/cloudsql-postgres/scripts/list_tablespaces.js
new file mode 100755
index 0000000..913204a
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_tablespaces.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_tablespaces";
+const toolsFileName = "list_tablespaces.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
new file mode 100755
index 0000000..e15e880
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_top_bloated_tables";
+const toolsFileName = "list_top_bloated_tables.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_triggers.js b/skills/cloudsql-postgres/scripts/list_triggers.js
new file mode 100755
index 0000000..9280eba
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_triggers.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_triggers";
+const toolsFileName = "list_triggers.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/list_views.js b/skills/cloudsql-postgres/scripts/list_views.js
new file mode 100755
index 0000000..350e089
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/list_views.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "list_views";
+const toolsFileName = "list_views.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/load_env.js b/skills/cloudsql-postgres/scripts/load_env.js
new file mode 100644
index 0000000..30b571d
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/load_env.js
@@ -0,0 +1,75 @@
+const fs = require('fs');
+const path = require('path');
+const os = require('os');
+
+function loadEnv() {
+  try {
+    // Check if a local .env exists in the current working directory of the project
+    const localEnvPath = path.resolve(process.cwd(), '.env');
+    if (fs.existsSync(localEnvPath)) {
+      parseAndSetEnv(localEnvPath);
+    }
+
+    // Resolve the extension name from gemini-extension.json
+    // Fallback to 'cloud-sql-postgresql' if we can't find it
+    let extensionName = 'cloud-sql-postgresql';
+    try {
+      const projectRoot = path.resolve(__dirname, '../../..');
+      const manifestPath = path.join(projectRoot, 'gemini-extension.json');
+      if (fs.existsSync(manifestPath)) {
+        const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
+        if (manifest.name) {
+          extensionName = manifest.name;
+        }
+      }
+    } catch (e) {
+      // Ignore parsing errors, fallback is fine
+    }
+
+    // Load from ~/.gemini/extensions/<name>/.env
+    const homeDir = os.homedir();
+    const geminiEnvPath = path.join(homeDir, '.gemini', 'extensions', extensionName, '.env');
+    if (fs.existsSync(geminiEnvPath)) {
+      parseAndSetEnv(geminiEnvPath);
+    }
+  } catch (err) {
+    console.error("Warning: Failed to load extension environment variables:", err.message);
+  }
+}
+
+function parseAndSetEnv(envPath) {
+  const envFileContent = fs.readFileSync(envPath, 'utf8');
+  const lines = envFileContent.split(/\r?\n/);
+  
+  for (const line of lines) {
+    const trimmedLine = line.trim();
+    // Ignore empty lines and comments
+    if (!trimmedLine || trimmedLine.startsWith('#')) {
+      continue;
+    }
+    
+    // Parse KEY=VALUE
+    const equalSignIndex = trimmedLine.indexOf('=');
+    if (equalSignIndex === -1) {
+      continue;
+    }
+    
+    const key = trimmedLine.substring(0, equalSignIndex).trim();
+    let value = trimmedLine.substring(equalSignIndex + 1).trim();
+    
+    // Remove surrounding quotes if present
+    if (value.startsWith('"') && value.endsWith('"')) {
+      value = value.substring(1, value.length - 1);
+    } else if (value.startsWith("'") && value.endsWith("'")) {
+      value = value.substring(1, value.length - 1);
+    }
+    
+    // Set if not already defined in process.env
+    if (key && process.env[key] === undefined) {
+      process.env[key] = value;
+    }
+  }
+}
+
+// Execute immediately when required
+loadEnv();
diff --git a/skills/cloudsql-postgres/scripts/long_running_transactions.js b/skills/cloudsql-postgres/scripts/long_running_transactions.js
new file mode 100755
index 0000000..bc22b59
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/long_running_transactions.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "long_running_transactions";
+const toolsFileName = "long_running_transactions.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres/scripts/replication_stats.js b/skills/cloudsql-postgres/scripts/replication_stats.js
new file mode 100755
index 0000000..ba06322
--- /dev/null
+++ b/skills/cloudsql-postgres/scripts/replication_stats.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+require('./load_env.js');
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+
+const toolName = "replication_stats";
+const toolsFileName = "replication_stats.yaml";
+
+function getToolboxPath() {
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+    } catch (e) {
+        // Ignore error;
+    }
+    const localPath = path.resolve(__dirname, '../../../toolbox');
+    if (fs.existsSync(localPath)) {
+        return localPath;
+    }
+    throw new Error("Toolbox binary not found");
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+let configArgs = [];
+if (toolsFileName) {
+  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});

From 2b0cea4872f1f52ec6959dfdb4ac9445492b1da0 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 11:41:14 +0530
Subject: [PATCH 02/13] remove tool yaml files

---
 .../assets/database_overview.yaml             | 17 -------
 .../cloudsql-postgres/assets/execute_sql.yaml | 17 -------
 .../assets/get_column_cardinality.yaml        | 17 -------
 .../assets/get_query_plan.yaml                | 33 -------------
 .../assets/list_active_queries.yaml           | 17 -------
 .../list_autovacuum_configurations.yaml       | 24 ----------
 .../assets/list_available_extensions.yaml     | 17 -------
 .../assets/list_database_stats.yaml           | 17 -------
 .../assets/list_indexes.yaml                  | 17 -------
 .../assets/list_installed_extensions.yaml     | 17 -------
 .../assets/list_invalid_indexes.yaml          | 32 -------------
 .../cloudsql-postgres/assets/list_locks.yaml  | 17 -------
 .../assets/list_memory_configurations.yaml    | 36 --------------
 .../assets/list_pg_settings.yaml              | 17 -------
 .../assets/list_publication_tables.yaml       | 17 -------
 .../assets/list_query_stats.yaml              | 17 -------
 .../assets/list_replication_slots.yaml        | 33 -------------
 .../cloudsql-postgres/assets/list_roles.yaml  | 17 -------
 .../assets/list_schemas.yaml                  | 17 -------
 .../assets/list_sequences.yaml                | 17 -------
 .../assets/list_stored_procedure.yaml         | 17 -------
 .../assets/list_table_stats.yaml              | 17 -------
 .../cloudsql-postgres/assets/list_tables.yaml | 17 -------
 .../assets/list_tablespaces.yaml              | 17 -------
 .../assets/list_top_bloated_tables.yaml       | 47 -------------------
 .../assets/list_triggers.yaml                 | 17 -------
 .../cloudsql-postgres/assets/list_views.yaml  | 17 -------
 .../assets/long_running_transactions.yaml     | 17 -------
 .../assets/replication_stats.yaml             | 17 -------
 29 files changed, 596 deletions(-)
 delete mode 100644 skills/cloudsql-postgres/assets/database_overview.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/execute_sql.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/get_column_cardinality.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/get_query_plan.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_active_queries.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_available_extensions.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_database_stats.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_indexes.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_installed_extensions.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_locks.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_memory_configurations.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_pg_settings.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_publication_tables.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_query_stats.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_replication_slots.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_roles.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_schemas.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_sequences.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_stored_procedure.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_table_stats.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_tables.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_tablespaces.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_triggers.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/list_views.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/long_running_transactions.yaml
 delete mode 100644 skills/cloudsql-postgres/assets/replication_stats.yaml

diff --git a/skills/cloudsql-postgres/assets/database_overview.yaml b/skills/cloudsql-postgres/assets/database_overview.yaml
deleted file mode 100644
index 58e4d20..0000000
--- a/skills/cloudsql-postgres/assets/database_overview.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: database_overview
-type: postgres-database-overview
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/execute_sql.yaml b/skills/cloudsql-postgres/assets/execute_sql.yaml
deleted file mode 100644
index d30572e..0000000
--- a/skills/cloudsql-postgres/assets/execute_sql.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: execute_sql
-type: postgres-execute-sql
-source: cloudsql-pg-source
-description: Use this tool to execute sql.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/get_column_cardinality.yaml b/skills/cloudsql-postgres/assets/get_column_cardinality.yaml
deleted file mode 100644
index 554989d..0000000
--- a/skills/cloudsql-postgres/assets/get_column_cardinality.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: get_column_cardinality
-type: postgres-get-column-cardinality
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/get_query_plan.yaml b/skills/cloudsql-postgres/assets/get_query_plan.yaml
deleted file mode 100644
index 72a3041..0000000
--- a/skills/cloudsql-postgres/assets/get_query_plan.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
-kind: tools
-name: get_query_plan
-type: postgres-sql
-source: cloudsql-pg-source
-description: Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—without executing it. This returns the optimizer's estimated plan, costs, and rows (no ANALYZE, no extra options). Use in production safely for plan inspection, regression checks, and query tuning workflows.
-statement: |
-  EXPLAIN (FORMAT JSON) {{.query}};
-authRequired: []
-parameters: []
-templateParameters:
-- name: query
-  type: string
-  description: The SQL statement for which you want to generate plan (omit the EXPLAIN keyword).
-  required: true
-  allowedValues: []
-  excludedValues: []
-  authServices: []
-  authSources: []
-  embeddedBy: ""
-  valueFromParam: ""
-  default: null
-  escape: null
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_active_queries.yaml b/skills/cloudsql-postgres/assets/list_active_queries.yaml
deleted file mode 100644
index 8cbbd3a..0000000
--- a/skills/cloudsql-postgres/assets/list_active_queries.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_active_queries
-type: postgres-list-active-queries
-source: cloudsql-pg-source
-description: List the top N (default 50) currently running queries (state='active') from pg_stat_activity, ordered by longest-running first. Returns pid, user, database, application_name, client_addr, state, wait_event_type/wait_event, backend/xact/query start times, computed query_duration, and the SQL text.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml b/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
deleted file mode 100644
index 131c223..0000000
--- a/skills/cloudsql-postgres/assets/list_autovacuum_configurations.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-kind: tools
-name: list_autovacuum_configurations
-type: postgres-sql
-source: cloudsql-pg-source
-description: List PostgreSQL autovacuum-related configurations (name and current setting) from pg_settings.
-statement: |
-  SELECT name,
-      setting
-  FROM   pg_settings
-  WHERE  category = 'Autovacuum';
-authRequired: []
-parameters: []
-templateParameters: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_available_extensions.yaml b/skills/cloudsql-postgres/assets/list_available_extensions.yaml
deleted file mode 100644
index bc1e93b..0000000
--- a/skills/cloudsql-postgres/assets/list_available_extensions.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_available_extensions
-type: postgres-list-available-extensions
-source: cloudsql-pg-source
-description: Discover all PostgreSQL extensions available for installation on this server, returning name, default_version, and description.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_database_stats.yaml b/skills/cloudsql-postgres/assets/list_database_stats.yaml
deleted file mode 100644
index 4c14b32..0000000
--- a/skills/cloudsql-postgres/assets/list_database_stats.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_database_stats
-type: postgres-list-database-stats
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_indexes.yaml b/skills/cloudsql-postgres/assets/list_indexes.yaml
deleted file mode 100644
index bc289cb..0000000
--- a/skills/cloudsql-postgres/assets/list_indexes.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_indexes
-type: postgres-list-indexes
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_installed_extensions.yaml b/skills/cloudsql-postgres/assets/list_installed_extensions.yaml
deleted file mode 100644
index b2bfac2..0000000
--- a/skills/cloudsql-postgres/assets/list_installed_extensions.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_installed_extensions
-type: postgres-list-installed-extensions
-source: cloudsql-pg-source
-description: List all installed PostgreSQL extensions with their name, version, schema, owner, and description.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml b/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
deleted file mode 100644
index 343a0e4..0000000
--- a/skills/cloudsql-postgres/assets/list_invalid_indexes.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-kind: tools
-name: list_invalid_indexes
-type: postgres-sql
-source: cloudsql-pg-source
-description: Lists all invalid PostgreSQL indexes which are taking up disk space but are unusable by the query planner. Typically created by failed CREATE INDEX CONCURRENTLY operations.
-statement: |
-  SELECT
-      nspname AS schema_name,
-      indexrelid::regclass AS index_name,
-      indrelid::regclass AS table_name,
-      pg_size_pretty(pg_total_relation_size(indexrelid)) AS index_size,
-      indisready,
-      indisvalid,
-      pg_get_indexdef(pg_class.oid) AS index_def
-  FROM pg_index
-  JOIN pg_class ON pg_class.oid = pg_index.indexrelid
-  JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
-  WHERE indisvalid = FALSE;
-authRequired: []
-parameters: []
-templateParameters: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_locks.yaml b/skills/cloudsql-postgres/assets/list_locks.yaml
deleted file mode 100644
index 4fb9e11..0000000
--- a/skills/cloudsql-postgres/assets/list_locks.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_locks
-type: postgres-list-locks
-source: cloudsql-pg-source
-description: Identifies all locks held by active processes showing the process ID, user, query text, and an aggregated list of all transactions and specific locks (relation, mode, grant status) associated with each process.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_memory_configurations.yaml b/skills/cloudsql-postgres/assets/list_memory_configurations.yaml
deleted file mode 100644
index ac32e75..0000000
--- a/skills/cloudsql-postgres/assets/list_memory_configurations.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-kind: tools
-name: list_memory_configurations
-type: postgres-sql
-source: cloudsql-pg-source
-description: List PostgreSQL memory-related configurations (name and current setting) from pg_settings.
-statement: |
-  (
-      SELECT
-      name,
-      pg_size_pretty((setting::bigint * 1024)::bigint) setting
-      FROM pg_settings
-      WHERE name IN ('work_mem', 'maintenance_work_mem')
-  )
-  UNION ALL
-  (
-      SELECT
-      name,
-      pg_size_pretty((((setting::bigint) * 8) * 1024)::bigint)
-      FROM pg_settings
-      WHERE name IN ('shared_buffers', 'wal_buffers', 'effective_cache_size', 'temp_buffers')
-  )
-  ORDER BY 1 DESC;
-authRequired: []
-parameters: []
-templateParameters: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_pg_settings.yaml b/skills/cloudsql-postgres/assets/list_pg_settings.yaml
deleted file mode 100644
index 3b89368..0000000
--- a/skills/cloudsql-postgres/assets/list_pg_settings.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_pg_settings
-type: postgres-list-pg-settings
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_publication_tables.yaml b/skills/cloudsql-postgres/assets/list_publication_tables.yaml
deleted file mode 100644
index 2d2d451..0000000
--- a/skills/cloudsql-postgres/assets/list_publication_tables.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_publication_tables
-type: postgres-list-publication-tables
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_query_stats.yaml b/skills/cloudsql-postgres/assets/list_query_stats.yaml
deleted file mode 100644
index 52ff91c..0000000
--- a/skills/cloudsql-postgres/assets/list_query_stats.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_query_stats
-type: postgres-list-query-stats
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_replication_slots.yaml b/skills/cloudsql-postgres/assets/list_replication_slots.yaml
deleted file mode 100644
index 870eebe..0000000
--- a/skills/cloudsql-postgres/assets/list_replication_slots.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
-kind: tools
-name: list_replication_slots
-type: postgres-sql
-source: cloudsql-pg-source
-description: List key details for all PostgreSQL replication slots (e.g., type, database, active status) and calculates the size of the outstanding WAL that is being prevented from removal by the slot.
-statement: |
-  SELECT
-  slot_name,
-  slot_type,
-  plugin,
-  database,
-  temporary,
-  active,
-  restart_lsn,
-  confirmed_flush_lsn,
-  xmin,
-  catalog_xmin,
-  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal
-  FROM pg_replication_slots;
-authRequired: []
-parameters: []
-templateParameters: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_roles.yaml b/skills/cloudsql-postgres/assets/list_roles.yaml
deleted file mode 100644
index 05b4e5d..0000000
--- a/skills/cloudsql-postgres/assets/list_roles.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_roles
-type: postgres-list-roles
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_schemas.yaml b/skills/cloudsql-postgres/assets/list_schemas.yaml
deleted file mode 100644
index d76f1b7..0000000
--- a/skills/cloudsql-postgres/assets/list_schemas.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_schemas
-type: postgres-list-schemas
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/assets/list_sequences.yaml b/skills/cloudsql-postgres/assets/list_sequences.yaml
deleted file mode 100644
index 1e99528..0000000
--- a/skills/cloudsql-postgres/assets/list_sequences.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_sequences
-type: postgres-list-sequences
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_stored_procedure.yaml b/skills/cloudsql-postgres/assets/list_stored_procedure.yaml
deleted file mode 100644
index 0e9d9ee..0000000
--- a/skills/cloudsql-postgres/assets/list_stored_procedure.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_stored_procedure
-type: postgres-list-stored-procedure
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_table_stats.yaml b/skills/cloudsql-postgres/assets/list_table_stats.yaml
deleted file mode 100644
index b97908c..0000000
--- a/skills/cloudsql-postgres/assets/list_table_stats.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_table_stats
-type: postgres-list-table-stats
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_tables.yaml b/skills/cloudsql-postgres/assets/list_tables.yaml
deleted file mode 100644
index 49d7cb0..0000000
--- a/skills/cloudsql-postgres/assets/list_tables.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_tables
-type: postgres-list-tables
-source: cloudsql-pg-source
-description: Lists detailed schema information (object type, columns, constraints, indexes, triggers, owner, comment) as JSON for user-created tables (ordinary or partitioned). Filters by a comma-separated list of names. If names are omitted, lists all tables in user schemas.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_tablespaces.yaml b/skills/cloudsql-postgres/assets/list_tablespaces.yaml
deleted file mode 100644
index e3a4cd6..0000000
--- a/skills/cloudsql-postgres/assets/list_tablespaces.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_tablespaces
-type: postgres-list-tablespaces
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml b/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
deleted file mode 100644
index f2cca0a..0000000
--- a/skills/cloudsql-postgres/assets/list_top_bloated_tables.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-kind: tools
-name: list_top_bloated_tables
-type: postgres-sql
-source: cloudsql-pg-source
-description: |
-  List the top tables by dead-tuple (approximate bloat signal), returning schema, table, live/dead tuples, percentage, and last vacuum/analyze times.
-statement: |
-  SELECT
-      schemaname AS schema_name,
-      relname AS relation_name,
-      n_live_tup AS live_tuples,
-      n_dead_tup AS dead_tuples,
-      TRUNC((n_dead_tup::NUMERIC / NULLIF(n_live_tup + n_dead_tup, 0)) * 100, 2) AS dead_tuple_percentage,
-      last_vacuum,
-      last_autovacuum,
-      last_analyze,
-      last_autoanalyze
-  FROM pg_stat_user_tables
-  ORDER BY n_dead_tup DESC
-  LIMIT COALESCE($1::int, 50);
-authRequired: []
-parameters:
-- name: limit
-  type: integer
-  description: The maximum number of results to return.
-  required: null
-  allowedValues: []
-  excludedValues: []
-  authServices: []
-  authSources: []
-  embeddedBy: ""
-  valueFromParam: ""
-  default: 50
-  minValue: null
-  maxValue: null
-templateParameters: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_triggers.yaml b/skills/cloudsql-postgres/assets/list_triggers.yaml
deleted file mode 100644
index 4307890..0000000
--- a/skills/cloudsql-postgres/assets/list_triggers.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_triggers
-type: postgres-list-triggers
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/list_views.yaml b/skills/cloudsql-postgres/assets/list_views.yaml
deleted file mode 100644
index ea8fa2e..0000000
--- a/skills/cloudsql-postgres/assets/list_views.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: list_views
-type: postgres-list-views
-source: cloudsql-pg-source
-description: ""
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/long_running_transactions.yaml b/skills/cloudsql-postgres/assets/long_running_transactions.yaml
deleted file mode 100644
index f88d46e..0000000
--- a/skills/cloudsql-postgres/assets/long_running_transactions.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: long_running_transactions
-type: postgres-long-running-transactions
-source: cloudsql-pg-source
-description: Identifies and lists database transactions that exceed a specified time limit. For each of the long running transactions, the output contains the process id, database name, user name, application name, client address, state, connection age, transaction age, query age, last activity age, wait event type, wait event, and query string.
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}
diff --git a/skills/cloudsql-postgres/assets/replication_stats.yaml b/skills/cloudsql-postgres/assets/replication_stats.yaml
deleted file mode 100644
index 197d3fc..0000000
--- a/skills/cloudsql-postgres/assets/replication_stats.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind: tools
-name: replication_stats
-type: postgres-replication-stats
-source: cloudsql-pg-source
-description: Lists each replica's process ID, user name, application name, backend_xmin (standby's xmin horizon reported by hot_standby_feedback), client IP address, connection state, and sync_state, along with lag sizes in bytes for sent_lag (primary to sent), write_lag (sent to written), flush_lag (written to flushed), replay_lag (flushed to replayed), and the overall total_lag (primary to replayed).
-authRequired: []
----
-kind: sources
-name: cloudsql-pg-source
-type: cloud-sql-postgres
-project: ${CLOUD_SQL_POSTGRES_PROJECT}
-region: ${CLOUD_SQL_POSTGRES_REGION}
-instance: ${CLOUD_SQL_POSTGRES_INSTANCE}
-ipType: ${CLOUD_SQL_POSTGRES_IP_TYPE}
-database: ${CLOUD_SQL_POSTGRES_DATABASE}
-user: ${CLOUD_SQL_POSTGRES_USER}
-password: ${CLOUD_SQL_POSTGRES_PASSWORD}

From 288fcca752ef013a0a648a89dceab480d0b90459 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 11:55:46 +0530
Subject: [PATCH 03/13] regenerate skills with new logic

---
 skills/cloudsql-postgres/SKILL.md             | 546 ++++--------------
 .../scripts/database_overview.js              |  65 ++-
 .../cloudsql-postgres/scripts/execute_sql.js  |  64 +-
 .../scripts/get_column_cardinality.js         |  65 ++-
 .../scripts/get_query_plan.js                 |  65 ++-
 .../scripts/list_active_queries.js            |  65 ++-
 .../scripts/list_autovacuum_configurations.js |  65 ++-
 .../scripts/list_available_extensions.js      |  65 ++-
 .../scripts/list_database_stats.js            |  53 +-
 .../cloudsql-postgres/scripts/list_indexes.js |  65 ++-
 .../scripts/list_installed_extensions.js      |  65 ++-
 .../scripts/list_invalid_indexes.js           |  65 ++-
 .../cloudsql-postgres/scripts/list_locks.js   |  65 ++-
 .../scripts/list_memory_configurations.js     |  65 ++-
 .../scripts/list_pg_settings.js               |  65 ++-
 .../scripts/list_publication_tables.js        |  65 ++-
 .../scripts/list_query_stats.js               |  65 ++-
 .../scripts/list_replication_slots.js         |  65 ++-
 .../cloudsql-postgres/scripts/list_roles.js   |  65 ++-
 .../cloudsql-postgres/scripts/list_schemas.js |  65 ++-
 .../scripts/list_sequences.js                 |  65 ++-
 .../scripts/list_stored_procedure.js          |  65 ++-
 .../scripts/list_table_stats.js               |  65 ++-
 .../cloudsql-postgres/scripts/list_tables.js  |  65 ++-
 .../scripts/list_tablespaces.js               |  65 ++-
 .../scripts/list_top_bloated_tables.js        |  65 ++-
 .../scripts/list_triggers.js                  |  65 ++-
 .../cloudsql-postgres/scripts/list_views.js   |  65 ++-
 .../scripts/long_running_transactions.js      |  65 ++-
 .../scripts/replication_stats.js              |  65 ++-
 30 files changed, 1586 insertions(+), 832 deletions(-)

diff --git a/skills/cloudsql-postgres/SKILL.md b/skills/cloudsql-postgres/SKILL.md
index ee1d33f..b665d13 100644
--- a/skills/cloudsql-postgres/SKILL.md
+++ b/skills/cloudsql-postgres/SKILL.md
@@ -8,10 +8,10 @@ description: skill for running tool operations in CloudSql postgres
 All scripts can be executed using Node.js. Replace `<param_name>` and `<param_value>` with actual values.
 
 **Bash:**
-`node scripts/<script_name>.js '{"<param_name>": "<param_value>"}'`
+`node <skill_dir>/scripts/<script_name>.js '{"<param_name>": "<param_value>"}'`
 
 **PowerShell:**
-`node scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
+`node <skill_dir>/scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
 
 ## Scripts
 
@@ -30,20 +30,10 @@ Use this tool to execute sql.
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "sql": {
-      "description": "The sql to execute.",
-      "type": "string"
-    }
-  },
-  "required": [
-    "sql"
-  ],
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| sql | string | The sql to execute. | Yes |  |
+
 
 ---
 
@@ -53,29 +43,12 @@ Estimates the number of unique values (cardinality) quickly for one or all colum
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "column_name": {
-      "description": "Optional: The column name for which the cardinality is to be found. If not provided, cardinality for all columns will be returned.",
-      "type": "string"
-    },
-    "schema_name": {
-      "default": "public",
-      "description": "Optional: The schema name in which the table is present.",
-      "type": "string"
-    },
-    "table_name": {
-      "description": "Required: The table name in which the column is present.",
-      "type": "string"
-    }
-  },
-  "required": [
-    "table_name"
-  ],
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| schema_name | string | Optional: The schema name in which the table is present. | No |  |
+| table_name | string | Required: The table name in which the column is present. | Yes |  |
+| column_name | string | Optional: The column name for which the cardinality is to be found. If not provided, cardinality for all columns will be returned. | No |  |
+
 
 ---
 
@@ -85,20 +58,10 @@ Generate a PostgreSQL EXPLAIN plan in JSON format for a single SQL statement—w
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "query": {
-      "description": "The SQL statement for which you want to generate plan (omit the EXPLAIN keyword).",
-      "type": "string"
-    }
-  },
-  "required": [
-    "query"
-  ],
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| query | string | The SQL statement for which you want to generate plan (omit the EXPLAIN keyword). | Yes |  |
+
 
 ---
 
@@ -108,28 +71,12 @@ List the top N (default 50) currently running queries (state='active') from pg_s
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "exclude_application_names": {
-      "default": "",
-      "description": "Optional: A comma-separated list of application names to exclude from the query results. This is useful for filtering out queries from specific applications (e.g., 'psql', 'pgAdmin', 'DBeaver'). The match is case-sensitive. Whitespace around commas and names is automatically handled. If this parameter is omitted, no applications are excluded.",
-      "type": "string"
-    },
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "min_duration": {
-      "default": "1 minute",
-      "description": "Optional: Only show queries running at least this long (e.g., '1 minute', '1 second', '2 seconds').",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| min_duration | string | Optional: Only show queries running at least this long (e.g., '1 minute', '1 second', '2 seconds'). | No | `1 minute` |
+| exclude_application_names | string | Optional: A comma-separated list of application names to exclude from the query results. This is useful for filtering out queries from specific applications (e.g., 'psql', 'pgAdmin', 'DBeaver'). The match is case-sensitive. Whitespace around commas and names is automatically handled. If this parameter is omitted, no applications are excluded. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -155,43 +102,15 @@ Discover all PostgreSQL extensions available for installation on this server, re
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "database_name": {
-      "default": "",
-      "description": "Optional: A specific database name pattern to search for.",
-      "type": "string"
-    },
-    "database_owner": {
-      "default": "",
-      "description": "Optional: A specific database owner name pattern to search for.",
-      "type": "string"
-    },
-    "default_tablespace": {
-      "default": "",
-      "description": "Optional: A specific default tablespace name pattern to search for.",
-      "type": "string"
-    },
-    "include_templates": {
-      "default": false,
-      "description": "Optional: Whether to include template databases in the results.",
-      "type": "boolean"
-    },
-    "limit": {
-      "default": 10,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "order_by": {
-      "default": "",
-      "description": "Optional: The field to order the results by. Valid values are 'size' and 'commit'.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| database_name | string | Optional: A specific database name pattern to search for. | No | `` |
+| include_templates | boolean | Optional: Whether to include template databases in the results. | No | `false` |
+| database_owner | string | Optional: A specific database owner name pattern to search for. | No | `` |
+| default_tablespace | string | Optional: A specific default tablespace name pattern to search for. | No | `` |
+| order_by | string | Optional: The field to order the results by. Valid values are 'size' and 'commit'. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `10` |
+
 
 ---
 
@@ -201,38 +120,14 @@ Lists available user indexes in the database, excluding system schemas (pg_catal
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "index_name": {
-      "default": "",
-      "description": "Optional: a text to filter results by index name. The input is used within a LIKE clause.",
-      "type": "string"
-    },
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return. Default is 50",
-      "type": "integer"
-    },
-    "only_unused": {
-      "default": false,
-      "description": "Optional: If true, only returns indexes that have never been used.",
-      "type": "boolean"
-    },
-    "schema_name": {
-      "default": "",
-      "description": "Optional: a text to filter results by schema name. The input is used within a LIKE clause.",
-      "type": "string"
-    },
-    "table_name": {
-      "default": "",
-      "description": "Optional: a text to filter results by table name. The input is used within a LIKE clause.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| schema_name | string | Optional: a text to filter results by schema name. The input is used within a LIKE clause. | No | `` |
+| table_name | string | Optional: a text to filter results by table name. The input is used within a LIKE clause. | No | `` |
+| index_name | string | Optional: a text to filter results by index name. The input is used within a LIKE clause. | No | `` |
+| only_unused | boolean | Optional: If true, only returns indexes that have never been used. | No | `false` |
+| limit | integer | Optional: The maximum number of rows to return. Default is 50 | No | `50` |
+
 
 ---
 
@@ -274,23 +169,11 @@ List PostgreSQL memory-related configurations (name and current setting) from pg
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "setting_name": {
-      "default": "",
-      "description": "Optional: A specific configuration parameter name pattern to search for.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| setting_name | string | Optional: A specific configuration parameter name pattern to search for. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -300,33 +183,13 @@ List PostgreSQL memory-related configurations (name and current setting) from pg
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "publication_names": {
-      "default": "",
-      "description": "Optional: Filters by a comma-separated list of publication names.",
-      "type": "string"
-    },
-    "schema_names": {
-      "default": "",
-      "description": "Optional: Filters by a comma-separated list of schema names.",
-      "type": "string"
-    },
-    "table_names": {
-      "default": "",
-      "description": "Optional: Filters by a comma-separated list of table names.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| table_names | string | Optional: Filters by a comma-separated list of table names. | No | `` |
+| publication_names | string | Optional: Filters by a comma-separated list of publication names. | No | `` |
+| schema_names | string | Optional: Filters by a comma-separated list of schema names. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -336,23 +199,11 @@ Lists performance statistics for executed queries ordered by total time, filteri
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "database_name": {
-      "default": "",
-      "description": "Optional: The database name to list query stats for.",
-      "type": "string"
-    },
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of results to return. Defaults to 50.",
-      "type": "integer"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| database_name | string | Optional: The database name to list query stats for. | No | `` |
+| limit | integer | Optional: The maximum number of results to return. Defaults to 50. | No | `50` |
+
 
 ---
 
@@ -370,23 +221,11 @@ Lists all the user-created roles in the instance . It returns the role name, Obj
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return. Default is 10",
-      "type": "integer"
-    },
-    "role_name": {
-      "default": "",
-      "description": "Optional: a text to filter results by role name. The input is used within a LIKE clause.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| role_name | string | Optional: a text to filter results by role name. The input is used within a LIKE clause. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. Default is 10 | No | `50` |
+
 
 ---
 
@@ -396,28 +235,12 @@ Lists all schemas in the database ordered by schema name and excluding system an
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 10,
-      "description": "Optional: The maximum number of schemas to return.",
-      "type": "integer"
-    },
-    "owner": {
-      "default": "",
-      "description": "Optional: A specific schema owner name pattern to search for.",
-      "type": "string"
-    },
-    "schema_name": {
-      "default": "",
-      "description": "Optional: A specific schema name pattern to search for.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| schema_name | string | Optional: A specific schema name pattern to search for. | No | `` |
+| owner | string | Optional: A specific schema owner name pattern to search for. | No | `` |
+| limit | integer | Optional: The maximum number of schemas to return. | No | `10` |
+
 
 ---
 
@@ -427,28 +250,12 @@ Lists sequences in the database. Returns sequence name, schema name, sequence ow
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return. Default is 50",
-      "type": "integer"
-    },
-    "schema_name": {
-      "default": "",
-      "description": "Optional: A specific schema name pattern to search for.",
-      "type": "string"
-    },
-    "sequence_name": {
-      "default": "",
-      "description": "Optional: A specific sequence name pattern to search for.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| schema_name | string | Optional: A specific schema name pattern to search for. | No | `` |
+| sequence_name | string | Optional: A specific sequence name pattern to search for. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. Default is 50 | No | `50` |
+
 
 ---
 
@@ -458,26 +265,12 @@ Retrieves stored procedure metadata returning schema name, procedure name, proce
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 20,
-      "description": "Optional: The maximum number of stored procedures to return. Defaults to 20.",
-      "type": "integer"
-    },
-    "role_name": {
-      "description": "Optional: The owner name to filter the stored procedures by. Defaults to NULL.",
-      "type": "string"
-    },
-    "schema_name": {
-      "description": "Optional: The schema name to filter the stored procedures by. Defaults to NULL.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| role_name | string | Optional: The owner name to filter the stored procedures by. Defaults to NULL. | No |  |
+| schema_name | string | Optional: The schema name to filter the stored procedures by. Defaults to NULL. | No |  |
+| limit | integer | Optional: The maximum number of stored procedures to return. Defaults to 20. | No | `20` |
+
 
 ---
 
@@ -495,35 +288,14 @@ Lists the user table statistics in the database ordered by number of
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of results to return",
-      "type": "integer"
-    },
-    "owner": {
-      "description": "Optional: A specific owner to filter by",
-      "type": "string"
-    },
-    "schema_name": {
-      "default": "public",
-      "description": "Optional: A specific schema name to filter by",
-      "type": "string"
-    },
-    "sort_by": {
-      "description": "Optional: The column to sort by",
-      "type": "string"
-    },
-    "table_name": {
-      "description": "Optional: A specific table name to filter by",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| schema_name | string | Optional: A specific schema name to filter by | No |  |
+| table_name | string | Optional: A specific table name to filter by | No |  |
+| owner | string | Optional: A specific owner to filter by | No |  |
+| sort_by | string | Optional: The column to sort by | No |  |
+| limit | integer | Optional: The maximum number of results to return | No | `50` |
+
 
 ---
 
@@ -533,23 +305,11 @@ Lists detailed schema information (object type, columns, constraints, indexes, t
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "output_format": {
-      "default": "detailed",
-      "description": "Optional: Use 'simple' for names only or 'detailed' for full info.",
-      "type": "string"
-    },
-    "table_names": {
-      "default": "",
-      "description": "Optional: A comma-separated list of table names. If empty, details for all tables will be listed.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| table_names | string | Optional: A comma-separated list of table names. If empty, details for all tables will be listed. | No | `` |
+| output_format | string | Optional: Use 'simple' for names only or 'detailed' for full info. | No | `detailed` |
+
 
 ---
 
@@ -559,23 +319,11 @@ Lists detailed schema information (object type, columns, constraints, indexes, t
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "tablespace_name": {
-      "default": "",
-      "description": "Optional: a text to filter results by tablespace name. The input is used within a LIKE clause.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| tablespace_name | string | Optional: a text to filter results by tablespace name. The input is used within a LIKE clause. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -586,18 +334,10 @@ List the top tables by dead-tuple (approximate bloat signal), returning schema,
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "The maximum number of results to return.",
-      "type": "integer"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| limit | integer | The maximum number of results to return. | No | `50` |
+
 
 ---
 
@@ -607,33 +347,13 @@ Lists all non-internal triggers in a database. Returns trigger name, schema name
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "schema_name": {
-      "default": "",
-      "description": "Optional: A specific schema name pattern to search for.",
-      "type": "string"
-    },
-    "table_name": {
-      "default": "",
-      "description": "Optional: A specific table name pattern to search for.",
-      "type": "string"
-    },
-    "trigger_name": {
-      "default": "",
-      "description": "Optional: A specific trigger name pattern to search for.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| trigger_name | string | Optional: A specific trigger name pattern to search for. | No | `` |
+| schema_name | string | Optional: A specific schema name pattern to search for. | No | `` |
+| table_name | string | Optional: A specific table name pattern to search for. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -643,28 +363,12 @@ Lists views in the database from pg_views with a default limit of 50 rows. Retur
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 50,
-      "description": "Optional: The maximum number of rows to return.",
-      "type": "integer"
-    },
-    "schema_name": {
-      "default": "",
-      "description": "Optional: A specific schema name to search for.",
-      "type": "string"
-    },
-    "view_name": {
-      "default": "",
-      "description": "Optional: A specific view name to search for.",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| view_name | string | Optional: A specific view name to search for. | No | `` |
+| schema_name | string | Optional: A specific schema name to search for. | No | `` |
+| limit | integer | Optional: The maximum number of rows to return. | No | `50` |
+
 
 ---
 
@@ -674,23 +378,11 @@ Identifies and lists database transactions that exceed a specified time limit. F
 
 #### Parameters
 
-```json
-{
-  "properties": {
-    "limit": {
-      "default": 20,
-      "description": "Optional: The maximum number of long-running transactions to return. Defaults to 20.",
-      "type": "integer"
-    },
-    "min_duration": {
-      "default": "5 minutes",
-      "description": "Optional: Only show transactions running at least this long (e.g., '1 minute', '15 minutes', '30 seconds').",
-      "type": "string"
-    }
-  },
-  "type": "object"
-}
-```
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| min_duration | string | Optional: Only show transactions running at least this long (e.g., '1 minute', '15 minutes', '30 seconds'). | No | `5 minutes` |
+| limit | integer | Optional: The maximum number of long-running transactions to return. Defaults to 20. | No | `20` |
+
 
 ---
 
diff --git a/skills/cloudsql-postgres/scripts/database_overview.js b/skills/cloudsql-postgres/scripts/database_overview.js
index b3b050d..d9bad49 100755
--- a/skills/cloudsql-postgres/scripts/database_overview.js
+++ b/skills/cloudsql-postgres/scripts/database_overview.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "database_overview";
-const toolsFileName = "database_overview.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/execute_sql.js b/skills/cloudsql-postgres/scripts/execute_sql.js
index fb01efe..cc69f9e 100755
--- a/skills/cloudsql-postgres/scripts/execute_sql.js
+++ b/skills/cloudsql-postgres/scripts/execute_sql.js
@@ -1,28 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
 const toolName = "execute_sql";
-const toolsFileName = "execute_sql.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
-    }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
+        throw new Error("Toolbox binary not found");
     }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -33,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/get_column_cardinality.js b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
index 5bf2bea..9e80522 100755
--- a/skills/cloudsql-postgres/scripts/get_column_cardinality.js
+++ b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "get_column_cardinality";
-const toolsFileName = "get_column_cardinality.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/get_query_plan.js b/skills/cloudsql-postgres/scripts/get_query_plan.js
index e95a906..7ed3f77 100755
--- a/skills/cloudsql-postgres/scripts/get_query_plan.js
+++ b/skills/cloudsql-postgres/scripts/get_query_plan.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "get_query_plan";
-const toolsFileName = "get_query_plan.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_active_queries.js b/skills/cloudsql-postgres/scripts/list_active_queries.js
index 35e4f95..1647f1e 100755
--- a/skills/cloudsql-postgres/scripts/list_active_queries.js
+++ b/skills/cloudsql-postgres/scripts/list_active_queries.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_active_queries";
-const toolsFileName = "list_active_queries.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
index 737129e..af89cdf 100755
--- a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_autovacuum_configurations";
-const toolsFileName = "list_autovacuum_configurations.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_available_extensions.js b/skills/cloudsql-postgres/scripts/list_available_extensions.js
index 4ec3142..cd87040 100755
--- a/skills/cloudsql-postgres/scripts/list_available_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_available_extensions.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_available_extensions";
-const toolsFileName = "list_available_extensions.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_database_stats.js b/skills/cloudsql-postgres/scripts/list_database_stats.js
index 94f5da8..29f9a17 100755
--- a/skills/cloudsql-postgres/scripts/list_database_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_database_stats.js
@@ -1,29 +1,31 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the "License");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an "AS IS" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_database_stats";
-const toolsFileName = "list_database_stats.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +36,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_indexes.js b/skills/cloudsql-postgres/scripts/list_indexes.js
index 0e490d4..d6b0470 100755
--- a/skills/cloudsql-postgres/scripts/list_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_indexes.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_indexes";
-const toolsFileName = "list_indexes.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_installed_extensions.js b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
index e568b53..ac7dfc6 100755
--- a/skills/cloudsql-postgres/scripts/list_installed_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_installed_extensions";
-const toolsFileName = "list_installed_extensions.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
index 409c154..d22afe1 100755
--- a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_invalid_indexes";
-const toolsFileName = "list_invalid_indexes.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_locks.js b/skills/cloudsql-postgres/scripts/list_locks.js
index 352623a..93f5bfc 100755
--- a/skills/cloudsql-postgres/scripts/list_locks.js
+++ b/skills/cloudsql-postgres/scripts/list_locks.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_locks";
-const toolsFileName = "list_locks.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_memory_configurations.js b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
index 3f30626..dba1c65 100755
--- a/skills/cloudsql-postgres/scripts/list_memory_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_memory_configurations";
-const toolsFileName = "list_memory_configurations.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_pg_settings.js b/skills/cloudsql-postgres/scripts/list_pg_settings.js
index 5a169b0..ed2f03b 100755
--- a/skills/cloudsql-postgres/scripts/list_pg_settings.js
+++ b/skills/cloudsql-postgres/scripts/list_pg_settings.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_pg_settings";
-const toolsFileName = "list_pg_settings.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_publication_tables.js b/skills/cloudsql-postgres/scripts/list_publication_tables.js
index 79eb5bf..c1c754c 100755
--- a/skills/cloudsql-postgres/scripts/list_publication_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_publication_tables.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_publication_tables";
-const toolsFileName = "list_publication_tables.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_query_stats.js b/skills/cloudsql-postgres/scripts/list_query_stats.js
index 7f74a1d..f734cbc 100755
--- a/skills/cloudsql-postgres/scripts/list_query_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_query_stats.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_query_stats";
-const toolsFileName = "list_query_stats.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_replication_slots.js b/skills/cloudsql-postgres/scripts/list_replication_slots.js
index 6f7ee52..55a6de9 100755
--- a/skills/cloudsql-postgres/scripts/list_replication_slots.js
+++ b/skills/cloudsql-postgres/scripts/list_replication_slots.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_replication_slots";
-const toolsFileName = "list_replication_slots.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_roles.js b/skills/cloudsql-postgres/scripts/list_roles.js
index c044adf..12ac933 100755
--- a/skills/cloudsql-postgres/scripts/list_roles.js
+++ b/skills/cloudsql-postgres/scripts/list_roles.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_roles";
-const toolsFileName = "list_roles.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_schemas.js b/skills/cloudsql-postgres/scripts/list_schemas.js
index d0a4fa0..a035876 100755
--- a/skills/cloudsql-postgres/scripts/list_schemas.js
+++ b/skills/cloudsql-postgres/scripts/list_schemas.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_schemas";
-const toolsFileName = "list_schemas.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_sequences.js b/skills/cloudsql-postgres/scripts/list_sequences.js
index 8d4123a..acaeddb 100755
--- a/skills/cloudsql-postgres/scripts/list_sequences.js
+++ b/skills/cloudsql-postgres/scripts/list_sequences.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_sequences";
-const toolsFileName = "list_sequences.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_stored_procedure.js b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
index 380487a..80eb9d4 100755
--- a/skills/cloudsql-postgres/scripts/list_stored_procedure.js
+++ b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_stored_procedure";
-const toolsFileName = "list_stored_procedure.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_table_stats.js b/skills/cloudsql-postgres/scripts/list_table_stats.js
index 5c7330d..8093dea 100755
--- a/skills/cloudsql-postgres/scripts/list_table_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_table_stats.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_table_stats";
-const toolsFileName = "list_table_stats.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_tables.js b/skills/cloudsql-postgres/scripts/list_tables.js
index fe701e9..b53a59a 100755
--- a/skills/cloudsql-postgres/scripts/list_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_tables.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_tables";
-const toolsFileName = "list_tables.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_tablespaces.js b/skills/cloudsql-postgres/scripts/list_tablespaces.js
index 913204a..adc8bad 100755
--- a/skills/cloudsql-postgres/scripts/list_tablespaces.js
+++ b/skills/cloudsql-postgres/scripts/list_tablespaces.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_tablespaces";
-const toolsFileName = "list_tablespaces.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
index e15e880..734786d 100755
--- a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_top_bloated_tables";
-const toolsFileName = "list_top_bloated_tables.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_triggers.js b/skills/cloudsql-postgres/scripts/list_triggers.js
index 9280eba..3df7005 100755
--- a/skills/cloudsql-postgres/scripts/list_triggers.js
+++ b/skills/cloudsql-postgres/scripts/list_triggers.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_triggers";
-const toolsFileName = "list_triggers.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/list_views.js b/skills/cloudsql-postgres/scripts/list_views.js
index 350e089..5d8b3e8 100755
--- a/skills/cloudsql-postgres/scripts/list_views.js
+++ b/skills/cloudsql-postgres/scripts/list_views.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "list_views";
-const toolsFileName = "list_views.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/long_running_transactions.js b/skills/cloudsql-postgres/scripts/long_running_transactions.js
index bc22b59..b52951a 100755
--- a/skills/cloudsql-postgres/scripts/long_running_transactions.js
+++ b/skills/cloudsql-postgres/scripts/long_running_transactions.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "long_running_transactions";
-const toolsFileName = "long_running_transactions.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);
diff --git a/skills/cloudsql-postgres/scripts/replication_stats.js b/skills/cloudsql-postgres/scripts/replication_stats.js
index ba06322..065c141 100755
--- a/skills/cloudsql-postgres/scripts/replication_stats.js
+++ b/skills/cloudsql-postgres/scripts/replication_stats.js
@@ -1,29 +1,43 @@
 #!/usr/bin/env node
-require('./load_env.js');
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
 
-
 const toolName = "replication_stats";
-const toolsFileName = "replication_stats.yaml";
+const configArgs = ["--prebuilt", "cloud-sql-postgres"];
 
 function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
     try {
         const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
         const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
         if (globalPath) {
             return globalPath.split('\n')[0].trim();
         }
+        throw new Error("Toolbox binary not found");
     } catch (e) {
-        // Ignore error;
+        throw new Error("Toolbox binary not found");
     }
-    const localPath = path.resolve(__dirname, '../../../toolbox');
-    if (fs.existsSync(localPath)) {
-        return localPath;
-    }
-    throw new Error("Toolbox binary not found");
 }
 
 let toolboxBinary;
@@ -34,15 +48,38 @@ try {
     process.exit(1);
 }
 
-let configArgs = [];
-if (toolsFileName) {
-  configArgs.push("--tools-file", path.join(__dirname, "..", "assets", toolsFileName));
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
 }
 
 const args = process.argv.slice(2);
-const toolboxArgs = [...configArgs, "invoke", toolName, ...args];
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
 
-const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit' });
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
 
 child.on('close', (code) => {
   process.exit(code);

From 4681ff9b8f22ce900a2d783b6d001325a822b648 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 12:03:14 +0530
Subject: [PATCH 04/13] add env loading require

---
 .../scripts/database_overview.js                 |  2 ++
 skills/cloudsql-postgres/scripts/execute_sql.js  |  2 ++
 .../scripts/get_column_cardinality.js            |  2 ++
 .../cloudsql-postgres/scripts/get_query_plan.js  |  2 ++
 .../scripts/list_active_queries.js               |  2 ++
 .../scripts/list_autovacuum_configurations.js    |  2 ++
 .../scripts/list_available_extensions.js         |  2 ++
 .../scripts/list_database_stats.js               |  2 ++
 skills/cloudsql-postgres/scripts/list_indexes.js |  2 ++
 .../scripts/list_installed_extensions.js         |  2 ++
 .../scripts/list_invalid_indexes.js              |  2 ++
 skills/cloudsql-postgres/scripts/list_locks.js   |  2 ++
 .../scripts/list_memory_configurations.js        |  2 ++
 .../scripts/list_pg_settings.js                  |  2 ++
 .../scripts/list_publication_tables.js           |  2 ++
 .../scripts/list_query_stats.js                  |  2 ++
 .../scripts/list_replication_slots.js            |  2 ++
 skills/cloudsql-postgres/scripts/list_roles.js   |  2 ++
 skills/cloudsql-postgres/scripts/list_schemas.js |  2 ++
 .../cloudsql-postgres/scripts/list_sequences.js  |  2 ++
 .../scripts/list_stored_procedure.js             |  2 ++
 .../scripts/list_table_stats.js                  |  2 ++
 skills/cloudsql-postgres/scripts/list_tables.js  |  2 ++
 .../scripts/list_tablespaces.js                  |  2 ++
 .../scripts/list_top_bloated_tables.js           |  2 ++
 .../cloudsql-postgres/scripts/list_triggers.js   |  2 ++
 skills/cloudsql-postgres/scripts/list_views.js   |  2 ++
 skills/cloudsql-postgres/scripts/load_env.js     | 16 ++++++++++++++++
 .../scripts/long_running_transactions.js         |  2 ++
 .../scripts/replication_stats.js                 |  2 ++
 30 files changed, 74 insertions(+)

diff --git a/skills/cloudsql-postgres/scripts/database_overview.js b/skills/cloudsql-postgres/scripts/database_overview.js
index d9bad49..7da0abd 100755
--- a/skills/cloudsql-postgres/scripts/database_overview.js
+++ b/skills/cloudsql-postgres/scripts/database_overview.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/execute_sql.js b/skills/cloudsql-postgres/scripts/execute_sql.js
index cc69f9e..f6cd8c8 100755
--- a/skills/cloudsql-postgres/scripts/execute_sql.js
+++ b/skills/cloudsql-postgres/scripts/execute_sql.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/get_column_cardinality.js b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
index 9e80522..e8cd9ec 100755
--- a/skills/cloudsql-postgres/scripts/get_column_cardinality.js
+++ b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/get_query_plan.js b/skills/cloudsql-postgres/scripts/get_query_plan.js
index 7ed3f77..9c42fe5 100755
--- a/skills/cloudsql-postgres/scripts/get_query_plan.js
+++ b/skills/cloudsql-postgres/scripts/get_query_plan.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_active_queries.js b/skills/cloudsql-postgres/scripts/list_active_queries.js
index 1647f1e..414c0a9 100755
--- a/skills/cloudsql-postgres/scripts/list_active_queries.js
+++ b/skills/cloudsql-postgres/scripts/list_active_queries.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
index af89cdf..421eb21 100755
--- a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_available_extensions.js b/skills/cloudsql-postgres/scripts/list_available_extensions.js
index cd87040..c348fbf 100755
--- a/skills/cloudsql-postgres/scripts/list_available_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_available_extensions.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_database_stats.js b/skills/cloudsql-postgres/scripts/list_database_stats.js
index 29f9a17..db3e209 100755
--- a/skills/cloudsql-postgres/scripts/list_database_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_database_stats.js
@@ -2,6 +2,8 @@
 
 // Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the "License");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an "AS IS" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_indexes.js b/skills/cloudsql-postgres/scripts/list_indexes.js
index d6b0470..bd0ff0b 100755
--- a/skills/cloudsql-postgres/scripts/list_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_indexes.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_installed_extensions.js b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
index ac7dfc6..22e1d44 100755
--- a/skills/cloudsql-postgres/scripts/list_installed_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
index d22afe1..0894730 100755
--- a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_locks.js b/skills/cloudsql-postgres/scripts/list_locks.js
index 93f5bfc..34f6ef4 100755
--- a/skills/cloudsql-postgres/scripts/list_locks.js
+++ b/skills/cloudsql-postgres/scripts/list_locks.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_memory_configurations.js b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
index dba1c65..d57cfcf 100755
--- a/skills/cloudsql-postgres/scripts/list_memory_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_pg_settings.js b/skills/cloudsql-postgres/scripts/list_pg_settings.js
index ed2f03b..39500f7 100755
--- a/skills/cloudsql-postgres/scripts/list_pg_settings.js
+++ b/skills/cloudsql-postgres/scripts/list_pg_settings.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_publication_tables.js b/skills/cloudsql-postgres/scripts/list_publication_tables.js
index c1c754c..1b28833 100755
--- a/skills/cloudsql-postgres/scripts/list_publication_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_publication_tables.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_query_stats.js b/skills/cloudsql-postgres/scripts/list_query_stats.js
index f734cbc..c93428b 100755
--- a/skills/cloudsql-postgres/scripts/list_query_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_query_stats.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_replication_slots.js b/skills/cloudsql-postgres/scripts/list_replication_slots.js
index 55a6de9..5323ef5 100755
--- a/skills/cloudsql-postgres/scripts/list_replication_slots.js
+++ b/skills/cloudsql-postgres/scripts/list_replication_slots.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_roles.js b/skills/cloudsql-postgres/scripts/list_roles.js
index 12ac933..637086b 100755
--- a/skills/cloudsql-postgres/scripts/list_roles.js
+++ b/skills/cloudsql-postgres/scripts/list_roles.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_schemas.js b/skills/cloudsql-postgres/scripts/list_schemas.js
index a035876..057cca4 100755
--- a/skills/cloudsql-postgres/scripts/list_schemas.js
+++ b/skills/cloudsql-postgres/scripts/list_schemas.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_sequences.js b/skills/cloudsql-postgres/scripts/list_sequences.js
index acaeddb..15f223f 100755
--- a/skills/cloudsql-postgres/scripts/list_sequences.js
+++ b/skills/cloudsql-postgres/scripts/list_sequences.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_stored_procedure.js b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
index 80eb9d4..a73ebb4 100755
--- a/skills/cloudsql-postgres/scripts/list_stored_procedure.js
+++ b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_table_stats.js b/skills/cloudsql-postgres/scripts/list_table_stats.js
index 8093dea..e83fec3 100755
--- a/skills/cloudsql-postgres/scripts/list_table_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_table_stats.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_tables.js b/skills/cloudsql-postgres/scripts/list_tables.js
index b53a59a..4363750 100755
--- a/skills/cloudsql-postgres/scripts/list_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_tables.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_tablespaces.js b/skills/cloudsql-postgres/scripts/list_tablespaces.js
index adc8bad..1012258 100755
--- a/skills/cloudsql-postgres/scripts/list_tablespaces.js
+++ b/skills/cloudsql-postgres/scripts/list_tablespaces.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
index 734786d..107a4e0 100755
--- a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_triggers.js b/skills/cloudsql-postgres/scripts/list_triggers.js
index 3df7005..188f9f3 100755
--- a/skills/cloudsql-postgres/scripts/list_triggers.js
+++ b/skills/cloudsql-postgres/scripts/list_triggers.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/list_views.js b/skills/cloudsql-postgres/scripts/list_views.js
index 5d8b3e8..e80d689 100755
--- a/skills/cloudsql-postgres/scripts/list_views.js
+++ b/skills/cloudsql-postgres/scripts/list_views.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/load_env.js b/skills/cloudsql-postgres/scripts/load_env.js
index 30b571d..67617bf 100644
--- a/skills/cloudsql-postgres/scripts/load_env.js
+++ b/skills/cloudsql-postgres/scripts/load_env.js
@@ -1,3 +1,19 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 const fs = require('fs');
 const path = require('path');
 const os = require('os');
diff --git a/skills/cloudsql-postgres/scripts/long_running_transactions.js b/skills/cloudsql-postgres/scripts/long_running_transactions.js
index b52951a..53118a2 100755
--- a/skills/cloudsql-postgres/scripts/long_running_transactions.js
+++ b/skills/cloudsql-postgres/scripts/long_running_transactions.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres/scripts/replication_stats.js b/skills/cloudsql-postgres/scripts/replication_stats.js
index 065c141..4cf1730 100755
--- a/skills/cloudsql-postgres/scripts/replication_stats.js
+++ b/skills/cloudsql-postgres/scripts/replication_stats.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');

From 6137746c3a66aa8b64103048d865fef182c5637a Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 13:44:43 +0530
Subject: [PATCH 05/13] update gemini extension settings

---
 gemini-extension.json | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/gemini-extension.json b/gemini-extension.json
index 77b4cbb..6b1834a 100644
--- a/gemini-extension.json
+++ b/gemini-extension.json
@@ -27,21 +27,17 @@
     {
       "name": "User",
       "description": "(Optional) Username of the database user (Default: IAM user)",
-      "envVar": "CLOUD_SQL_POSTGRES_USER",
-      "required": false
+      "envVar": "CLOUD_SQL_POSTGRES_USER"
     },
     {
       "name": "Password",
       "description": "(Optional) Password of the database user  (Default: IAM user)",
-      "envVar": "CLOUD_SQL_POSTGRES_PASSWORD",
-      "required": false
+      "envVar": "CLOUD_SQL_POSTGRES_PASSWORD"
     },
     {
       "name": "IP Type",
       "description": "(Optional) Type of the IP address: PUBLIC, PRIVATE, or PSC (Default: Public)",
-      "envVar": "CLOUD_SQL_POSTGRES_IP_TYPE",
-      "default": "PUBLIC",
-      "required": false
+      "envVar": "CLOUD_SQL_POSTGRES_IP_TYPE"
     }
   ]
 }

From 583fb0865783aa6f0c81d80267c965dea9e841cf Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 13:49:58 +0530
Subject: [PATCH 06/13] add admin skills

---
 skills/cloudsql-postgres-admin/SKILL.md       | 191 ++++++++++++++++++
 .../scripts/clone_instance.js                 |  91 +++++++++
 .../scripts/create_backup.js                  |  91 +++++++++
 .../scripts/create_database.js                |  91 +++++++++
 .../scripts/create_instance.js                |  91 +++++++++
 .../scripts/create_user.js                    |  91 +++++++++
 .../scripts/get_instance.js                   |  91 +++++++++
 .../scripts/list_databases.js                 |  91 +++++++++
 .../scripts/list_instances.js                 |  91 +++++++++
 .../scripts/load_env.js                       |  91 +++++++++
 .../scripts/postgres_upgrade_precheck.js      |  91 +++++++++
 .../scripts/restore_backup.js                 |  91 +++++++++
 .../scripts/wait_for_operation.js             |  91 +++++++++
 13 files changed, 1283 insertions(+)
 create mode 100644 skills/cloudsql-postgres-admin/SKILL.md
 create mode 100755 skills/cloudsql-postgres-admin/scripts/clone_instance.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/create_backup.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/create_database.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/create_instance.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/create_user.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/get_instance.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/list_databases.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/list_instances.js
 create mode 100644 skills/cloudsql-postgres-admin/scripts/load_env.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/restore_backup.js
 create mode 100755 skills/cloudsql-postgres-admin/scripts/wait_for_operation.js

diff --git a/skills/cloudsql-postgres-admin/SKILL.md b/skills/cloudsql-postgres-admin/SKILL.md
new file mode 100644
index 0000000..4c1b10e
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/SKILL.md
@@ -0,0 +1,191 @@
+---
+name: cloudsql-postgres-admin
+description: skill for performing administrative operations on cloudsql postgres
+---
+
+## Usage
+
+All scripts can be executed using Node.js. Replace `<param_name>` and `<param_value>` with actual values.
+
+**Bash:**
+`node <skill_dir>/scripts/<script_name>.js '{"<param_name>": "<param_value>"}'`
+
+**PowerShell:**
+`node <skill_dir>/scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
+
+## Scripts
+
+
+### clone_instance
+
+Clone an existing Cloud SQL instance into a new instance. The clone can be a direct copy of the source instance, or a point-in-time-recovery (PITR) clone from a specific timestamp. The call returns a Cloud SQL Operation object. Call wait_for_operation tool after this, make sure to use multiplier as 4 to poll the opertation status till it is marked DONE.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| sourceInstanceName | string | The name of the instance to be cloned. | Yes |  |
+| destinationInstanceName | string | The name of the new instance that will be created by cloning the source instance. | Yes |  |
+| pointInTime | string | The timestamp in RFC 3339 format to which the source instance should be cloned. | No |  |
+| preferredZone | string | The preferred zone for the new instance. | No |  |
+| preferredSecondaryZone | string | The preferred secondary zone for the new instance. | No |  |
+
+
+---
+
+### create_backup
+
+Creates a backup on a Cloud SQL instance.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| instance | string | Cloud SQL instance ID. This does not include the project ID. | Yes |  |
+| location | string | Location of the backup run. | No |  |
+| backup_description | string | The description of this backup run. | No |  |
+
+
+---
+
+### create_database
+
+
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| instance | string | The ID of the instance where the database will be created. | Yes |  |
+| name | string | The name for the new database. Must be unique within the instance. | Yes |  |
+
+
+---
+
+### create_instance
+
+
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| name | string | The name of the instance | Yes |  |
+| databaseVersion | string | The database version for Postgres. If not specified, defaults to the latest available version (e.g., POSTGRES_17). | No | `POSTGRES_17` |
+| rootPassword | string | The root password for the instance | Yes |  |
+| editionPreset | string | The edition of the instance. Can be `Production` or `Development`. This determines the default machine type and availability. Defaults to `Development`. | No | `Development` |
+
+
+---
+
+### create_user
+
+
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| instance | string | The ID of the instance where the user will be created. | Yes |  |
+| name | string | The name for the new user. Must be unique within the instance. | Yes |  |
+| password | string | A secure password for the new user. Not required for IAM users. | No |  |
+| iamUser | boolean | Set to true to create a Cloud IAM user. | Yes |  |
+
+
+---
+
+### get_instance
+
+
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| projectId | string | The project ID | Yes |  |
+| instanceId | string | The instance ID | Yes |  |
+
+
+---
+
+### list_databases
+
+Lists all databases for a Cloud SQL instance.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| instance | string | The instance ID | Yes |  |
+
+
+---
+
+### list_instances
+
+Lists all type of Cloud SQL instances for a project.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+
+
+---
+
+### postgres_upgrade_precheck
+
+Analyzes a Cloud SQL PostgreSQL instance for major version upgrade readiness. Results are provided to guide customer actions:
+ERROR: Action Required. These are critical issues blocking the upgrade. Customers must resolve these using the provided actions_required steps before attempting the upgrade.
+WARNING: Review Recommended. These are potential issues. Customers should review the message and actions_required. While not blocking, addressing these is advised to prevent future problems or unexpected behavior post-upgrade.
+INFO: No Action Needed. Informational messages only. This pre-check helps customers proactively fix problems, preventing upgrade failures and ensuring a smoother transition.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| instance | string | The name of the instance to check | Yes |  |
+| targetDatabaseVersion | string | The target PostgreSQL version for the upgrade (e.g., POSTGRES_18). If not specified, defaults to the PostgreSQL 18. | No | `POSTGRES_18` |
+
+
+---
+
+### restore_backup
+
+Restores a backup on a Cloud SQL instance.
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| target_project | string | The project ID | Yes |  |
+| target_instance | string | Cloud SQL instance ID of the target instance. This does not include the project ID. | Yes |  |
+| backup_id | string | Identifier of the backup being restored. Can be a BackupRun ID, backup name, or BackupDR backup name. Use the full backup ID as provided, do not try to parse it | Yes |  |
+| source_project | string | GCP project ID of the instance that the backup belongs to. Only required if the backup_id is a BackupRun ID. | No |  |
+| source_instance | string | Cloud SQL instance ID of the instance that the backup belongs to. Only required if the backup_id is a BackupRun ID. | No |  |
+
+
+---
+
+### wait_for_operation
+
+
+
+#### Parameters
+
+| Name | Type | Description | Required | Default |
+| :--- | :--- | :--- | :--- | :--- |
+| project | string | The project ID | Yes |  |
+| operation | string | The operation ID | Yes |  |
+
+
+---
+
diff --git a/skills/cloudsql-postgres-admin/scripts/clone_instance.js b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
new file mode 100755
index 0000000..b324dab
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "clone_instance";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/create_backup.js b/skills/cloudsql-postgres-admin/scripts/create_backup.js
new file mode 100755
index 0000000..ca380e5
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/create_backup.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "create_backup";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/create_database.js b/skills/cloudsql-postgres-admin/scripts/create_database.js
new file mode 100755
index 0000000..3d00b5b
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/create_database.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "create_database";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/create_instance.js b/skills/cloudsql-postgres-admin/scripts/create_instance.js
new file mode 100755
index 0000000..48e8a55
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/create_instance.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "create_instance";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/create_user.js b/skills/cloudsql-postgres-admin/scripts/create_user.js
new file mode 100755
index 0000000..3fca27c
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/create_user.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "create_user";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/get_instance.js b/skills/cloudsql-postgres-admin/scripts/get_instance.js
new file mode 100755
index 0000000..4d2d9cb
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/get_instance.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "get_instance";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/list_databases.js b/skills/cloudsql-postgres-admin/scripts/list_databases.js
new file mode 100755
index 0000000..b019476
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/list_databases.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "list_databases";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/list_instances.js b/skills/cloudsql-postgres-admin/scripts/list_instances.js
new file mode 100755
index 0000000..24504d8
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/list_instances.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "list_instances";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/load_env.js b/skills/cloudsql-postgres-admin/scripts/load_env.js
new file mode 100644
index 0000000..67617bf
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/load_env.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const fs = require('fs');
+const path = require('path');
+const os = require('os');
+
+function loadEnv() {
+  try {
+    // Check if a local .env exists in the current working directory of the project
+    const localEnvPath = path.resolve(process.cwd(), '.env');
+    if (fs.existsSync(localEnvPath)) {
+      parseAndSetEnv(localEnvPath);
+    }
+
+    // Resolve the extension name from gemini-extension.json
+    // Fallback to 'cloud-sql-postgresql' if we can't find it
+    let extensionName = 'cloud-sql-postgresql';
+    try {
+      const projectRoot = path.resolve(__dirname, '../../..');
+      const manifestPath = path.join(projectRoot, 'gemini-extension.json');
+      if (fs.existsSync(manifestPath)) {
+        const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
+        if (manifest.name) {
+          extensionName = manifest.name;
+        }
+      }
+    } catch (e) {
+      // Ignore parsing errors, fallback is fine
+    }
+
+    // Load from ~/.gemini/extensions/<name>/.env
+    const homeDir = os.homedir();
+    const geminiEnvPath = path.join(homeDir, '.gemini', 'extensions', extensionName, '.env');
+    if (fs.existsSync(geminiEnvPath)) {
+      parseAndSetEnv(geminiEnvPath);
+    }
+  } catch (err) {
+    console.error("Warning: Failed to load extension environment variables:", err.message);
+  }
+}
+
+function parseAndSetEnv(envPath) {
+  const envFileContent = fs.readFileSync(envPath, 'utf8');
+  const lines = envFileContent.split(/\r?\n/);
+  
+  for (const line of lines) {
+    const trimmedLine = line.trim();
+    // Ignore empty lines and comments
+    if (!trimmedLine || trimmedLine.startsWith('#')) {
+      continue;
+    }
+    
+    // Parse KEY=VALUE
+    const equalSignIndex = trimmedLine.indexOf('=');
+    if (equalSignIndex === -1) {
+      continue;
+    }
+    
+    const key = trimmedLine.substring(0, equalSignIndex).trim();
+    let value = trimmedLine.substring(equalSignIndex + 1).trim();
+    
+    // Remove surrounding quotes if present
+    if (value.startsWith('"') && value.endsWith('"')) {
+      value = value.substring(1, value.length - 1);
+    } else if (value.startsWith("'") && value.endsWith("'")) {
+      value = value.substring(1, value.length - 1);
+    }
+    
+    // Set if not already defined in process.env
+    if (key && process.env[key] === undefined) {
+      process.env[key] = value;
+    }
+  }
+}
+
+// Execute immediately when required
+loadEnv();
diff --git a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
new file mode 100755
index 0000000..4f3e6a2
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "postgres_upgrade_precheck";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/restore_backup.js b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
new file mode 100755
index 0000000..74019e2
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "restore_backup";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});
diff --git a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
new file mode 100755
index 0000000..ca1b273
--- /dev/null
+++ b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
@@ -0,0 +1,91 @@
+#!/usr/bin/env node
+
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const { spawn, execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+
+const toolName = "wait_for_operation";
+const configArgs = ["--prebuilt", "cloud-sql-postgres-admin"];
+
+function getToolboxPath() {
+    if (process.env.GEMINI_CLI === '1') {
+        const localPath = path.resolve(__dirname, '../../../toolbox');
+        if (fs.existsSync(localPath)) {
+            return localPath;
+        }
+    }
+    try {
+        const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
+        const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
+        if (globalPath) {
+            return globalPath.split('\n')[0].trim();
+        }
+        throw new Error("Toolbox binary not found");
+    } catch (e) {
+        throw new Error("Toolbox binary not found");
+    }
+}
+
+let toolboxBinary;
+try {
+    toolboxBinary = getToolboxPath();
+} catch (err) {
+    console.error("Error:", err.message);
+    process.exit(1);
+}
+
+function getEnv() {
+    const envPath = path.resolve(__dirname, '../../../.env');
+    const env = { ...process.env };
+    if (fs.existsSync(envPath)) {
+        const envContent = fs.readFileSync(envPath, 'utf-8');
+        envContent.split('\n').forEach(line => {
+            const trimmed = line.trim();
+            if (trimmed && !trimmed.startsWith('#')) {
+                const splitIdx = trimmed.indexOf('=');
+                if (splitIdx !== -1) {
+                    const key = trimmed.slice(0, splitIdx).trim();
+                    let value = trimmed.slice(splitIdx + 1).trim();
+                    value = value.replace(/(^['"]|['"]$)/g, '');
+                    if (env[key] === undefined) {
+                        env[key] = value;
+                    }
+                }
+            }
+        });
+    }
+    return env;
+}
+
+let env = process.env;
+if (process.env.GEMINI_CLI === '1') {
+    env = getEnv();
+}
+
+const args = process.argv.slice(2);
+const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, ...args];
+
+const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
+
+child.on('close', (code) => {
+  process.exit(code);
+});
+
+child.on('error', (err) => {
+  console.error("Error executing toolbox:", err);
+  process.exit(1);
+});

From b0e9a8fda0509425e1c1676c68fb5282b7f0b9d1 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 15:30:36 +0530
Subject: [PATCH 07/13] load env vars for skill exec

---
 skills/cloudsql-postgres-admin/scripts/clone_instance.js        | 2 ++
 skills/cloudsql-postgres-admin/scripts/create_backup.js         | 2 ++
 skills/cloudsql-postgres-admin/scripts/create_database.js       | 2 ++
 skills/cloudsql-postgres-admin/scripts/create_instance.js       | 2 ++
 skills/cloudsql-postgres-admin/scripts/create_user.js           | 2 ++
 skills/cloudsql-postgres-admin/scripts/get_instance.js          | 2 ++
 skills/cloudsql-postgres-admin/scripts/list_databases.js        | 2 ++
 skills/cloudsql-postgres-admin/scripts/list_instances.js        | 2 ++
 .../scripts/postgres_upgrade_precheck.js                        | 2 ++
 skills/cloudsql-postgres-admin/scripts/restore_backup.js        | 2 ++
 skills/cloudsql-postgres-admin/scripts/wait_for_operation.js    | 2 ++
 11 files changed, 22 insertions(+)

diff --git a/skills/cloudsql-postgres-admin/scripts/clone_instance.js b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
index b324dab..11d913f 100755
--- a/skills/cloudsql-postgres-admin/scripts/clone_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_backup.js b/skills/cloudsql-postgres-admin/scripts/create_backup.js
index ca380e5..35c92f1 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_backup.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_backup.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_database.js b/skills/cloudsql-postgres-admin/scripts/create_database.js
index 3d00b5b..76bd230 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_database.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_database.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_instance.js b/skills/cloudsql-postgres-admin/scripts/create_instance.js
index 48e8a55..68b5033 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_instance.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_user.js b/skills/cloudsql-postgres-admin/scripts/create_user.js
index 3fca27c..d10842e 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_user.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_user.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/get_instance.js b/skills/cloudsql-postgres-admin/scripts/get_instance.js
index 4d2d9cb..9bcf6d7 100755
--- a/skills/cloudsql-postgres-admin/scripts/get_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/get_instance.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/list_databases.js b/skills/cloudsql-postgres-admin/scripts/list_databases.js
index b019476..2946632 100755
--- a/skills/cloudsql-postgres-admin/scripts/list_databases.js
+++ b/skills/cloudsql-postgres-admin/scripts/list_databases.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/list_instances.js b/skills/cloudsql-postgres-admin/scripts/list_instances.js
index 24504d8..44f1f71 100755
--- a/skills/cloudsql-postgres-admin/scripts/list_instances.js
+++ b/skills/cloudsql-postgres-admin/scripts/list_instances.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
index 4f3e6a2..e60e348 100755
--- a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
+++ b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/restore_backup.js b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
index 74019e2..15df89d 100755
--- a/skills/cloudsql-postgres-admin/scripts/restore_backup.js
+++ b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');
diff --git a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
index ca1b273..d398624 100755
--- a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
+++ b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
@@ -14,6 +14,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+require('./load_env');
+
 const { spawn, execSync } = require('child_process');
 const path = require('path');
 const fs = require('fs');

From 8b0963605500f93b7be38a81ebb132dfe103b26a Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 15:42:13 +0530
Subject: [PATCH 08/13] update load_env file

---
 .../scripts/load_env.js                       | 95 +++++++------------
 skills/cloudsql-postgres/scripts/load_env.js  | 95 +++++++------------
 2 files changed, 70 insertions(+), 120 deletions(-)

diff --git a/skills/cloudsql-postgres-admin/scripts/load_env.js b/skills/cloudsql-postgres-admin/scripts/load_env.js
index 67617bf..c7fb464 100644
--- a/skills/cloudsql-postgres-admin/scripts/load_env.js
+++ b/skills/cloudsql-postgres-admin/scripts/load_env.js
@@ -18,74 +18,49 @@ const fs = require('fs');
 const path = require('path');
 const os = require('os');
 
+function parseEnvFile(filePath) {
+  if (!fs.existsSync(filePath)) return {};
+  const content = fs.readFileSync(filePath, 'utf8');
+  
+  return content.split(/\r?\n/).reduce((acc, line) => {
+    const trimmed = line.trim();
+    if (!trimmed || trimmed.startsWith('#')) return acc;
+
+    const [key, ...valueParts] = trimmed.split('=');
+    if (!key) return acc;
+
+    let value = valueParts.join('=').trim().replace(/^(['"])(.*)\1$/, '$2');
+    acc[key.trim()] = value;
+    return acc;
+  }, {});
+}
+
 function loadEnv() {
   try {
-    // Check if a local .env exists in the current working directory of the project
-    const localEnvPath = path.resolve(process.cwd(), '.env');
-    if (fs.existsSync(localEnvPath)) {
-      parseAndSetEnv(localEnvPath);
-    }
-
-    // Resolve the extension name from gemini-extension.json
-    // Fallback to 'cloud-sql-postgresql' if we can't find it
     let extensionName = 'cloud-sql-postgresql';
-    try {
-      const projectRoot = path.resolve(__dirname, '../../..');
-      const manifestPath = path.join(projectRoot, 'gemini-extension.json');
-      if (fs.existsSync(manifestPath)) {
-        const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
-        if (manifest.name) {
-          extensionName = manifest.name;
-        }
-      }
-    } catch (e) {
-      // Ignore parsing errors, fallback is fine
+    const projectRoot = path.resolve(__dirname, '../../..');
+    const manifestPath = path.join(projectRoot, 'gemini-extension.json');
+
+    // Resolve Extension Name
+    if (fs.existsSync(manifestPath)) {
+      const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
+      extensionName = manifest.name || extensionName;
     }
 
-    // Load from ~/.gemini/extensions/<name>/.env
-    const homeDir = os.homedir();
-    const geminiEnvPath = path.join(homeDir, '.gemini', 'extensions', extensionName, '.env');
-    if (fs.existsSync(geminiEnvPath)) {
-      parseAndSetEnv(geminiEnvPath);
+    // Define Paths
+    const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
+    const localPath = path.join(projectRoot, '.env'); // .env
+
+    // Merge Environments (Global < Local)
+    const finalEnv = { ...parseEnvFile(globalPath), ...parseEnvFile(localPath) };
+
+    // Apply to process.env without overwriting existing shell vars
+    for (const [key, value] of Object.entries(finalEnv)) {
+      if (!(key in process.env)) process.env[key] = value;
     }
   } catch (err) {
     console.error("Warning: Failed to load extension environment variables:", err.message);
   }
 }
 
-function parseAndSetEnv(envPath) {
-  const envFileContent = fs.readFileSync(envPath, 'utf8');
-  const lines = envFileContent.split(/\r?\n/);
-  
-  for (const line of lines) {
-    const trimmedLine = line.trim();
-    // Ignore empty lines and comments
-    if (!trimmedLine || trimmedLine.startsWith('#')) {
-      continue;
-    }
-    
-    // Parse KEY=VALUE
-    const equalSignIndex = trimmedLine.indexOf('=');
-    if (equalSignIndex === -1) {
-      continue;
-    }
-    
-    const key = trimmedLine.substring(0, equalSignIndex).trim();
-    let value = trimmedLine.substring(equalSignIndex + 1).trim();
-    
-    // Remove surrounding quotes if present
-    if (value.startsWith('"') && value.endsWith('"')) {
-      value = value.substring(1, value.length - 1);
-    } else if (value.startsWith("'") && value.endsWith("'")) {
-      value = value.substring(1, value.length - 1);
-    }
-    
-    // Set if not already defined in process.env
-    if (key && process.env[key] === undefined) {
-      process.env[key] = value;
-    }
-  }
-}
-
-// Execute immediately when required
-loadEnv();
+loadEnv();
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/scripts/load_env.js b/skills/cloudsql-postgres/scripts/load_env.js
index 67617bf..c7fb464 100644
--- a/skills/cloudsql-postgres/scripts/load_env.js
+++ b/skills/cloudsql-postgres/scripts/load_env.js
@@ -18,74 +18,49 @@ const fs = require('fs');
 const path = require('path');
 const os = require('os');
 
+function parseEnvFile(filePath) {
+  if (!fs.existsSync(filePath)) return {};
+  const content = fs.readFileSync(filePath, 'utf8');
+  
+  return content.split(/\r?\n/).reduce((acc, line) => {
+    const trimmed = line.trim();
+    if (!trimmed || trimmed.startsWith('#')) return acc;
+
+    const [key, ...valueParts] = trimmed.split('=');
+    if (!key) return acc;
+
+    let value = valueParts.join('=').trim().replace(/^(['"])(.*)\1$/, '$2');
+    acc[key.trim()] = value;
+    return acc;
+  }, {});
+}
+
 function loadEnv() {
   try {
-    // Check if a local .env exists in the current working directory of the project
-    const localEnvPath = path.resolve(process.cwd(), '.env');
-    if (fs.existsSync(localEnvPath)) {
-      parseAndSetEnv(localEnvPath);
-    }
-
-    // Resolve the extension name from gemini-extension.json
-    // Fallback to 'cloud-sql-postgresql' if we can't find it
     let extensionName = 'cloud-sql-postgresql';
-    try {
-      const projectRoot = path.resolve(__dirname, '../../..');
-      const manifestPath = path.join(projectRoot, 'gemini-extension.json');
-      if (fs.existsSync(manifestPath)) {
-        const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
-        if (manifest.name) {
-          extensionName = manifest.name;
-        }
-      }
-    } catch (e) {
-      // Ignore parsing errors, fallback is fine
+    const projectRoot = path.resolve(__dirname, '../../..');
+    const manifestPath = path.join(projectRoot, 'gemini-extension.json');
+
+    // Resolve Extension Name
+    if (fs.existsSync(manifestPath)) {
+      const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
+      extensionName = manifest.name || extensionName;
     }
 
-    // Load from ~/.gemini/extensions/<name>/.env
-    const homeDir = os.homedir();
-    const geminiEnvPath = path.join(homeDir, '.gemini', 'extensions', extensionName, '.env');
-    if (fs.existsSync(geminiEnvPath)) {
-      parseAndSetEnv(geminiEnvPath);
+    // Define Paths
+    const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
+    const localPath = path.join(projectRoot, '.env'); // .env
+
+    // Merge Environments (Global < Local)
+    const finalEnv = { ...parseEnvFile(globalPath), ...parseEnvFile(localPath) };
+
+    // Apply to process.env without overwriting existing shell vars
+    for (const [key, value] of Object.entries(finalEnv)) {
+      if (!(key in process.env)) process.env[key] = value;
     }
   } catch (err) {
     console.error("Warning: Failed to load extension environment variables:", err.message);
   }
 }
 
-function parseAndSetEnv(envPath) {
-  const envFileContent = fs.readFileSync(envPath, 'utf8');
-  const lines = envFileContent.split(/\r?\n/);
-  
-  for (const line of lines) {
-    const trimmedLine = line.trim();
-    // Ignore empty lines and comments
-    if (!trimmedLine || trimmedLine.startsWith('#')) {
-      continue;
-    }
-    
-    // Parse KEY=VALUE
-    const equalSignIndex = trimmedLine.indexOf('=');
-    if (equalSignIndex === -1) {
-      continue;
-    }
-    
-    const key = trimmedLine.substring(0, equalSignIndex).trim();
-    let value = trimmedLine.substring(equalSignIndex + 1).trim();
-    
-    // Remove surrounding quotes if present
-    if (value.startsWith('"') && value.endsWith('"')) {
-      value = value.substring(1, value.length - 1);
-    } else if (value.startsWith("'") && value.endsWith("'")) {
-      value = value.substring(1, value.length - 1);
-    }
-    
-    // Set if not already defined in process.env
-    if (key && process.env[key] === undefined) {
-      process.env[key] = value;
-    }
-  }
-}
-
-// Execute immediately when required
-loadEnv();
+loadEnv();
\ No newline at end of file

From 5d252d6214f8988b7084f4b3977a680865da649f Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 15:59:50 +0530
Subject: [PATCH 09/13] check for env at three different places

---
 skills/cloudsql-postgres-admin/scripts/load_env.js | 11 ++++++++---
 skills/cloudsql-postgres/scripts/load_env.js       | 11 ++++++++---
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/skills/cloudsql-postgres-admin/scripts/load_env.js b/skills/cloudsql-postgres-admin/scripts/load_env.js
index c7fb464..5c703e3 100644
--- a/skills/cloudsql-postgres-admin/scripts/load_env.js
+++ b/skills/cloudsql-postgres-admin/scripts/load_env.js
@@ -49,10 +49,15 @@ function loadEnv() {
 
     // Define Paths
     const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
-    const localPath = path.join(projectRoot, '.env'); // .env
+    const localPath = path.join(projectRoot, '.env'); // cloud-sql-postgresql/.env
+    const cwdPath = path.resolve(process.cwd(), '.env'); // <cwd>/.env
 
-    // Merge Environments (Global < Local)
-    const finalEnv = { ...parseEnvFile(globalPath), ...parseEnvFile(localPath) };
+    // Merge Environments (Global < Extension Root < User Working Directory)
+    const finalEnv = { 
+      ...parseEnvFile(globalPath), 
+      ...parseEnvFile(localPath),
+      ...(cwdPath !== localPath ? parseEnvFile(cwdPath) : {})
+    };
 
     // Apply to process.env without overwriting existing shell vars
     for (const [key, value] of Object.entries(finalEnv)) {
diff --git a/skills/cloudsql-postgres/scripts/load_env.js b/skills/cloudsql-postgres/scripts/load_env.js
index c7fb464..5c703e3 100644
--- a/skills/cloudsql-postgres/scripts/load_env.js
+++ b/skills/cloudsql-postgres/scripts/load_env.js
@@ -49,10 +49,15 @@ function loadEnv() {
 
     // Define Paths
     const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
-    const localPath = path.join(projectRoot, '.env'); // .env
+    const localPath = path.join(projectRoot, '.env'); // cloud-sql-postgresql/.env
+    const cwdPath = path.resolve(process.cwd(), '.env'); // <cwd>/.env
 
-    // Merge Environments (Global < Local)
-    const finalEnv = { ...parseEnvFile(globalPath), ...parseEnvFile(localPath) };
+    // Merge Environments (Global < Extension Root < User Working Directory)
+    const finalEnv = { 
+      ...parseEnvFile(globalPath), 
+      ...parseEnvFile(localPath),
+      ...(cwdPath !== localPath ? parseEnvFile(cwdPath) : {})
+    };
 
     // Apply to process.env without overwriting existing shell vars
     for (const [key, value] of Object.entries(finalEnv)) {

From 741c9adb6453ce5d8cf75341ae18628fadb4af2a Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 21:11:26 +0530
Subject: [PATCH 10/13] remove load env file

---
 .../scripts/clone_instance.js                 |  2 +-
 .../scripts/create_backup.js                  |  2 +-
 .../scripts/create_database.js                |  2 +-
 .../scripts/create_instance.js                |  2 +-
 .../scripts/create_user.js                    |  2 +-
 .../scripts/get_instance.js                   |  2 +-
 .../scripts/list_databases.js                 |  2 +-
 .../scripts/list_instances.js                 |  2 +-
 .../scripts/load_env.js                       | 71 -------------------
 .../scripts/postgres_upgrade_precheck.js      |  2 +-
 .../scripts/restore_backup.js                 |  2 +-
 .../scripts/wait_for_operation.js             |  2 +-
 .../scripts/database_overview.js              |  2 +-
 .../cloudsql-postgres/scripts/execute_sql.js  |  2 +-
 .../scripts/get_column_cardinality.js         |  2 +-
 .../scripts/get_query_plan.js                 |  2 +-
 .../scripts/list_active_queries.js            |  2 +-
 .../scripts/list_autovacuum_configurations.js |  2 +-
 .../scripts/list_available_extensions.js      |  2 +-
 .../scripts/list_database_stats.js            |  2 +-
 .../cloudsql-postgres/scripts/list_indexes.js |  2 +-
 .../scripts/list_installed_extensions.js      |  2 +-
 .../scripts/list_invalid_indexes.js           |  2 +-
 .../cloudsql-postgres/scripts/list_locks.js   |  2 +-
 .../scripts/list_memory_configurations.js     |  2 +-
 .../scripts/list_pg_settings.js               |  2 +-
 .../scripts/list_publication_tables.js        |  2 +-
 .../scripts/list_query_stats.js               |  2 +-
 .../scripts/list_replication_slots.js         |  2 +-
 .../cloudsql-postgres/scripts/list_roles.js   |  2 +-
 .../cloudsql-postgres/scripts/list_schemas.js |  2 +-
 .../scripts/list_sequences.js                 |  2 +-
 .../scripts/list_stored_procedure.js          |  2 +-
 .../scripts/list_table_stats.js               |  2 +-
 .../cloudsql-postgres/scripts/list_tables.js  |  2 +-
 .../scripts/list_tablespaces.js               |  2 +-
 .../scripts/list_top_bloated_tables.js        |  2 +-
 .../scripts/list_triggers.js                  |  2 +-
 .../cloudsql-postgres/scripts/list_views.js   |  2 +-
 skills/cloudsql-postgres/scripts/load_env.js  | 71 -------------------
 .../scripts/long_running_transactions.js      |  2 +-
 .../scripts/replication_stats.js              |  2 +-
 42 files changed, 40 insertions(+), 182 deletions(-)
 delete mode 100644 skills/cloudsql-postgres-admin/scripts/load_env.js
 delete mode 100644 skills/cloudsql-postgres/scripts/load_env.js

diff --git a/skills/cloudsql-postgres-admin/scripts/clone_instance.js b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
index 11d913f..df3f6aa 100755
--- a/skills/cloudsql-postgres-admin/scripts/clone_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/clone_instance.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_backup.js b/skills/cloudsql-postgres-admin/scripts/create_backup.js
index 35c92f1..bde7983 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_backup.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_backup.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_database.js b/skills/cloudsql-postgres-admin/scripts/create_database.js
index 76bd230..b3ab345 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_database.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_database.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_instance.js b/skills/cloudsql-postgres-admin/scripts/create_instance.js
index 68b5033..776fe06 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_instance.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/create_user.js b/skills/cloudsql-postgres-admin/scripts/create_user.js
index d10842e..601d592 100755
--- a/skills/cloudsql-postgres-admin/scripts/create_user.js
+++ b/skills/cloudsql-postgres-admin/scripts/create_user.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/get_instance.js b/skills/cloudsql-postgres-admin/scripts/get_instance.js
index 9bcf6d7..a7113f5 100755
--- a/skills/cloudsql-postgres-admin/scripts/get_instance.js
+++ b/skills/cloudsql-postgres-admin/scripts/get_instance.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/list_databases.js b/skills/cloudsql-postgres-admin/scripts/list_databases.js
index 2946632..d5173b1 100755
--- a/skills/cloudsql-postgres-admin/scripts/list_databases.js
+++ b/skills/cloudsql-postgres-admin/scripts/list_databases.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/list_instances.js b/skills/cloudsql-postgres-admin/scripts/list_instances.js
index 44f1f71..557af1c 100755
--- a/skills/cloudsql-postgres-admin/scripts/list_instances.js
+++ b/skills/cloudsql-postgres-admin/scripts/list_instances.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/load_env.js b/skills/cloudsql-postgres-admin/scripts/load_env.js
deleted file mode 100644
index 5c703e3..0000000
--- a/skills/cloudsql-postgres-admin/scripts/load_env.js
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env node
-
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-const fs = require('fs');
-const path = require('path');
-const os = require('os');
-
-function parseEnvFile(filePath) {
-  if (!fs.existsSync(filePath)) return {};
-  const content = fs.readFileSync(filePath, 'utf8');
-  
-  return content.split(/\r?\n/).reduce((acc, line) => {
-    const trimmed = line.trim();
-    if (!trimmed || trimmed.startsWith('#')) return acc;
-
-    const [key, ...valueParts] = trimmed.split('=');
-    if (!key) return acc;
-
-    let value = valueParts.join('=').trim().replace(/^(['"])(.*)\1$/, '$2');
-    acc[key.trim()] = value;
-    return acc;
-  }, {});
-}
-
-function loadEnv() {
-  try {
-    let extensionName = 'cloud-sql-postgresql';
-    const projectRoot = path.resolve(__dirname, '../../..');
-    const manifestPath = path.join(projectRoot, 'gemini-extension.json');
-
-    // Resolve Extension Name
-    if (fs.existsSync(manifestPath)) {
-      const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
-      extensionName = manifest.name || extensionName;
-    }
-
-    // Define Paths
-    const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
-    const localPath = path.join(projectRoot, '.env'); // cloud-sql-postgresql/.env
-    const cwdPath = path.resolve(process.cwd(), '.env'); // <cwd>/.env
-
-    // Merge Environments (Global < Extension Root < User Working Directory)
-    const finalEnv = { 
-      ...parseEnvFile(globalPath), 
-      ...parseEnvFile(localPath),
-      ...(cwdPath !== localPath ? parseEnvFile(cwdPath) : {})
-    };
-
-    // Apply to process.env without overwriting existing shell vars
-    for (const [key, value] of Object.entries(finalEnv)) {
-      if (!(key in process.env)) process.env[key] = value;
-    }
-  } catch (err) {
-    console.error("Warning: Failed to load extension environment variables:", err.message);
-  }
-}
-
-loadEnv();
\ No newline at end of file
diff --git a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
index e60e348..3d94b38 100755
--- a/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
+++ b/skills/cloudsql-postgres-admin/scripts/postgres_upgrade_precheck.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/restore_backup.js b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
index 15df89d..aa6105e 100755
--- a/skills/cloudsql-postgres-admin/scripts/restore_backup.js
+++ b/skills/cloudsql-postgres-admin/scripts/restore_backup.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
index d398624..24247a2 100755
--- a/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
+++ b/skills/cloudsql-postgres-admin/scripts/wait_for_operation.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/database_overview.js b/skills/cloudsql-postgres/scripts/database_overview.js
index 7da0abd..c7e43ea 100755
--- a/skills/cloudsql-postgres/scripts/database_overview.js
+++ b/skills/cloudsql-postgres/scripts/database_overview.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/execute_sql.js b/skills/cloudsql-postgres/scripts/execute_sql.js
index f6cd8c8..a30ae4e 100755
--- a/skills/cloudsql-postgres/scripts/execute_sql.js
+++ b/skills/cloudsql-postgres/scripts/execute_sql.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/get_column_cardinality.js b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
index e8cd9ec..12e429e 100755
--- a/skills/cloudsql-postgres/scripts/get_column_cardinality.js
+++ b/skills/cloudsql-postgres/scripts/get_column_cardinality.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/get_query_plan.js b/skills/cloudsql-postgres/scripts/get_query_plan.js
index 9c42fe5..583f943 100755
--- a/skills/cloudsql-postgres/scripts/get_query_plan.js
+++ b/skills/cloudsql-postgres/scripts/get_query_plan.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_active_queries.js b/skills/cloudsql-postgres/scripts/list_active_queries.js
index 414c0a9..70f03c4 100755
--- a/skills/cloudsql-postgres/scripts/list_active_queries.js
+++ b/skills/cloudsql-postgres/scripts/list_active_queries.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
index 421eb21..c3a3353 100755
--- a/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_autovacuum_configurations.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_available_extensions.js b/skills/cloudsql-postgres/scripts/list_available_extensions.js
index c348fbf..23039d2 100755
--- a/skills/cloudsql-postgres/scripts/list_available_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_available_extensions.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_database_stats.js b/skills/cloudsql-postgres/scripts/list_database_stats.js
index db3e209..e01362d 100755
--- a/skills/cloudsql-postgres/scripts/list_database_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_database_stats.js
@@ -2,7 +2,7 @@
 
 // Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the "License");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an "AS IS" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_indexes.js b/skills/cloudsql-postgres/scripts/list_indexes.js
index bd0ff0b..44579bb 100755
--- a/skills/cloudsql-postgres/scripts/list_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_indexes.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_installed_extensions.js b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
index 22e1d44..e6a9eea 100755
--- a/skills/cloudsql-postgres/scripts/list_installed_extensions.js
+++ b/skills/cloudsql-postgres/scripts/list_installed_extensions.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
index 0894730..274e514 100755
--- a/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
+++ b/skills/cloudsql-postgres/scripts/list_invalid_indexes.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_locks.js b/skills/cloudsql-postgres/scripts/list_locks.js
index 34f6ef4..b2056e6 100755
--- a/skills/cloudsql-postgres/scripts/list_locks.js
+++ b/skills/cloudsql-postgres/scripts/list_locks.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_memory_configurations.js b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
index d57cfcf..31fef99 100755
--- a/skills/cloudsql-postgres/scripts/list_memory_configurations.js
+++ b/skills/cloudsql-postgres/scripts/list_memory_configurations.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_pg_settings.js b/skills/cloudsql-postgres/scripts/list_pg_settings.js
index 39500f7..6d1d73d 100755
--- a/skills/cloudsql-postgres/scripts/list_pg_settings.js
+++ b/skills/cloudsql-postgres/scripts/list_pg_settings.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_publication_tables.js b/skills/cloudsql-postgres/scripts/list_publication_tables.js
index 1b28833..398d792 100755
--- a/skills/cloudsql-postgres/scripts/list_publication_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_publication_tables.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_query_stats.js b/skills/cloudsql-postgres/scripts/list_query_stats.js
index c93428b..61f2277 100755
--- a/skills/cloudsql-postgres/scripts/list_query_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_query_stats.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_replication_slots.js b/skills/cloudsql-postgres/scripts/list_replication_slots.js
index 5323ef5..946a6bd 100755
--- a/skills/cloudsql-postgres/scripts/list_replication_slots.js
+++ b/skills/cloudsql-postgres/scripts/list_replication_slots.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_roles.js b/skills/cloudsql-postgres/scripts/list_roles.js
index 637086b..35e1107 100755
--- a/skills/cloudsql-postgres/scripts/list_roles.js
+++ b/skills/cloudsql-postgres/scripts/list_roles.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_schemas.js b/skills/cloudsql-postgres/scripts/list_schemas.js
index 057cca4..1851d85 100755
--- a/skills/cloudsql-postgres/scripts/list_schemas.js
+++ b/skills/cloudsql-postgres/scripts/list_schemas.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_sequences.js b/skills/cloudsql-postgres/scripts/list_sequences.js
index 15f223f..39cc4ba 100755
--- a/skills/cloudsql-postgres/scripts/list_sequences.js
+++ b/skills/cloudsql-postgres/scripts/list_sequences.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_stored_procedure.js b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
index a73ebb4..2399cb5 100755
--- a/skills/cloudsql-postgres/scripts/list_stored_procedure.js
+++ b/skills/cloudsql-postgres/scripts/list_stored_procedure.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_table_stats.js b/skills/cloudsql-postgres/scripts/list_table_stats.js
index e83fec3..ef37260 100755
--- a/skills/cloudsql-postgres/scripts/list_table_stats.js
+++ b/skills/cloudsql-postgres/scripts/list_table_stats.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_tables.js b/skills/cloudsql-postgres/scripts/list_tables.js
index 4363750..4778f19 100755
--- a/skills/cloudsql-postgres/scripts/list_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_tables.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_tablespaces.js b/skills/cloudsql-postgres/scripts/list_tablespaces.js
index 1012258..1fa3780 100755
--- a/skills/cloudsql-postgres/scripts/list_tablespaces.js
+++ b/skills/cloudsql-postgres/scripts/list_tablespaces.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
index 107a4e0..739dc2a 100755
--- a/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
+++ b/skills/cloudsql-postgres/scripts/list_top_bloated_tables.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_triggers.js b/skills/cloudsql-postgres/scripts/list_triggers.js
index 188f9f3..cf83929 100755
--- a/skills/cloudsql-postgres/scripts/list_triggers.js
+++ b/skills/cloudsql-postgres/scripts/list_triggers.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/list_views.js b/skills/cloudsql-postgres/scripts/list_views.js
index e80d689..1483738 100755
--- a/skills/cloudsql-postgres/scripts/list_views.js
+++ b/skills/cloudsql-postgres/scripts/list_views.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/load_env.js b/skills/cloudsql-postgres/scripts/load_env.js
deleted file mode 100644
index 5c703e3..0000000
--- a/skills/cloudsql-postgres/scripts/load_env.js
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env node
-
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-const fs = require('fs');
-const path = require('path');
-const os = require('os');
-
-function parseEnvFile(filePath) {
-  if (!fs.existsSync(filePath)) return {};
-  const content = fs.readFileSync(filePath, 'utf8');
-  
-  return content.split(/\r?\n/).reduce((acc, line) => {
-    const trimmed = line.trim();
-    if (!trimmed || trimmed.startsWith('#')) return acc;
-
-    const [key, ...valueParts] = trimmed.split('=');
-    if (!key) return acc;
-
-    let value = valueParts.join('=').trim().replace(/^(['"])(.*)\1$/, '$2');
-    acc[key.trim()] = value;
-    return acc;
-  }, {});
-}
-
-function loadEnv() {
-  try {
-    let extensionName = 'cloud-sql-postgresql';
-    const projectRoot = path.resolve(__dirname, '../../..');
-    const manifestPath = path.join(projectRoot, 'gemini-extension.json');
-
-    // Resolve Extension Name
-    if (fs.existsSync(manifestPath)) {
-      const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
-      extensionName = manifest.name || extensionName;
-    }
-
-    // Define Paths
-    const globalPath = path.join(os.homedir(), '.gemini', 'extensions', extensionName, '.env'); // ~/.gemini/extensions/<name>/.env
-    const localPath = path.join(projectRoot, '.env'); // cloud-sql-postgresql/.env
-    const cwdPath = path.resolve(process.cwd(), '.env'); // <cwd>/.env
-
-    // Merge Environments (Global < Extension Root < User Working Directory)
-    const finalEnv = { 
-      ...parseEnvFile(globalPath), 
-      ...parseEnvFile(localPath),
-      ...(cwdPath !== localPath ? parseEnvFile(cwdPath) : {})
-    };
-
-    // Apply to process.env without overwriting existing shell vars
-    for (const [key, value] of Object.entries(finalEnv)) {
-      if (!(key in process.env)) process.env[key] = value;
-    }
-  } catch (err) {
-    console.error("Warning: Failed to load extension environment variables:", err.message);
-  }
-}
-
-loadEnv();
\ No newline at end of file
diff --git a/skills/cloudsql-postgres/scripts/long_running_transactions.js b/skills/cloudsql-postgres/scripts/long_running_transactions.js
index 53118a2..b16afb1 100755
--- a/skills/cloudsql-postgres/scripts/long_running_transactions.js
+++ b/skills/cloudsql-postgres/scripts/long_running_transactions.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');
diff --git a/skills/cloudsql-postgres/scripts/replication_stats.js b/skills/cloudsql-postgres/scripts/replication_stats.js
index 4cf1730..4bc4d7e 100755
--- a/skills/cloudsql-postgres/scripts/replication_stats.js
+++ b/skills/cloudsql-postgres/scripts/replication_stats.js
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-require('./load_env');
+
 
 const { spawn, execSync } = require('child_process');
 const path = require('path');

From ffdaa8ee034d16ef5b56d2b6524a5d89402cd3ec Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Tue, 10 Mar 2026 21:14:00 +0530
Subject: [PATCH 11/13] add note to skill.md

---
 skills/cloudsql-postgres-admin/SKILL.md | 2 ++
 skills/cloudsql-postgres/SKILL.md       | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/skills/cloudsql-postgres-admin/SKILL.md b/skills/cloudsql-postgres-admin/SKILL.md
index 4c1b10e..a308060 100644
--- a/skills/cloudsql-postgres-admin/SKILL.md
+++ b/skills/cloudsql-postgres-admin/SKILL.md
@@ -13,6 +13,8 @@ All scripts can be executed using Node.js. Replace `<param_name>` and `<param_va
 **PowerShell:**
 `node <skill_dir>/scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
 
+Note: The scripts automatically load the environment variables from various .env files. Do not ask the user to set vars unless skill executions fails due to env var absence.
+
 ## Scripts
 
 
diff --git a/skills/cloudsql-postgres/SKILL.md b/skills/cloudsql-postgres/SKILL.md
index b665d13..1f52cf0 100644
--- a/skills/cloudsql-postgres/SKILL.md
+++ b/skills/cloudsql-postgres/SKILL.md
@@ -13,6 +13,8 @@ All scripts can be executed using Node.js. Replace `<param_name>` and `<param_va
 **PowerShell:**
 `node <skill_dir>/scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`
 
+Note: The scripts automatically load the environment variables from various .env files. Do not ask the user to set vars unless skill executions fails due to env var absence.
+
 ## Scripts
 
 

From e982d817335798d0fbb47168c9794cef68007793 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <twishabansal07@gmail.com>
Date: Wed, 11 Mar 2026 10:35:53 +0530
Subject: [PATCH 12/13] update markdown file

---
 CLOUD-SQL-POSTGRESQL.md | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/CLOUD-SQL-POSTGRESQL.md b/CLOUD-SQL-POSTGRESQL.md
index 877fd18..4cf31be 100644
--- a/CLOUD-SQL-POSTGRESQL.md
+++ b/CLOUD-SQL-POSTGRESQL.md
@@ -13,7 +13,7 @@ To install this extension, the Gemini CLI version must be v0.6.0 or above. The v
 
 This section covers connecting to a Cloud SQL for PostgreSQL instance.
 
-1. **Verify Environment Variables**: The extension requires the following environment variables to be set before the Gemini CLI is started:
+1. **Extension Configuration**: This extension requires several settings (e.g., Project ID, Instance ID, Database Name, User, and Password). These values are gathered via prompts when you first install or link the extension:
 
     * `CLOUD_SQL_POSTGRES_PROJECT`: The GCP project ID.
     * `CLOUD_SQL_POSTGRES_REGION`: The region of your Cloud SQL instance.
@@ -22,6 +22,8 @@ This section covers connecting to a Cloud SQL for PostgreSQL instance.
     * `CLOUD_SQL_POSTGRES_USER`: The database username.
     * `CLOUD_SQL_POSTGRES_PASSWORD`: The password for the database user.
 
+    If you need to update any of these values later, use the `gemini extensions config cloud-sql-postgresql` command.
+
 2. **Handle Missing Variables**: If a command fails with an error message containing a placeholder like `${CLOUD_SQL_POSTGRES_PROJECT}`, it signifies a missing environment variable. Inform the user which variable is missing and instruct them to set it.
 
 3. **Handle Permission Errors**: If you encounter permission errors, ensure the user has the **Cloud SQL Client** (`roles/cloudsql.client`) role and the correct database-level permissions.
@@ -61,9 +63,9 @@ This section provides context on additional skills that can be recommended to th
 When you create a new Cloud SQL for PostgreSQL instance, or database using the available skills, the connection is not automatically established. You will need to perform the following steps:
 
 1.  **(Optional) Save your conversation:** To avoid losing your progress, save the current session by running the command: `/chat save <your-tag>`
-2.  **Stop the CLI:** Terminate the Gemini CLI.
-3.  **Update Environment Variables:** Set or update your environment variables (e.g. `CLOUD_SQL_POSTGRES_DATABASE`, `CLOUD_SQL_POSTGRES_INSTANCE`) to point to the new resource.
-4.  **Restart:** Relaunch the Gemini CLI
+2. **Stop the CLI**: Terminate the Gemini CLI.
+3. **Update Extension Configuration**: Use the command `gemini extensions config cloud-sql-postgresql` to update your settings (e.g. `CLOUD_SQL_POSTGRES_DATABASE`, `CLOUD_SQL_POSTGRES_INSTANCE`) to point to the new resource.
+4. **Restart**: Relaunch the Gemini CLI
 5.  **(Optional) Resume conversation:** Resume your conversation with the command: `/chat resume <your-tag>`
 
 **Important:** Do not assume a connection to a newly created resource is active. Always follow the steps above to reconfigure your connection.
@@ -77,8 +79,9 @@ Users may have set project environment variables:
 *   `CLOUD_SQL_POSTGRES_INSTANCE`: The ID of the Cloud SQL for PostgreSQL instance.
 *   `CLOUD_SQL_POSTGRES_DATABASE`: The name of the database.
 
-Instead of prompting the user for these values for specific skill calls, prompt the user to verify reuse a specific value.
-Make sure to not use the environment variable name like `CLOUD_SQL_POSTGRES_PROJECT`, `${CLOUD_SQL_POSTGRES_PROJECT}`, or `$CLOUD_SQL_POSTGRES_PROJECT`. The value can be found by using command: `echo $CLOUD_SQL_POSTGRES_PROJECT`.
+Instead of prompting the user for these values for specific skill calls, prompt the user to verify the reuse of a specific setting value.
+Make sure to not use the environment variable name like `CLOUD_SQL_POSTGRES_PROJECT`, `${CLOUD_SQL_POSTGRES_PROJECT}`, or `$CLOUD_SQL_POSTGRES_PROJECT`. 
+The value can be verified by the user using the `gemini extensions config cloud-sql-postgresql` command or by checking their local settings.
 
 ## Use Full Table Name Format "DATABASE_NAME.SCHEMA_NAME.TABLE_NAME"
 

From 75239cf9ae97c685af14c7760523b66071b96a14 Mon Sep 17 00:00:00 2001
From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com>
Date: Wed, 11 Mar 2026 14:26:42 +0530
Subject: [PATCH 13/13] Update DEVELOPER.md

---
 DEVELOPER.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/DEVELOPER.md b/DEVELOPER.md
index 34fe96d..07162e3 100644
--- a/DEVELOPER.md
+++ b/DEVELOPER.md
@@ -43,7 +43,7 @@ The core logic for this extension is handled by a pre-built `toolbox` binary. Th
     extension from your local directory.
 
     ```bash
-    gemini extensions link .
+    gemini extensions install .
     ```
     The CLI will prompt you to confirm the installation. Accept it to proceed.
 
