From 17118dfa28ba9f85fb2f759eca1da81e70d77a14 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Sat, 17 Oct 2026 13:11:05 -0700 Subject: [PATCH 01/13] feat(altimate-code): add experimental direct MCP data tools and dual-mode routing - `.mcp.json` starts `altimate-code mcp serve`, so Claude Code calls altimate-code's read-only data tools (warehouse_list, schema_inspect, sql_execute, sql_check, sql_materialize) directly; Claude's own model does the reasoning and no second LLM runs. - New lean `data-question` skill: inspect value profiles before choosing columns or keys, compute in the database, materialize the small side for cross-database joins, check keys/fan-out when they matter. - The `altimate-code` routing skill now answers data questions with the tools and keeps `altimate-code run` delegation for long multi-step jobs; the SessionStart hook and `/altimate` text match. - Version 1.1.0-experimental; README and CHANGELOG note it needs an altimate-code build with `mcp serve` and describe the read-only limits. Co-Authored-By: Claude Opus 5.5 --- .claude-plugin/marketplace.json | 4 +- README.md | 14 +- .../altimate-code/.claude-plugin/plugin.json | 4 +- plugins/altimate-code/.mcp.json | 8 ++ plugins/altimate-code/CHANGELOG.md | 11 ++ plugins/altimate-code/README.md | 123 +++++++++++++----- plugins/altimate-code/commands/altimate.md | 23 +++- .../hooks-handlers/session-start.sh | 12 +- plugins/altimate-code/hooks/hooks.json | 2 +- .../skills/altimate-code/SKILL.md | 85 ++++++------ .../skills/data-question/SKILL.md | 31 +++++ 11 files changed, 226 insertions(+), 91 deletions(-) create mode 100644 plugins/altimate-code/.mcp.json create mode 100644 plugins/altimate-code/skills/data-question/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 36550af..d9a6864 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,13 +6,13 @@ "url": "https://altimate.ai" }, "metadata": { - "description": "Altimate's Claude Code plugin — delegates dbt and warehouse work to the altimate-code CLI agent.", + "description": "Altimate's Claude Code plugin — direct MCP data tools and CLI delegation for long dbt and warehouse jobs.", "version": "1.0.0" }, "plugins": [ { "name": "altimate-code", - "description": "Delegates dbt and warehouse work to altimate-code, a specialized CLI agent with 100+ purpose-built data tools (SQL analysis, column-level lineage, dbt build/test/run, warehouse profiling, FinOps, connectivity to Snowflake, BigQuery, Redshift, Databricks, Postgres, MySQL, DuckDB).", + "description": "Use altimate-code data tools directly through MCP with Claude Code reasoning, or delegate long dbt and warehouse jobs to the altimate-code CLI agent.", "source": "./plugins/altimate-code", "strict": false } diff --git a/README.md b/README.md index 52a3f8e..3de28e3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,19 @@ The Altimate marketplace of Claude Code plugins. -Currently ships one plugin: **[altimate-code](./plugins/altimate-code/)** — delegates dbt and warehouse work to the [altimate-code](https://github.com/AltimateAI/altimate-code) CLI agent. +Currently ships one plugin: **[altimate-code](./plugins/altimate-code/)** — gives Claude Code direct MCP data tools from [altimate-code](https://github.com/AltimateAI/altimate-code), with CLI delegation for long dbt and warehouse jobs. + +**Experimental: requires an altimate-code build with `mcp serve`.** Claude Code +supplies the reasoning and LLM cost for direct data questions; the MCP server +runs no LLM. Tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, +and `sql_materialize` (session-local scratch DuckDB for cross-database joins). + +Source queries are read-only by default: database-enforced on Postgres, SQLite, +and DuckDB; classification-only elsewhere, so use a read-only DB user. Connections +come from project/global `.altimate-code/connections.json` and +`ALTIMATE_CODE_CONN_*` environment variables, or an explicit `--connections ` +server argument. See the [plugin README](./plugins/altimate-code/README.md) for setup, +value profiles, result spill files, and the separate LLM billing for delegated jobs. ## Install diff --git a/plugins/altimate-code/.claude-plugin/plugin.json b/plugins/altimate-code/.claude-plugin/plugin.json index ba2b6d7..25881c7 100644 --- a/plugins/altimate-code/.claude-plugin/plugin.json +++ b/plugins/altimate-code/.claude-plugin/plugin.json @@ -1,8 +1,8 @@ { "name": "altimate-code", "displayName": "Altimate Code", - "version": "1.0.0", - "description": "Delegates dbt and warehouse work to altimate-code, a specialized CLI agent with 100+ purpose-built data tools (SQL analysis, column-level lineage, dbt build/test/run, warehouse profiling, FinOps, connectivity to Snowflake, BigQuery, Redshift, Databricks, Postgres, MySQL, DuckDB).", + "version": "1.1.0-experimental", + "description": "Use altimate-code data tools directly through MCP with Claude Code reasoning, or delegate long dbt and warehouse jobs to the altimate-code CLI agent.", "author": { "name": "AltimateAI", "url": "https://altimate.ai" diff --git a/plugins/altimate-code/.mcp.json b/plugins/altimate-code/.mcp.json new file mode 100644 index 0000000..91038e3 --- /dev/null +++ b/plugins/altimate-code/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "altimate-code": { + "command": "altimate-code", + "args": ["mcp", "serve"] + } + } +} diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 51abc76..94cab92 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this plugin will be documented in this file. +## [1.1.0-experimental] — Unreleased — experimental; requires an altimate-code build with `mcp serve` + +### Added +- Stdio MCP registration for `altimate-code mcp serve`, without `--allow-write`. +- Direct data tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize`. +- Lean `data-question` skill for value-profile inspection, SQL analysis, cross-connection scratch joins, and correctness checks. + +### Changed +- Routing skill, `/altimate`, and SessionStart context use MCP directly for data questions with Claude Code reasoning; long jobs retain CLI delegation and agent-persona guidance. +- Documentation covers experimental prerequisites, connection discovery, read-only enforcement limits, local result files, and separate reasoning/billing paths. + ## [1.0.0] — 2026-07-09 ### Added diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 35ee013..82b8508 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -1,8 +1,13 @@ # Altimate Code — Claude Code plugin -Routes dbt + warehouse tasks from Claude Code to [altimate-code](https://github.com/AltimateAI/altimate-code), a specialized open-source CLI agent with 100+ deterministic data-engineering tools: SQL anti-pattern detection, column-level lineage, dbt build/test/run against real warehouses, FinOps and cost analysis, cross-dialect translation and data parity, and PII detection. +Use [altimate-code](https://github.com/AltimateAI/altimate-code) data tools directly +from Claude Code through MCP. **Claude Code does the reasoning and carries the +LLM cost** for data questions; the stdio MCP server runs no LLM. Long multi-step +jobs such as dbt project builds, migrations, and FinOps reports can still be +delegated to `altimate-code run`, which uses its own agent and configured provider. -**Why delegate?** General coding agents can edit SQL files; they can't inspect your live warehouse state. altimate-code gives Claude Code a deterministic data-engineering layer — indexed schemas, real query history, real cost data — instead of guesses. +**1.1.0-experimental: requires an altimate-code build with `mcp serve`.** This +server is in an unreleased branch; a published CLI release may not include it. ## Install @@ -13,57 +18,111 @@ Routes dbt + warehouse tasks from Claude Code to [altimate-code](https://github. ## Prerequisites -The altimate-code CLI must be installed and configured on your PATH: +Install an altimate-code build containing `mcp serve` and put `altimate-code` on +PATH where Claude Code can launch it. The CLI requires Node 20+. Check your build +with `altimate-code mcp serve --help`; an unknown command means you need a build +that includes the MCP server. Installing the latest published npm package alone +may not satisfy this experimental requirement. -```bash -npm install -g altimate-code # requires Node 20+ -altimate-code # launch the TUI, then run /connect to configure your LLM provider +Configure database connections as described below. Direct MCP use does **not** +require an altimate-code LLM provider or API key. For delegated jobs only, run +`altimate-code` to configure its provider (or use its provider environment settings). + +## How it works + +The plugin's `.mcp.json` registers the `altimate-code` stdio server by running +`altimate-code mcp serve`, without `--allow-write`. Claude calls these tools directly: + +| Tool | Purpose | +|---|---| +| `warehouse_list` | List available connections. | +| `schema_inspect` | Inspect columns and value profiles: frequency-ranked values, distinct/null counts, unique-in-sample flags, value shapes, and MongoDB nested paths. | +| `sql_execute` | Execute SQL, read-only by default. Large results spill to a local file path. | +| `sql_check` | Check keys, fan-out, grain, and nulls that could affect correctness. | +| `sql_materialize` | Copy a read-only query result from any connection into session-local `scratch` DuckDB for cross-database joins. | + +For a data question, Claude lists connections, inspects schemas and value profiles, +computes in SQL, checks correctness where needed, and returns the requested values +with a one-line basis. For cross-connection joins, it materializes the smaller +filtered side and other required inputs into `scratch`, then joins there. + +The routing skill and `/altimate ` select this direct path for answers, +numbers, and lists. Long jobs needing altimate-code's own agent use +`altimate-code run` with persona selection (`fast-edit`, `analyst`, or `builder`) +and a private output file. Delegated jobs use the CLI's separate LLM provider, +costs, and rate limits. `/review` retains the specialized dbt/SQL reviewer. +A short SessionStart hook describes these capabilities to Claude. + +## Connections + +The server uses normal altimate-code discovery: project and global +`.altimate-code/connections.json` files, and `ALTIMATE_CODE_CONN_*` environment +variables. Launch Claude Code in the intended project and make any connection +environment variables available to its MCP subprocess. + +To select a connections file explicitly, change the server's `args` in +`plugins/altimate-code/.mcp.json` (or the installed plugin's `.mcp.json`) to: + +```json +["mcp", "serve", "--connections", "/absolute/path/to/connections.json"] ``` -Or configure a provider via environment variable (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and 20+ others — see the [altimate-code docs](https://docs.altimate.sh)). +Use an absolute path to avoid working-directory ambiguity. Connection credentials +are database credentials; they are independent of an LLM provider configuration. -If altimate-code is not on PATH or not configured, the plugin surfaces the failure with fix instructions rather than silently falling back to Claude's native tools. +## Read-only default -## How it works +The plugin does not pass `--allow-write`. Read-only execution is **database-enforced +on Postgres, SQLite, and DuckDB**. Elsewhere it is **SQL-classification-only**; +use a read-only DB user to enforce the boundary in the database. This default is +not a universal database permission guarantee. The CLI supports `--allow-write` +for explicitly enabling writes, but this plugin does not enable it. -1. A **SessionStart hook** adds a static description of altimate-code's capabilities to the session, so Claude Code knows when a task fits. -2. When a data-engineering task fires the **skill** (or you invoke **`/altimate `** explicitly), Claude Code runs `altimate-code run ""` locally, selecting the cheapest suitable agent persona (`fast-edit` for dbt/SQL edits, `analyst` for aggregation-heavy correctness work, `builder` for warehouse-state investigation). -3. altimate-code plans and executes the task using your configured LLM provider. Warehouse queries, dbt commands, and file edits run **locally under your credentials**. -4. The result is written to a local output file and surfaced back in your Claude Code conversation. +`sql_materialize` copies read-only source query results into session-local +`scratch` DuckDB; that local analytical storage does not modify the source +databases. Large results can also be written to local spill files. ## Example prompts -Once installed, try these in Claude Code (or prefix any of them with `/altimate`): - -1. **Column-level lineage** — *"Trace the `revenue_usd` column in `models/marts/fct_revenue.sql` back to its sources, and list every downstream model that would be affected if I change its rounding."* -2. **Warehouse cost analysis** — *"Give me a cost report for our Snowflake account: the ten most expensive queries this month and any warehouses that look over-provisioned."* -3. **Cross-dialect validation** — *"Compare `prod.orders` in Snowflake with `analytics.orders` in BigQuery row-by-row using `id` as the key, and summarize any mismatches."* -4. **dbt test generation** — *"Generate dbt tests for `models/staging/stg_orders.sql`, including unit tests for the CASE/WHEN logic."* +- "How many orders were completed last month? Return the count and total revenue." +- "Join customer activity across our two connections and list the ten most active customers." +- "/altimate Build and test a dbt staging project for these sources." +- "/altimate Produce a warehouse FinOps report with recommendations." +- "/review Review my dbt changes." ## Data handling -Delegating a task passes your prompt text to the altimate-code CLI, which sends it to your configured LLM provider — the Altimate LLM Gateway by default, or your own provider (BYOK), in which case Altimate never sees it. Warehouse credentials and query results stay on your machine. +MCP tools run locally under your database credentials. Tool results, including +sampled values and query results Claude reads, enter the Claude Code conversation +and are handled by Claude Code's configured model/provider. The MCP server makes +no separate LLM calls. Scratch data and spilled results are local artifacts. -Full details: **[PRIVACY.md](../../PRIVACY.md)** · Security policy and disclosure: **[SECURITY.md](../../SECURITY.md)** · Terms: **[TERMS.md](../../TERMS.md)** +Delegation passes your task to `altimate-code run`; its own configured LLM +provider handles the task and any data supplied to that agent. This is a separate +provider and billing path from direct MCP use. + +See **[PRIVACY.md](../../PRIVACY.md)** for the existing delegation policy; +**[SECURITY.md](../../SECURITY.md)** and **[TERMS.md](../../TERMS.md)** also apply. ## Troubleshooting | Symptom | Fix | |---|---| -| `command not found: altimate-code` | `npm install -g altimate-code` (Node 20+), then run `altimate-code` once to configure your provider. | -| `Unauthorized` / `No provider configured` | Run `altimate-code` to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | -| Task hangs for several minutes | Open `altimate-code` to check for a pending prompt in the TUI, or re-run specifying a known-good model. | -| Empty result | The task may be too ambiguous — restate with the target table, expected columns, or time window. | -| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate-code` TUI or `profiles.yml`. | -| Plugin installed but never delegates | Confirm it's enabled: `claude plugin enable altimate-code@altimate-claude-plugin`. | - -Still stuck? See [Support](#support). +| `command not found: altimate-code` | Put a build with `mcp serve` on Claude Code's PATH. | +| Unknown `mcp` or `serve` command | Use an altimate-code build containing the unreleased MCP server. | +| No connections / database access error | Check project/global connection files, `ALTIMATE_CODE_CONN_*` environment variables, and database permissions. | +| `Unauthorized` / `No provider configured` from a delegated job | Configure the CLI's LLM provider; direct MCP data questions do not need it. | +| Delegated job hangs or returns no output | Check the CLI TUI for pending prompts and provide a precise target and expected result. | +| Plugin unavailable | Confirm it is enabled: `claude plugin enable altimate-code@altimate-claude-plugin`. | ## Components -- **Skill** — `skills/altimate-code/SKILL.md` — delegation logic and agent-persona selection -- **Command** — `commands/altimate.md` — `/altimate` slash command for explicit delegation -- **Hook** — `hooks/hooks.json` — SessionStart capability description (static text only) +- **MCP server** — `.mcp.json` — direct stdio data tools +- **Routing skill** — `skills/altimate-code/SKILL.md` — direct questions or CLI delegation +- **Data-question skill** — `skills/data-question/SKILL.md` — concise analysis workflow +- **Review skill** — `skills/review/SKILL.md` — specialized dbt/SQL review +- **Commands** — `commands/altimate.md` and `commands/review.md` +- **Hook** — `hooks/hooks.json` and `hooks-handlers/session-start.sh` ## Support diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index ee80180..f2b8e6f 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -1,11 +1,19 @@ --- -description: Delegate a task to altimate-code, the specialised data-engineering CLI agent (warehouse access, column-level lineage, cross-DB, FinOps, query optimization) +description: Answer data questions with altimate-code MCP tools or delegate long dbt and warehouse jobs to its CLI agent. argument-hint: --- -The user explicitly invoked `/altimate` to delegate this task to altimate-code. You MUST run the task via the `altimate-code` CLI — do NOT attempt the work with native `Bash`/`Edit`/`Write` tools. +The user invoked `/altimate` to use altimate-code for this task. For a data +question requesting answers, numbers, or lists, use the `altimate-code` MCP tools +directly and follow the `data-question` skill. Claude Code does the reasoning; +do not invoke `altimate-code run` or require its LLM provider for this path. +If MCP is unavailable, report the error and the requirement for a build with +`mcp serve` and configured connections; do not silently delegate instead. -Workflow (follow in order, no skipping): +For a long multi-step job needing altimate-code's own agent (such as a dbt project +build, migration, or FinOps report), use the delegation workflow below. + +Delegation workflow (follow in order): 1. **Verify altimate-code is installed:** ```bash @@ -18,14 +26,15 @@ Workflow (follow in order, no skipping): | Task shape | Use `--agent` | |---|---| - | Any dbt / SQL task (rename, refactor, create, debug, structural) | `fast-edit` (default) | + | Delegated dbt / SQL project job (rename, refactor, create, debug, structural) | `fast-edit` (default) | | Aggregation correctness on multi-table joins | `analyst` if fast-edit fails the user's verification | | Warehouse-state work (lineage, cost, parity, schema diff, PII, FinOps) | `builder` | | Vague debug ("X is broken") | **Stop — ask the user for the specific error before delegating.** | - Decision rule: start with `fast-edit`. Only use `analyst` / `builder` when the cheap path fails for a documented reason. + Decision rule: start with `fast-edit` for delegated dbt/SQL project jobs; use `analyst` after correctness verification fails, and `builder` for warehouse-state jobs. Data questions use MCP regardless of join complexity. -3. **Run altimate-code with the chosen agent.** Pass `$ARGUMENTS` through a +3. **Run altimate-code with the chosen agent.** Choose a here-doc delimiter that + does not occur as a standalone line in the task. Pass `$ARGUMENTS` through a here-doc into a variable so the shell never command-substitutes anything the user typed, and write the result to a private `mktemp` file (not a shared `/tmp/altimate-result.md` — concurrent invocations clobber each other and a @@ -65,4 +74,4 @@ Workflow (follow in order, no skipping): 5. **On any altimate-code error** (`Unauthorized`, `Token limit reached`, `No provider configured`, warehouse credentials wrong, process timeout) — surface the error message to the user along with the fix from the skill body's failure-modes table. Do NOT fall back to native tools. The user invoked `/altimate` specifically to use altimate-code; falling back would defeat the purpose. -Task to delegate: $ARGUMENTS +Task: $ARGUMENTS diff --git a/plugins/altimate-code/hooks-handlers/session-start.sh b/plugins/altimate-code/hooks-handlers/session-start.sh index eae5dce..5a90d21 100755 --- a/plugins/altimate-code/hooks-handlers/session-start.sh +++ b/plugins/altimate-code/hooks-handlers/session-start.sh @@ -1,16 +1,10 @@ #!/usr/bin/env bash -# SessionStart hook for the altimate-code plugin. Emits a descriptive statement -# of the altimate-code skill's capabilities so Claude can route to it when the -# task shape fits. Deliberately descriptive rather than imperative — see the -# Claude plugin review-criteria checklist items on "avoid instructing Claude -# to call other tools" and "don't interfere with tool sequencing." -# -# Uses printf (not a here-doc) so the hook works in restricted sandboxes that -# refuse to create the temporary file a here-doc needs. +# Static SessionStart capability description. printf works in sandboxes that +# refuse the temporary files a here-doc can require. printf '%s\n' '{' printf ' "hookSpecificOutput": {\n' printf ' "hookEventName": "SessionStart",\n' -printf ' "additionalContext": "The altimate-code plugin ships two skills in this session. (1) The `altimate-code` skill routes data-engineering work to the altimate-code CLI — column-level lineage, downstream-impact, cross-database validation, FinOps, PII from sampled rows, query cost attribution, schema diffs, dev-vs-prod diffing. It is not well-suited for pure file/code edits to dbt models and SQL files that do not touch warehouse state — native Bash/Edit/Write handles those faster. (2) The `review` skill runs the altimate-code dbt PR reviewer on dbt project changes (models/**.sql, schema.yml, dbt_project.yml, sources.yml, macros, snapshots, seeds). It emits a signed verdict envelope with column lineage, query equivalence, dbt anti-pattern detection, and PII screening — none of which native tools or a generic code-review skill can compute. When the user asks to review dbt / SQL / warehouse changes, this is the specialized reviewer available. For non-dbt code review (TypeScript, Python, Go), the `review` skill declines."\n' +printf ' "additionalContext": "The altimate-code plugin provides MCP data tools for warehouse questions: Claude Code reasons directly with warehouse_list, schema_inspect, sql_execute, sql_check, and sql_materialize. The data-question skill covers this workflow. The altimate-code routing skill delegates long jobs such as dbt builds, migrations, and FinOps reports to the CLI agent. The review skill and /review command provide the specialized dbt/SQL PR reviewer."\n' printf ' }\n' printf '}\n' diff --git a/plugins/altimate-code/hooks/hooks.json b/plugins/altimate-code/hooks/hooks.json index 10999b0..e554842 100644 --- a/plugins/altimate-code/hooks/hooks.json +++ b/plugins/altimate-code/hooks/hooks.json @@ -1,5 +1,5 @@ { - "description": "SessionStart nudge directing the agent to delegate data-engineering tasks to altimate-code via the altimate-code skill. The UserPromptSubmit pre-run hook was removed because it double-invoked altimate-code (once at hook time, once when the model fired the skill), doubling token consumption on the altimate-gateway without improving delegation rate — the skill body + SessionStart directive already route the model to altimate-code reliably.", + "description": "SessionStart capability description: direct MCP tools for data questions, CLI delegation for long jobs, and the specialized dbt/SQL reviewer.", "hooks": { "SessionStart": [ { diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 9fa80ec..191dc3f 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -1,31 +1,42 @@ --- name: altimate-code description: >- - Delegates dbt and warehouse work to altimate-code, a specialized CLI agent - with 100+ purpose-built data tools. Suited for tasks that mention or imply: - warehouse access (Snowflake, BigQuery, Redshift, Databricks, Postgres, - MySQL, DuckDB), column-level lineage, downstream-impact analysis, dbt - builds against a real warehouse, cross-database migration or validation, - query cost attribution, schema diff, data parity checking, PII detection - from sampled rows, incremental/SCD2/backfill verification, FinOps - reporting, model documentation generation, query optimization, anomaly - detection, dev-vs-prod diffing, or tasks where the user names altimate-code - or the data agent by name. The skill routes to a purpose-built CLI, so it - covers workloads that touch live data, lineage, or warehouse state more - directly than native file-editing tools do. + Routes warehouse data questions to altimate-code MCP tools for Claude to + answer directly; delegates long dbt project builds, migrations, and FinOps + jobs to the altimate-code CLI agent. Use also when altimate-code is named. --- # altimate-code -altimate-code is a CLI AI agent with 100+ purpose-built data engineering tools. **This skill exists for one purpose: delegate the user's task to altimate-code and pass the result back.** Native tools (Bash, Edit, Write, Read) are NOT a fallback path inside this skill — if altimate-code cannot complete the task, surface the failure to the user and STOP. +Choose the path from the requested outcome, including when invoked via `/altimate`. -## You MUST follow this workflow +## Data questions: use MCP tools directly -1. **Verify altimate-code is on PATH** with `command -v altimate-code`. If it returns nothing, jump to "Not installed" below and stop. -2. **Run altimate-code with the user's task** using the invocation below. Pass the user's request through verbatim — do not paraphrase or split it. -3. **Read the output file** and present it to the user as-is. +For answers, numbers, or lists over warehouse data, use the `altimate-code` MCP +server yourself. Follow the `data-question` skill for discovery, value profiles, +SQL, cross-connection joins, correctness checks, and answer shape. The tools are +`warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize`. +Claude Code does the reasoning; this server runs no LLM and needs no separate +LLM-provider configuration. Do not delegate a data question to `altimate-code run`. -Do not attempt the work with Edit/Write/Bash yourself, even if it looks simple. The whole point of this skill is to route data-engineering work to the agent that's built for it. If you find yourself reaching for Edit or Write while this skill is active, stop and re-read this paragraph. +The server is read-only by default for source databases. Postgres, SQLite, and +DuckDB enforce read-only access at the database level; other databases rely on +SQL classification, so use a read-only DB user. `sql_materialize` writes only to +session-local `scratch` DuckDB for analysis. Large query results may spill to a +local file path; read the needed results there before answering. + +If MCP is unavailable, report the connection/startup error and check that an +altimate-code build with `mcp serve` is on PATH and connections are configured. +Do not silently switch to the separate CLI agent or invent results. Use native +file-reading tools as needed to read local result files. + +## Long jobs: delegate to the CLI agent + +Use `altimate-code run` for long multi-step jobs needing its own agent, such as +building a dbt project, migrations, or a FinOps report. First check +`command -v altimate-code`. Pass the user's task verbatim using the safe +invocation below, then read and present the output. Delegation uses +altimate-code's own configured LLM provider, costs, and rate limits. ## Invocation — pick the right agent for the task @@ -35,16 +46,16 @@ altimate-code has multiple agent personas. The default (`builder`) does a full p | Shape | Examples | Use | |---|---|---| -| **Any dbt / SQL task** (rename, refactor, create model, debug, structural reorg, multi-step setup) | the vast majority of customer requests | `fast-edit` — try this first | +| **Delegated dbt / SQL job** (rename, refactor, create model, debug, structural reorg, multi-step setup) | long project jobs needing the CLI agent | `fast-edit` — try this first | | **Multi-table aggregation correctness** | new model joining 3+ tables with `count(*)` / `sum() over (...)` / "first X, last X" logic that must be exactly right | `analyst` if `fast-edit` fails the user's verification | | **Warehouse-state work** | column-level lineage, downstream-impact, cross-DB migration / parity, query cost attribution against a real warehouse, schema diff between environments, PII detection, FinOps reporting | `builder` (default — has warehouse tools enabled) | | **Vague debug** ("X is broken", "make it work", "fix this") | unspecified failure mode | **Don't delegate yet.** Ask the user for the specific error message or symptom before invoking any agent — empirically all three agents fail vague debug prompts at ~700K tokens each. | -**Decision policy:** start with `fast-edit` for any dbt/SQL task. If the user reports the result is wrong (e.g. aggregation values don't match), retry with `analyst`. Only use `builder` when the task genuinely needs the warehouse-investigation tools (it's 10–20× more expensive than fast-edit and rarely required). +**Decision policy (delegation only):** start with `fast-edit` for dbt/SQL project jobs. Data questions stay on the MCP path, including multi-table aggregations. If the user reports the result is wrong (e.g. aggregation values don't match), retry with `analyst`. Only use `builder` when the task genuinely needs the warehouse-investigation tools (it's 10–20× more expensive than fast-edit and rarely required). ### Step 2 — invoke with the chosen agent -Pass the task through a here-doc into a variable so the shell never +Choose a here-doc delimiter that does not occur as a standalone line in the task. Pass the task through a quoted here-doc into a variable so the shell never command-substitutes anything the user typed (a task like `refactor `whoami` and $(rm -rf ~)` would otherwise fire `whoami` and `rm -rf ~` before `altimate-code` ever runs). Write the result to a @@ -98,22 +109,22 @@ altimate-code's prompt cache is warm in a continued session — project structur If the user starts a clearly unrelated workflow (different project, different schema, different debugging thread), drop `--continue` and start fresh — the warm cache is irrelevant and you'd carry unrelated history into the prompt. -## Failure modes — route every one to the user +## Delegation failures -When altimate-code returns an error, **report the error to the user and STOP**. Do not fall back to Bash, Edit, or Write. The skill's contract is "altimate-code handles this, or the user is told why it couldn't." +If `altimate-code run` fails, report the error and stop that delegation; do not +silently replace it with native edits or warehouse commands. -| Symptom | What to tell the user — verbatim | +| Symptom | Action to tell the user | |---|---| -| `command not found: altimate-code` | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) and run `altimate-code` once to configure auth. Then re-run your request." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` in your terminal to open the TUI and reconfigure your provider, then re-run your request." | -| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate-code` to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | -| Output file empty | "altimate-code returned without producing output. The task may be too ambiguous — please restate with more detail (target table, expected columns, time window)." | -| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via `altimate-code` TUI." | - -In every row, the instruction to the user is the action — you do not retry the task with native tools. If the user fixes the underlying issue and asks again, you delegate again. - -## Notes - -- altimate-code runs its own LLM, separate from Claude Code's. Costs and rate limits accrue to altimate-code's configured provider. -- Sessions persist in altimate-code's local store — `altimate-code session list` shows prior runs; `--continue` resumes the latest, `--session ` resumes a specific one. -- For very long tasks, the `--output` file is the source of truth — stdout buffering can drop content. +| CLI not on PATH | Install an altimate-code build appropriate for this plugin, then retry. MCP requires a build with `mcp serve`. | +| `Unauthorized: Incorrect auth token` / `No provider configured` | Run `altimate-code` in a terminal and configure its LLM provider, then retry the delegated job. MCP data questions do not require this provider. | +| Process hangs >5 min | Open the altimate-code TUI to check for a pending prompt. | +| Output file empty | Report the missing output; ask for the target, expected result, or time window if the task is ambiguous. | +| Warehouse error (`UNKNOWN_USER`, `Database does not exist`) | Check the project's warehouse connection configuration and database access. | + +## Delegation notes + +- Sessions persist locally: `altimate-code session list` lists prior runs; + `--continue` resumes the latest, `--session ` a specific session. +- For very long tasks, the private `--output` file is the source of truth; + stdout buffering can drop content. diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md new file mode 100644 index 0000000..f0fd722 --- /dev/null +++ b/plugins/altimate-code/skills/data-question/SKILL.md @@ -0,0 +1,31 @@ +--- +name: data-question +description: >- + Answer natural-language questions over one or more databases directly with + altimate-code MCP tools, using Claude Code for reasoning and SQL analysis. +--- + +# Answer a data question + +Use the `altimate-code` MCP tools yourself; Claude Code supplies the reasoning. + +1. List available connections with `warehouse_list`. +2. Inspect relevant tables with `schema_inspect`. Read its value profile before + choosing columns or join keys: frequency-ranked values, distinct/null counts, + unique-in-sample flags, value shapes, and nested paths where present. Formats + can differ across databases; names alone do not establish compatible keys. +3. Prefer computing filters, joins, and aggregates in the database with + `sql_execute`. If results spill to a file path, read the needed results there. +4. For joins across connections, use `sql_materialize` to copy the smaller, + filtered side into session-local `scratch` DuckDB. Materialize the other + required inputs there too, then join them in one SQL query in `scratch`. +5. Use `sql_check` when keys, fan-out, grain, or nulls could change the answer. + Unique-in-sample is evidence to investigate, not proof of a unique key. +6. Check that every condition in the question actually filters something. + Compare counts or values before and after filtering; investigate no-op + conditions rather than silently dropping them or inventing exclusions. +7. When a phrase has two readings, compute both and choose using the question's + own definitions. If those definitions do not resolve it, show both readings. +8. Return the requested values in the requested shape, with a one-line basis + stating the sources, filters, and calculation. Report tool failures or missing + data plainly; do not fabricate values. From acf4b838b1c2576af33defc67511e2979e1f3b2b Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Sat, 17 Oct 2026 13:16:36 -0700 Subject: [PATCH 02/13] fix: fall back to delegation when MCP is unavailable, restore routing triggers - Data questions prefer the altimate-code MCP tools and fall back to `altimate-code run` (analyst) when the server is missing or fails to start, telling the user which path was used. - Restore delegation triggers for lineage, impact, schema diff, parity, PII, cost attribution, optimization, SCD2/incremental checks, docs and diffs. - PRIVACY.md describes the local MCP server and that tool results reach the model provider; `sql_check` engines and materialize-first noted. - Delegation here-docs use a per-call delimiter checked against the task text. - CONTRIBUTING.md covers `.mcp.json` and the `data-question` skill. Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 17 +++++-- PRIVACY.md | 25 ++++++--- README.md | 6 ++- plugins/altimate-code/CHANGELOG.md | 5 +- plugins/altimate-code/README.md | 33 +++++++----- plugins/altimate-code/commands/altimate.md | 38 +++++++++----- .../skills/altimate-code/SKILL.md | 51 ++++++++++++------- .../skills/data-question/SKILL.md | 15 ++++-- 8 files changed, 125 insertions(+), 65 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c264273..033e4fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Thanks for taking the time to contribute. This plugin lives in one repo (`AltimateAI/altimate-claude-plugin`) and ships a single Claude Code plugin (`altimate-code`) that delegates data-engineering tasks to the [altimate-code](https://github.com/AltimateAI/altimate-code) CLI. +Thanks for taking the time to contribute. This plugin lives in one repo (`AltimateAI/altimate-claude-plugin`) and ships a single Claude Code plugin (`altimate-code`). It prefers direct MCP tools for data questions and delegates to the [altimate-code](https://github.com/AltimateAI/altimate-code) CLI for other capabilities and long jobs. When MCP tools are unavailable, data questions also delegate, using the analyst persona. Both paths tell the user which is being used; delegation uses the CLI's separate configured LLM provider. ## Quick start @@ -26,9 +26,12 @@ altimate-claude-plugin/ │ └── altimate-code/ │ ├── .claude-plugin/ │ │ └── plugin.json # plugin manifest +│ ├── .mcp.json # local stdio MCP server registration │ ├── skills/ -│ │ └── altimate-code/ -│ │ └── SKILL.md # delegation logic +│ │ ├── altimate-code/ +│ │ │ └── SKILL.md # MCP/delegation routing and CLI invocation +│ │ └── data-question/ +│ │ └── SKILL.md # direct analysis and analyst fallback │ ├── hooks/ │ │ └── hooks.json # SessionStart hook config │ ├── hooks-handlers/ @@ -47,6 +50,8 @@ altimate-claude-plugin/ ## What to change where - **Routing behavior** (when Claude picks up the skill): edit `plugins/altimate-code/skills/altimate-code/SKILL.md` frontmatter description and/or `plugins/altimate-code/hooks-handlers/session-start.sh` `additionalContext`. +- **Direct data-question analysis and MCP fallback**: edit `plugins/altimate-code/skills/data-question/SKILL.md`. +- **MCP server launch**: edit `plugins/altimate-code/.mcp.json` (`altimate-code mcp serve`, read-only by default). - **Explicit-invocation UX** (what `/altimate ` does): edit `plugins/altimate-code/commands/altimate.md`. - **CLI invocation details** (agent selection, flags, follow-up handling): edit the workflow section in `plugins/altimate-code/skills/altimate-code/SKILL.md`. @@ -77,9 +82,11 @@ claude plugin install altimate-code@altimate-claude-plugin ## Components -- **Skill** — `plugins/altimate-code/skills/altimate-code/SKILL.md` — the delegation logic (`altimate-code run "$USER_TASK"` and surface the result). +- **Routing skill** — `plugins/altimate-code/skills/altimate-code/SKILL.md` — prefer available MCP tools for data questions; otherwise delegate to `altimate-code run` with `analyst`. Delegate other capabilities and long jobs using the appropriate persona. +- **Data-question skill** — `plugins/altimate-code/skills/data-question/SKILL.md` — MCP discovery, value profiles, SQL, scratch joins, and correctness checks; CLI analyst fallback when tools are unavailable. +- **MCP registration** — `plugins/altimate-code/.mcp.json` — launches the local stdio server; builds without `mcp serve` fail to start it and use delegation instead. - **Hook** — `plugins/altimate-code/hooks/hooks.json` + `plugins/altimate-code/hooks-handlers/session-start.sh` — SessionStart hook that describes the plugin's capabilities in the system prompt so Claude can route to it when the task shape fits. -- **Command** — `plugins/altimate-code/commands/altimate.md` — `/altimate` slash command for explicit delegation with agent-persona selection. +- **Command** — `plugins/altimate-code/commands/altimate.md` — `/altimate` slash command follows the same MCP/delegation routing with agent-persona selection. ## Reporting bugs / requesting features diff --git a/PRIVACY.md b/PRIVACY.md index 39247b9..3264e51 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,7 +1,7 @@ # Privacy Policy — Altimate Code plugin for Claude Code -**Effective date:** July 9, 2026 -**Applies to:** the `altimate-code` Claude Code plugin distributed from this repository, and the data flows it initiates through the [altimate-code](https://github.com/AltimateAI/altimate-code) CLI. +**Effective date:** October 17, 2026 +**Applies to:** the `altimate-code` Claude Code plugin distributed from this repository, and the data flows it initiates through the [altimate-code](https://github.com/AltimateAI/altimate-code) MCP server and CLI. This policy supplements the Altimate AI [Privacy Policy](https://www.altimate.ai/privacy) and [Terms](https://www.altimate.ai/terms), which govern Altimate services generally. Where this document is silent, the master policy applies. Questions: **info@altimate.ai**. @@ -9,16 +9,25 @@ This policy supplements the Altimate AI [Privacy Policy](https://www.altimate.ai ## The short version -- The plugin itself collects **no data**. It is a routing layer (a skill, a slash command, and a static session hook) that tells Claude Code when to delegate a task to the altimate-code CLI installed on your machine. +- When the plugin is enabled, Claude Code launches a local `altimate-code mcp serve` process for direct data tools. This requires a build containing `mcp serve`; if the server cannot start or its tools are unavailable, data questions fall back to CLI delegation. +- MCP tool results, including sampled column values and query results, enter the Claude Code conversation and therefore reach your configured model provider. The local MCP server makes no separate LLM calls. - When a task **is** delegated, your task text is passed to the altimate-code CLI, which sends it to an LLM provider to plan and execute the work — the Altimate LLM Gateway by default, or a provider you configure (BYOK). - Warehouse queries, dbt commands, and file edits run **locally on your machine, under your credentials**. Your warehouse credentials are never sent to Altimate. - Installing the plugin is an explicit act — `/plugin marketplace add` does not install it, and `/plugin install` never auto-runs. Nothing is delegated until the plugin is installed and you send a task that matches the skill. ## What the plugin does and does not do -The plugin contains no executable service of its own. Its only runtime behavior is a SessionStart hook that prints a fixed, static text block describing the skill's capabilities. It does not read your files, does not phone home, and does not collect analytics. +The plugin registers a local stdio MCP server through `.mcp.json`, provides routing skills and slash commands, and runs a SessionStart hook that prints a fixed capability description. The server reads configured connections and runs data tools under your local credentials. The plugin adds no analytics of its own; CLI telemetry is described below. -Data leaves Claude Code's process only when the delegation skill or the `/altimate` command fires and invokes the locally installed altimate-code CLI. +## Data flows through MCP tools + +| Data | Where it goes | Retention | +|---|---|---| +| Database credentials and connection configuration | Read locally by the MCP server to connect to your databases | Local configuration; not included in tool results | +| Schema metadata, sampled column values, and query results returned by tools | Local MCP server → Claude Code conversation → your configured model provider | Governed by Claude Code and your model provider's policies | +| Scratch tables and spilled query results | Local session storage or spill files; any content Claude reads enters the conversation and reaches your model provider | Local artifacts; conversation copies follow Claude Code and provider policies | + +The MCP server makes no separate LLM calls. Delegation uses the separate provider path below. ## Data flows when a task is delegated @@ -26,7 +35,7 @@ Data leaves Claude Code's process only when the delegation skill or the `/altima |---|---|---| | Your task prompt (verbatim) | Local altimate-code CLI → your configured LLM provider | Altimate LLM Gateway does not retain full prompts and responses after processing. BYOK providers: governed by that provider's policy — Altimate never sees this traffic. | | Warehouse credentials (`profiles.yml`, env vars) | Stay on your machine; used locally by the CLI | Never transmitted to Altimate | -| Warehouse query results, dbt output, file edits | Produced locally; written to a local output file surfaced back to Claude Code | Local only | +| Warehouse query results, dbt output, file edits | Produced locally; data supplied to the CLI agent reaches its configured LLM provider. Output read back into Claude Code reaches Claude Code's model provider. | Local output files; provider copies follow the applicable provider policies | | Schema metadata indexed by the CLI | Local index on your machine | Local only | **Bring Your Own Key (BYOK):** if you configure your own provider (Anthropic, OpenAI, Bedrock, Azure OpenAI, Ollama, and others), your prompts go directly from your machine to that provider. Altimate is not in the path. @@ -57,8 +66,8 @@ All data transmitted to Altimate services is encrypted in transit using TLS. Alt ## Your choices -- **Don't enable the plugin** — it ships disabled; nothing is delegated until you enable it. -- **Use BYOK** — route prompts directly to your own provider so Altimate never sees them. +- **Don't enable the plugin** — no plugin MCP server is launched and no tasks are delegated while it is disabled. +- **Use BYOK for delegation** — route CLI agent prompts directly to your own provider. MCP tool results are handled by Claude Code's configured model provider independently. - **Disable telemetry** — see above. - **Contact us** — for access, correction, or deletion requests, email **info@altimate.ai**. diff --git a/README.md b/README.md index 3de28e3..0bfbfd3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,11 @@ The Altimate marketplace of Claude Code plugins. Currently ships one plugin: **[altimate-code](./plugins/altimate-code/)** — gives Claude Code direct MCP data tools from [altimate-code](https://github.com/AltimateAI/altimate-code), with CLI delegation for long dbt and warehouse jobs. -**Experimental: requires an altimate-code build with `mcp serve`.** Claude Code +**Experimental: direct MCP use requires an altimate-code build with `mcp serve`.** +Released builds without `mcp serve` fail to start the MCP server; the plugin then +falls back to `altimate-code run` with the analyst persona for data questions, +using the CLI's configured LLM provider. The plugin tells you which path it uses. +With MCP available, Claude Code supplies the reasoning and LLM cost for direct data questions; the MCP server runs no LLM. Tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize` (session-local scratch DuckDB for cross-database joins). diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 94cab92..7a85e01 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this plugin will be documented in this file. -## [1.1.0-experimental] — Unreleased — experimental; requires an altimate-code build with `mcp serve` +## [1.1.0-experimental] — Unreleased — direct MCP use requires an altimate-code build with `mcp serve` ### Added - Stdio MCP registration for `altimate-code mcp serve`, without `--allow-write`. @@ -10,7 +10,8 @@ All notable changes to this plugin will be documented in this file. - Lean `data-question` skill for value-profile inspection, SQL analysis, cross-connection scratch joins, and correctness checks. ### Changed -- Routing skill, `/altimate`, and SessionStart context use MCP directly for data questions with Claude Code reasoning; long jobs retain CLI delegation and agent-persona guidance. +- Routing skill, `data-question`, and `/altimate` prefer MCP for data questions with Claude Code reasoning. If the MCP tools are unavailable, they fall back to CLI analyst delegation and tell the user which path is used. Released builds without `mcp serve` fail to start the MCP server and use this fallback. +- Long jobs and capabilities outside the five MCP tools retain CLI delegation and agent-persona guidance. - Documentation covers experimental prerequisites, connection discovery, read-only enforcement limits, local result files, and separate reasoning/billing paths. ## [1.0.0] — 2026-07-09 diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 82b8508..32623e6 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -6,8 +6,10 @@ LLM cost** for data questions; the stdio MCP server runs no LLM. Long multi-step jobs such as dbt project builds, migrations, and FinOps reports can still be delegated to `altimate-code run`, which uses its own agent and configured provider. -**1.1.0-experimental: requires an altimate-code build with `mcp serve`.** This -server is in an unreleased branch; a published CLI release may not include it. +**1.1.0-experimental: direct MCP use requires an altimate-code build with `mcp serve`.** +This server is in an unreleased branch. Released builds without `mcp serve` fail +to start the MCP server; the plugin falls back to `altimate-code run` with the +analyst persona for data questions. It tells you which path is being used. ## Install @@ -18,11 +20,11 @@ server is in an unreleased branch; a published CLI release may not include it. ## Prerequisites -Install an altimate-code build containing `mcp serve` and put `altimate-code` on -PATH where Claude Code can launch it. The CLI requires Node 20+. Check your build -with `altimate-code mcp serve --help`; an unknown command means you need a build -that includes the MCP server. Installing the latest published npm package alone -may not satisfy this experimental requirement. +Put `altimate-code` on PATH where Claude Code can launch it. The CLI requires +Node 20+. For direct MCP use, install a build containing `mcp serve`. Check your +build with `altimate-code mcp serve --help`; an unknown command means the MCP +server cannot start and data questions use CLI delegation instead. Installing +the latest published npm package alone does not provide the unreleased server. Configure database connections as described below. Direct MCP use does **not** require an altimate-code LLM provider or API key. For delegated jobs only, run @@ -38,7 +40,7 @@ The plugin's `.mcp.json` registers the `altimate-code` stdio server by running | `warehouse_list` | List available connections. | | `schema_inspect` | Inspect columns and value profiles: frequency-ranked values, distinct/null counts, unique-in-sample flags, value shapes, and MongoDB nested paths. | | `sql_execute` | Execute SQL, read-only by default. Large results spill to a local file path. | -| `sql_check` | Check keys, fan-out, grain, and nulls that could affect correctness. | +| `sql_check` | Check keys, fan-out, grain, and nulls on SQLite, DuckDB, and Postgres. For other engines, first `sql_materialize` the relevant rows into `scratch` and check there. | | `sql_materialize` | Copy a read-only query result from any connection into session-local `scratch` DuckDB for cross-database joins. | For a data question, Claude lists connections, inspects schemas and value profiles, @@ -46,10 +48,13 @@ computes in SQL, checks correctness where needed, and returns the requested valu with a one-line basis. For cross-connection joins, it materializes the smaller filtered side and other required inputs into `scratch`, then joins there. -The routing skill and `/altimate ` select this direct path for answers, -numbers, and lists. Long jobs needing altimate-code's own agent use +The routing skill, `data-question` skill, and `/altimate ` prefer this direct +path for answers, numbers, and lists when the MCP tools are available in the +session. If the server is missing or fails to start, they delegate data questions +with `--agent analyst`. Long jobs and capabilities outside the five MCP tools use `altimate-code run` with persona selection (`fast-edit`, `analyst`, or `builder`) -and a private output file. Delegated jobs use the CLI's separate LLM provider, +and a private output file. The plugin tells you which path it uses. +Delegated jobs use the CLI's separate LLM provider, costs, and rate limits. `/review` retains the specialized dbt/SQL reviewer. A short SessionStart hook describes these capabilities to Claude. @@ -101,15 +106,15 @@ Delegation passes your task to `altimate-code run`; its own configured LLM provider handles the task and any data supplied to that agent. This is a separate provider and billing path from direct MCP use. -See **[PRIVACY.md](../../PRIVACY.md)** for the existing delegation policy; +See **[PRIVACY.md](../../PRIVACY.md)** for MCP and delegation data flows; **[SECURITY.md](../../SECURITY.md)** and **[TERMS.md](../../TERMS.md)** also apply. ## Troubleshooting | Symptom | Fix | |---|---| -| `command not found: altimate-code` | Put a build with `mcp serve` on Claude Code's PATH. | -| Unknown `mcp` or `serve` command | Use an altimate-code build containing the unreleased MCP server. | +| `command not found: altimate-code` | Install altimate-code on Claude Code's PATH for delegation; direct MCP tools additionally require a build with `mcp serve`. | +| Unknown `mcp` or `serve` command | The MCP server fails to start; data questions fall back to CLI analyst delegation. Configure the CLI's LLM provider for delegation, or use a build containing `mcp serve` for direct MCP tools. | | No connections / database access error | Check project/global connection files, `ALTIMATE_CODE_CONN_*` environment variables, and database permissions. | | `Unauthorized` / `No provider configured` from a delegated job | Configure the CLI's LLM provider; direct MCP data questions do not need it. | | Delegated job hangs or returns no output | Check the CLI TUI for pending prompts and provide a precise target and expected result. | diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index f2b8e6f..37d2318 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -1,17 +1,21 @@ --- -description: Answer data questions with altimate-code MCP tools or delegate long dbt and warehouse jobs to its CLI agent. +description: Prefer altimate-code MCP for data questions; delegate when unavailable and for other dbt and warehouse jobs. argument-hint: --- The user invoked `/altimate` to use altimate-code for this task. For a data -question requesting answers, numbers, or lists, use the `altimate-code` MCP tools -directly and follow the `data-question` skill. Claude Code does the reasoning; -do not invoke `altimate-code run` or require its LLM provider for this path. -If MCP is unavailable, report the error and the requirement for a build with -`mcp serve` and configured connections; do not silently delegate instead. +question requesting answers, numbers, or lists, prefer the `altimate-code` MCP +tools when available in the session and follow the `data-question` skill. +Claude Code does the reasoning; this path needs no CLI LLM provider. If the tools +are unavailable (server missing or failed to start), use the delegation workflow +below with `--agent analyst`. Released builds without `mcp serve` can still +delegate. Tell the user which path is being used and, for fallback, that MCP is +unavailable and delegation uses the CLI's separate configured LLM provider. For a long multi-step job needing altimate-code's own agent (such as a dbt project -build, migration, or FinOps report), use the delegation workflow below. +build, migration, or FinOps report), or a capability outside the five MCP tools +listed in the `altimate-code` skill, use the delegation workflow below. Tell the +user that CLI delegation is being used. Delegation workflow (follow in order): @@ -26,23 +30,29 @@ Delegation workflow (follow in order): | Task shape | Use `--agent` | |---|---| + | Data question when MCP tools are unavailable | `analyst` | | Delegated dbt / SQL project job (rename, refactor, create, debug, structural) | `fast-edit` (default) | | Aggregation correctness on multi-table joins | `analyst` if fast-edit fails the user's verification | | Warehouse-state work (lineage, cost, parity, schema diff, PII, FinOps) | `builder` | | Vague debug ("X is broken") | **Stop — ask the user for the specific error before delegating.** | - Decision rule: start with `fast-edit` for delegated dbt/SQL project jobs; use `analyst` after correctness verification fails, and `builder` for warehouse-state jobs. Data questions use MCP regardless of join complexity. + Decision rule: use `analyst` for data questions when MCP tools are unavailable; otherwise prefer MCP regardless of join complexity. Start with `fast-edit` for delegated dbt/SQL project jobs; use `analyst` after correctness verification fails, and `builder` for warehouse-state jobs. -3. **Run altimate-code with the chosen agent.** Choose a here-doc delimiter that - does not occur as a standalone line in the task. Pass `$ARGUMENTS` through a +3. **Run altimate-code with the chosen agent.** Generate a fresh delimiter per + call, such as `ALTIMATE_TASK_`, and check that it does not occur as + a standalone line in the complete task. Regenerate it if it does. Replace both + occurrences of `ALTIMATE_TASK_` in each template below with that + checked delimiter; keep the opening delimiter single-quoted (no shell + expansion). Insert the actual `$ARGUMENTS` text verbatim into the body before + execution. Pass it through a here-doc into a variable so the shell never command-substitutes anything the user typed, and write the result to a private `mktemp` file (not a shared `/tmp/altimate-result.md` — concurrent invocations clobber each other and a world-readable fixed path leaks warehouse rows or PII): ```bash - TASK="$(cat <<'ALTIMATE_TASK' + TASK="$(cat <<'ALTIMATE_TASK_' $ARGUMENTS - ALTIMATE_TASK + ALTIMATE_TASK_ )" umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" @@ -56,9 +66,9 @@ Delegation workflow (follow in order): **If this is a follow-up task in the same project** (the user invoked `/altimate` already in this conversation about the same dbt project / warehouse / data context), add `--continue` to resume the warm session — cache is hot, follow-on cost is materially lower: ```bash - TASK="$(cat <<'ALTIMATE_TASK' + TASK="$(cat <<'ALTIMATE_TASK_' $ARGUMENTS - ALTIMATE_TASK + ALTIMATE_TASK_ )" umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 191dc3f..b7721f4 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -1,23 +1,26 @@ --- name: altimate-code description: >- - Routes warehouse data questions to altimate-code MCP tools for Claude to - answer directly; delegates long dbt project builds, migrations, and FinOps - jobs to the altimate-code CLI agent. Use also when altimate-code is named. + Prefer altimate-code MCP for data questions; delegate if unavailable. Delegate + dbt builds, migrations, FinOps, column-level lineage, downstream impact, schema + diff, data parity, PII detection, query cost attribution, query optimization, + incremental/SCD2 verification, model docs, and dev-vs-prod diffs. Use also when + altimate-code is named. --- # altimate-code Choose the path from the requested outcome, including when invoked via `/altimate`. -## Data questions: use MCP tools directly +## Data questions: prefer MCP tools, otherwise delegate For answers, numbers, or lists over warehouse data, use the `altimate-code` MCP -server yourself. Follow the `data-question` skill for discovery, value profiles, +server yourself when its tools are available in the session. Follow the +`data-question` skill for discovery, value profiles, SQL, cross-connection joins, correctness checks, and answer shape. The tools are `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize`. Claude Code does the reasoning; this server runs no LLM and needs no separate -LLM-provider configuration. Do not delegate a data question to `altimate-code run`. +LLM-provider configuration. Tell the user that the MCP path is being used. The server is read-only by default for source databases. Postgres, SQLite, and DuckDB enforce read-only access at the database level; other databases rely on @@ -25,15 +28,22 @@ SQL classification, so use a read-only DB user. `sql_materialize` writes only to session-local `scratch` DuckDB for analysis. Large query results may spill to a local file path; read the needed results there before answering. -If MCP is unavailable, report the connection/startup error and check that an -altimate-code build with `mcp serve` is on PATH and connections are configured. -Do not silently switch to the separate CLI agent or invent results. Use native -file-reading tools as needed to read local result files. +If the MCP tools are unavailable in the session (server missing or failed to +start), tell the user that MCP is unavailable and that you are using CLI +delegation with its separate configured LLM provider. Follow the invocation +workflow below with `--agent analyst`. Released altimate-code builds without +`mcp serve` can still use this delegation path. If an available tool fails, +report that error; do not invent results. Use native file-reading tools as needed +to read local result files. -## Long jobs: delegate to the CLI agent +## Other capabilities and long jobs: delegate to the CLI agent Use `altimate-code run` for long multi-step jobs needing its own agent, such as -building a dbt project, migrations, or a FinOps report. First check +building a dbt project, migrations, or a FinOps report. Also delegate capabilities +outside the five MCP tools: column-level lineage, downstream impact, schema diff, +data parity, PII detection, query cost attribution, query optimization, +incremental/SCD2 verification, model docs, and dev-vs-prod diffs. Tell the user +that CLI delegation is being used. First check `command -v altimate-code`. Pass the user's task verbatim using the safe invocation below, then read and present the output. Delegation uses altimate-code's own configured LLM provider, costs, and rate limits. @@ -46,25 +56,30 @@ altimate-code has multiple agent personas. The default (`builder`) does a full p | Shape | Examples | Use | |---|---|---| +| **Data question when MCP tools are unavailable** | answers, numbers, lists, including multi-table aggregations | `analyst` | | **Delegated dbt / SQL job** (rename, refactor, create model, debug, structural reorg, multi-step setup) | long project jobs needing the CLI agent | `fast-edit` — try this first | | **Multi-table aggregation correctness** | new model joining 3+ tables with `count(*)` / `sum() over (...)` / "first X, last X" logic that must be exactly right | `analyst` if `fast-edit` fails the user's verification | | **Warehouse-state work** | column-level lineage, downstream-impact, cross-DB migration / parity, query cost attribution against a real warehouse, schema diff between environments, PII detection, FinOps reporting | `builder` (default — has warehouse tools enabled) | | **Vague debug** ("X is broken", "make it work", "fix this") | unspecified failure mode | **Don't delegate yet.** Ask the user for the specific error message or symptom before invoking any agent — empirically all three agents fail vague debug prompts at ~700K tokens each. | -**Decision policy (delegation only):** start with `fast-edit` for dbt/SQL project jobs. Data questions stay on the MCP path, including multi-table aggregations. If the user reports the result is wrong (e.g. aggregation values don't match), retry with `analyst`. Only use `builder` when the task genuinely needs the warehouse-investigation tools (it's 10–20× more expensive than fast-edit and rarely required). +**Decision policy (delegation only):** use `analyst` for data questions when MCP tools are unavailable; otherwise prefer MCP for data questions, including multi-table aggregations. Start with `fast-edit` for dbt/SQL project jobs. If the user reports the result is wrong (e.g. aggregation values don't match), retry with `analyst`. Only use `builder` when the task genuinely needs the warehouse-investigation tools (it's 10–20× more expensive than fast-edit and rarely required). ### Step 2 — invoke with the chosen agent -Choose a here-doc delimiter that does not occur as a standalone line in the task. Pass the task through a quoted here-doc into a variable so the shell never +Generate a fresh delimiter per call, such as `ALTIMATE_TASK_`, and +check that it does not occur as a standalone line in the complete task. Regenerate +it if it does. Replace both occurrences of `ALTIMATE_TASK_` in each +template below with that checked delimiter; keep the opening delimiter +single-quoted (no shell expansion). Pass the task through a quoted here-doc into a variable so the shell never command-substitutes anything the user typed (a task like `refactor `whoami` and $(rm -rf ~)` would otherwise fire `whoami` and `rm -rf ~` before `altimate-code` ever runs). Write the result to a private temporary file, not a shared one under `/tmp`: ```bash -TASK="$(cat <<'ALTIMATE_TASK' +TASK="$(cat <<'ALTIMATE_TASK_' -ALTIMATE_TASK +ALTIMATE_TASK_ )" umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" @@ -91,9 +106,9 @@ Then `Read "$OUTPUT_FILE"` and emit its contents to the user without re-summaris When the user makes a follow-up data task in the same project after a successful altimate-code delegation, prefer `--continue` to resume the warm session instead of starting a fresh one. Same here-doc + `mktemp` pattern: ```bash -TASK="$(cat <<'ALTIMATE_TASK' +TASK="$(cat <<'ALTIMATE_TASK_' -ALTIMATE_TASK +ALTIMATE_TASK_ )" umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md index f0fd722..46ecff6 100644 --- a/plugins/altimate-code/skills/data-question/SKILL.md +++ b/plugins/altimate-code/skills/data-question/SKILL.md @@ -1,13 +1,19 @@ --- name: data-question description: >- - Answer natural-language questions over one or more databases directly with - altimate-code MCP tools, using Claude Code for reasoning and SQL analysis. + Prefer altimate-code MCP tools for natural-language questions over databases, + using Claude Code for reasoning; delegate to the CLI analyst if unavailable. --- # Answer a data question -Use the `altimate-code` MCP tools yourself; Claude Code supplies the reasoning. +When the `altimate-code` MCP tools are available in the session, use them yourself; +Claude Code supplies the reasoning. Tell the user that the MCP path is being used. +If the tools are unavailable (server missing or failed to start), tell the user +and follow the `altimate-code` skill's CLI delegation workflow with +`--agent analyst`, including its installation/provider checks and private output +file. Delegation uses the CLI's separate configured LLM provider. Do not attempt +the MCP steps below when its tools are unavailable. 1. List available connections with `warehouse_list`. 2. Inspect relevant tables with `schema_inspect`. Read its value profile before @@ -20,6 +26,9 @@ Use the `altimate-code` MCP tools yourself; Claude Code supplies the reasoning. filtered side into session-local `scratch` DuckDB. Materialize the other required inputs there too, then join them in one SQL query in `scratch`. 5. Use `sql_check` when keys, fan-out, grain, or nulls could change the answer. + It runs on SQLite, DuckDB, and Postgres. For other engines, first use + `sql_materialize` to copy the relevant rows into `scratch`, then run the checks + there. Materialize all relevant rows for a key or grain check, not just a sample. Unique-in-sample is evidence to investigate, not proof of a unique key. 6. Check that every condition in the question actually filters something. Compare counts or values before and after filtering; investigate no-op From e0f9581471027d0740d56bcb97b21b96e532f4dd Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Sat, 17 Oct 2026 17:15:31 -0700 Subject: [PATCH 03/13] feat: route data questions to MCP tools from SessionStart and sharpen skill triggers - SessionStart output now carries compact routing (MCP tools for data questions, analyst/fast-edit/builder delegation otherwise). - Skill descriptions trigger on ordinary data questions. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/hooks-handlers/session-start.sh | 5 +++-- plugins/altimate-code/skills/altimate-code/SKILL.md | 11 ++++++----- plugins/altimate-code/skills/data-question/SKILL.md | 5 +++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/plugins/altimate-code/hooks-handlers/session-start.sh b/plugins/altimate-code/hooks-handlers/session-start.sh index 5a90d21..b2d1dcf 100755 --- a/plugins/altimate-code/hooks-handlers/session-start.sh +++ b/plugins/altimate-code/hooks-handlers/session-start.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash -# Static SessionStart capability description. printf works in sandboxes that +# Static SessionStart routing guidance. printf works in sandboxes that # refuse the temporary files a here-doc can require. printf '%s\n' '{' printf ' "hookSpecificOutput": {\n' printf ' "hookEventName": "SessionStart",\n' -printf ' "additionalContext": "The altimate-code plugin provides MCP data tools for warehouse questions: Claude Code reasons directly with warehouse_list, schema_inspect, sql_execute, sql_check, and sql_materialize. The data-question skill covers this workflow. The altimate-code routing skill delegates long jobs such as dbt builds, migrations, and FinOps reports to the CLI agent. The review skill and /review command provide the specialized dbt/SQL PR reviewer."\n' +# shellcheck disable=SC2016 +printf ' "additionalContext": "altimate-code routing:\\n- Data questions (answers, numbers, lists over warehouses): use the altimate-code MCP tools yourself; they run as altimate-code'"'"'s read-only analyst.\\n- If MCP is unavailable, delegate with `altimate-code run --agent analyst`.\\n- dbt/SQL project edits: delegate with `--agent fast-edit`.\\n- Warehouse-state work (lineage, impact, parity, PII, cost attribution, FinOps, environment diffs): delegate with `--agent builder`.\\n- Say which path was used. The review skill and /review command provide the dbt/SQL PR reviewer."\n' printf ' }\n' printf '}\n' diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index b7721f4..46c7293 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -1,11 +1,12 @@ --- name: altimate-code description: >- - Prefer altimate-code MCP for data questions; delegate if unavailable. Delegate - dbt builds, migrations, FinOps, column-level lineage, downstream impact, schema - diff, data parity, PII detection, query cost attribution, query optimization, - incremental/SCD2 verification, model docs, and dev-vs-prod diffs. Use also when - altimate-code is named. + Route data questions over a database or warehouse ("how many", "which", + "average", "top N", "compare") to the altimate-code MCP tools; delegate if + unavailable. Delegate dbt builds, migrations, FinOps, column-level lineage, + downstream impact, schema diff, data parity, PII detection, query cost + attribution, query optimization, incremental/SCD2 verification, model docs, + and dev-vs-prod diffs. Use also when altimate-code is named. --- # altimate-code diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md index 46ecff6..6934dd2 100644 --- a/plugins/altimate-code/skills/data-question/SKILL.md +++ b/plugins/altimate-code/skills/data-question/SKILL.md @@ -1,8 +1,9 @@ --- name: data-question description: >- - Prefer altimate-code MCP tools for natural-language questions over databases, - using Claude Code for reasoning; delegate to the CLI analyst if unavailable. + Use for ordinary data questions over a database or warehouse ("how many", + "which", "average", "top N", "compare", counts, lists, totals). Answer with the + altimate-code MCP tools yourself; delegate to the CLI analyst if unavailable. --- # Answer a data question From dcbf163588fb4a44dace9e7a0cf07ce43df2c549 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Sat, 17 Oct 2026 19:44:33 -0700 Subject: [PATCH 04/13] feat: add analyst agent and answer_commit finish step Co-Authored-By: Claude Sonnet 5.5 --- plugins/altimate-code/agents/analyst.md | 16 ++++++++++++++++ .../altimate-code/skills/data-question/SKILL.md | 12 +++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 plugins/altimate-code/agents/analyst.md diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md new file mode 100644 index 0000000..db7179d --- /dev/null +++ b/plugins/altimate-code/agents/analyst.md @@ -0,0 +1,16 @@ +--- +name: analyst +description: Read-only data analyst. Use as the main agent (`claude --agent altimate-code:analyst`) to answer data questions over connected warehouses with the altimate-code MCP tools, finishing with `answer_commit`. +--- + +You are a read-only data analyst working through the altimate-code MCP tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, `sql_materialize` and `answer_commit`. Do not modify source data or files. `sql_materialize` may write session-local `scratch` tables. + +Inspect connections, schemas and actual rows before joining or parsing; key formats may differ across databases. Start with `warehouse_list`, then `schema_inspect` without `table` to see the tables, and read its value profile (ranked values, distinct/null counts, unique flag, value shapes) before choosing columns or join keys. Establish population, grain, denominator and assumptions. Every clause of the question must bite: a filter that removes nothing usually means the wrong column. When a phrase admits two readings (which population, denominator, transform or owner column), compute both, then choose by the question's own definitions and the data's shape; keep that reasoning out of the final message, and record the chosen and rejected reading as one `answer_commit` `readings` entry. When a rule or policy decides the answer, read its full text (not a preview), enumerate each competing clause, and evaluate every condition as satisfied, violated or unknown against the row's own fields and dates before choosing. Use `sql_check` for keys, fan-out, grain, nulls or extraction coverage when they affect the answer; trivial queries need no ritual. + +Derive large intermediate sets in-engine. For a cross-engine join, move the smaller side: a few hundred keys go into an IN list or VALUES against the big table; `sql_materialize` into `scratch` only the side that is small after filtering, never a multi-million-row table when a filter or aggregate could shrink it first. Preserve requested weighting: group means weighted by contributing counts can be exact; unweighted averages change the weighting. For many similar tables, prefer catalog-driven SQL (information_schema, DuckDB query_table/UNION ALL BY NAME) after confirming dialect support. + +Treat inferred text labels as data: fixed rubric, stable IDs, full coverage and duplicate checks, then deterministic counting, never by eye. + +Use selected columns, partition filters and LIMIT/sampling to inspect cheaply; estimates are not exact final computations. Aggregate in SQL for exact answers. On timeout, revise the query. Report costs only from evidence. If results spill to a file path, read the needed part there. + +Finish by calling `answer_commit` with the single chosen value(s), one field per item the request asks for (every named item, such as an entity and its related item or count, must be its own field: when the request asks for only the answer, anything left in the basis or prose is dropped), `asked` listing those items from the question in order, a one-or-two-sentence basis (population, grain, source object/column), or `unresolved` with the reason. Then reply with exactly the `FINAL ANSWER:` text it returns and nothing else. Always supply `basis`, even when unresolved. Never list excluded candidates or alternative answers; a top-N with a tie at the boundary still returns N concrete rows (note the tie briefly in `rows.note`); when the request asks for only the answer or a specific format, set `answer_only`. Commit numbers that appear in query output; compute derived numbers in SQL. If `answer_commit` rejects the call, fix what it names and call it again. If it is unavailable, finish with one or two sentences of basis and a final line `FINAL ANSWER: `; never guess. diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md index 6934dd2..ea4f382 100644 --- a/plugins/altimate-code/skills/data-question/SKILL.md +++ b/plugins/altimate-code/skills/data-question/SKILL.md @@ -36,6 +36,12 @@ the MCP steps below when its tools are unavailable. conditions rather than silently dropping them or inventing exclusions. 7. When a phrase has two readings, compute both and choose using the question's own definitions. If those definitions do not resolve it, show both readings. -8. Return the requested values in the requested shape, with a one-line basis - stating the sources, filters, and calculation. Report tool failures or missing - data plainly; do not fabricate values. +8. Finish with `answer_commit`: pass one field (or rows column) per item the + request asks for, `asked` listing those items in order, and a one-line basis + (sources, filters, calculation). It rejects a call that leaves an asked item + unanswered or commits a number absent from query output; fix what it names and + call again. Reply with exactly the `FINAL ANSWER:` text it returns. Report tool + failures or missing data plainly; do not fabricate values. + +For a dedicated analyst session, start Claude Code with +`claude --agent altimate-code:analyst`; it carries this method as its system prompt. From 40a4fe28c5f015b0f627365b9ab4514e4f55543c Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 13:49:35 -0700 Subject: [PATCH 05/13] feat: point the analyst and skills at the five default MCP tools The MCP server's default toolset is now `warehouse_list`, `warehouse_add`, `sql_execute` (with `tables` for schemas and value profiles), `sql_materialize` and `answer_commit`; `schema_inspect` and `sql_check` need `mcp serve --all-tools`. The analyst agent, skills, READMEs and changelog no longer tell the model to call the hidden tools, and a missing connection is added with `warehouse_add`. Co-Authored-By: Claude Opus 5.5 --- README.md | 5 +++-- plugins/altimate-code/CHANGELOG.md | 2 +- plugins/altimate-code/README.md | 10 ++++++---- plugins/altimate-code/agents/analyst.md | 4 ++-- plugins/altimate-code/skills/altimate-code/SKILL.md | 2 +- plugins/altimate-code/skills/data-question/SKILL.md | 12 ++++++------ 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0bfbfd3..9d7b96b 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,9 @@ falls back to `altimate-code run` with the analyst persona for data questions, using the CLI's configured LLM provider. The plugin tells you which path it uses. With MCP available, Claude Code supplies the reasoning and LLM cost for direct data questions; the MCP server -runs no LLM. Tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, -and `sql_materialize` (session-local scratch DuckDB for cross-database joins). +runs no LLM. Tools: `warehouse_list`, `warehouse_add`, `sql_execute` (with `tables` +for schemas and value profiles), `sql_materialize` (session-local scratch DuckDB for +cross-database joins) and `answer_commit`. Source queries are read-only by default: database-enforced on Postgres, SQLite, and DuckDB; classification-only elsewhere, so use a read-only DB user. Connections diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 7a85e01..7a25f4e 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this plugin will be documented in this file. ### Added - Stdio MCP registration for `altimate-code mcp serve`, without `--allow-write`. -- Direct data tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize`. +- Direct data tools: `warehouse_list`, `warehouse_add`, `sql_execute` (`tables` returns schemas and value profiles in the same call), `sql_materialize` and `answer_commit`; `schema_inspect` and `sql_check` with `mcp serve --all-tools`. - Lean `data-question` skill for value-profile inspection, SQL analysis, cross-connection scratch joins, and correctness checks. ### Changed diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 32623e6..014c928 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -37,11 +37,13 @@ The plugin's `.mcp.json` registers the `altimate-code` stdio server by running | Tool | Purpose | |---|---| -| `warehouse_list` | List available connections. | -| `schema_inspect` | Inspect columns and value profiles: frequency-ranked values, distinct/null counts, unique-in-sample flags, value shapes, and MongoDB nested paths. | -| `sql_execute` | Execute SQL, read-only by default. Large results spill to a local file path. | -| `sql_check` | Check keys, fan-out, grain, and nulls on SQLite, DuckDB, and Postgres. For other engines, first `sql_materialize` the relevant rows into `scratch` and check there. | +| `warehouse_list` | List available connections; for local databases also tables, columns and a sample row. | +| `warehouse_add` | Add a connection when none is configured or one is missing. | +| `sql_execute` | Execute SQL, read-only by default; `queries` batches independent queries and `tables` returns columns and value profiles (frequency-ranked values, distinct/null counts, unique-in-sample flags, value shapes, MongoDB nested paths) in the same call. Large results spill to a local file path. | | `sql_materialize` | Copy a read-only query result from any connection into session-local `scratch` DuckDB for cross-database joins. | +| `answer_commit` | Finish a data question with one field per requested item. | + +`altimate-code mcp serve --all-tools` also exposes `schema_inspect` and `sql_check`. For a data question, Claude lists connections, inspects schemas and value profiles, computes in SQL, checks correctness where needed, and returns the requested values diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index db7179d..cb765f4 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -3,9 +3,9 @@ name: analyst description: Read-only data analyst. Use as the main agent (`claude --agent altimate-code:analyst`) to answer data questions over connected warehouses with the altimate-code MCP tools, finishing with `answer_commit`. --- -You are a read-only data analyst working through the altimate-code MCP tools: `warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, `sql_materialize` and `answer_commit`. Do not modify source data or files. `sql_materialize` may write session-local `scratch` tables. +You are a read-only data analyst working through the altimate-code MCP tools: `warehouse_list`, `warehouse_add`, `sql_execute`, `sql_materialize` and `answer_commit`. Do not modify source data or files. `sql_materialize` may write session-local `scratch` tables. -Inspect connections, schemas and actual rows before joining or parsing; key formats may differ across databases. Start with `warehouse_list`, then `schema_inspect` without `table` to see the tables, and read its value profile (ranked values, distinct/null counts, unique flag, value shapes) before choosing columns or join keys. Establish population, grain, denominator and assumptions. Every clause of the question must bite: a filter that removes nothing usually means the wrong column. When a phrase admits two readings (which population, denominator, transform or owner column), compute both, then choose by the question's own definitions and the data's shape; keep that reasoning out of the final message, and record the chosen and rejected reading as one `answer_commit` `readings` entry. When a rule or policy decides the answer, read its full text (not a preview), enumerate each competing clause, and evaluate every condition as satisfied, violated or unknown against the row's own fields and dates before choosing. Use `sql_check` for keys, fan-out, grain, nulls or extraction coverage when they affect the answer; trivial queries need no ritual. +Inspect connections, schemas and actual rows before joining or parsing; key formats may differ across databases. Start with `warehouse_list`; if it lists no connection you need, find the details in the project (config files, `.env`, local database files) and call `warehouse_add`. Pass `tables` to `sql_execute` to get each table's columns and value profile (ranked values, distinct/null counts, unique flag, value shapes) in the same call as your first queries, and read it before choosing columns or join keys; put independent queries in one call with `queries`. Establish population, grain, denominator and assumptions. Every clause of the question must bite: a filter that removes nothing usually means the wrong column. When a phrase admits two readings (which population, denominator, transform or owner column), compute both, then choose by the question's own definitions and the data's shape; keep that reasoning out of the final message, and record the chosen and rejected reading as one `answer_commit` `readings` entry. When a rule or policy decides the answer, read its full text (not a preview), enumerate each competing clause, and evaluate every condition as satisfied, violated or unknown against the row's own fields and dates before choosing. Check keys, fan-out, grain, nulls or extraction coverage with a counting query when they affect the answer; trivial queries need no ritual. Derive large intermediate sets in-engine. For a cross-engine join, move the smaller side: a few hundred keys go into an IN list or VALUES against the big table; `sql_materialize` into `scratch` only the side that is small after filtering, never a multi-million-row table when a filter or aggregate could shrink it first. Preserve requested weighting: group means weighted by contributing counts can be exact; unweighted averages change the weighting. For many similar tables, prefer catalog-driven SQL (information_schema, DuckDB query_table/UNION ALL BY NAME) after confirming dialect support. diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 46c7293..ae95f04 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -19,7 +19,7 @@ For answers, numbers, or lists over warehouse data, use the `altimate-code` MCP server yourself when its tools are available in the session. Follow the `data-question` skill for discovery, value profiles, SQL, cross-connection joins, correctness checks, and answer shape. The tools are -`warehouse_list`, `schema_inspect`, `sql_execute`, `sql_check`, and `sql_materialize`. +`warehouse_list`, `warehouse_add`, `sql_execute` (with `tables` for schemas), `sql_materialize`, and `answer_commit`. Claude Code does the reasoning; this server runs no LLM and needs no separate LLM-provider configuration. Tell the user that the MCP path is being used. diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md index ea4f382..8a4645a 100644 --- a/plugins/altimate-code/skills/data-question/SKILL.md +++ b/plugins/altimate-code/skills/data-question/SKILL.md @@ -16,8 +16,10 @@ and follow the `altimate-code` skill's CLI delegation workflow with file. Delegation uses the CLI's separate configured LLM provider. Do not attempt the MCP steps below when its tools are unavailable. -1. List available connections with `warehouse_list`. -2. Inspect relevant tables with `schema_inspect`. Read its value profile before +1. List available connections with `warehouse_list`. If the one you need is + missing, find its details in the project and add it with `warehouse_add`. +2. Inspect relevant tables by passing `tables` to `sql_execute` (together with + your first queries when you can). Read the value profile before choosing columns or join keys: frequency-ranked values, distinct/null counts, unique-in-sample flags, value shapes, and nested paths where present. Formats can differ across databases; names alone do not establish compatible keys. @@ -26,10 +28,8 @@ the MCP steps below when its tools are unavailable. 4. For joins across connections, use `sql_materialize` to copy the smaller, filtered side into session-local `scratch` DuckDB. Materialize the other required inputs there too, then join them in one SQL query in `scratch`. -5. Use `sql_check` when keys, fan-out, grain, or nulls could change the answer. - It runs on SQLite, DuckDB, and Postgres. For other engines, first use - `sql_materialize` to copy the relevant rows into `scratch`, then run the checks - there. Materialize all relevant rows for a key or grain check, not just a sample. +5. Check keys, fan-out, grain, or nulls with counting queries when they could + change the answer. Count over all relevant rows, not just a sample. Unique-in-sample is evidence to investigate, not proof of a unique key. 6. Check that every condition in the question actually filters something. Compare counts or values before and after filtering; investigate no-op From b59bb98221b07a85440d1b9b5f79181afaea0dc0 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 16:52:56 -0700 Subject: [PATCH 06/13] refactor: drop the data-question skill; the analyst agent and server instructions carry its method The skill duplicated the analyst agent and the MCP server instructions, and its listing was sent with every request (no session loaded it). The routing skill, /altimate and README now point at the server instructions. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/README.md | 3 +- plugins/altimate-code/commands/altimate.md | 2 +- .../skills/altimate-code/SKILL.md | 5 +- .../skills/data-question/SKILL.md | 47 ------------------- 4 files changed, 4 insertions(+), 53 deletions(-) delete mode 100644 plugins/altimate-code/skills/data-question/SKILL.md diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 014c928..dfb0515 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -50,7 +50,7 @@ computes in SQL, checks correctness where needed, and returns the requested valu with a one-line basis. For cross-connection joins, it materializes the smaller filtered side and other required inputs into `scratch`, then joins there. -The routing skill, `data-question` skill, and `/altimate ` prefer this direct +The routing skill and `/altimate ` prefer this direct path for answers, numbers, and lists when the MCP tools are available in the session. If the server is missing or fails to start, they delegate data questions with `--agent analyst`. Long jobs and capabilities outside the five MCP tools use @@ -126,7 +126,6 @@ See **[PRIVACY.md](../../PRIVACY.md)** for MCP and delegation data flows; - **MCP server** — `.mcp.json` — direct stdio data tools - **Routing skill** — `skills/altimate-code/SKILL.md` — direct questions or CLI delegation -- **Data-question skill** — `skills/data-question/SKILL.md` — concise analysis workflow - **Review skill** — `skills/review/SKILL.md` — specialized dbt/SQL review - **Commands** — `commands/altimate.md` and `commands/review.md` - **Hook** — `hooks/hooks.json` and `hooks-handlers/session-start.sh` diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index 37d2318..254408b 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -5,7 +5,7 @@ argument-hint: The user invoked `/altimate` to use altimate-code for this task. For a data question requesting answers, numbers, or lists, prefer the `altimate-code` MCP -tools when available in the session and follow the `data-question` skill. +tools when available in the session and follow the server's analysis method. Claude Code does the reasoning; this path needs no CLI LLM provider. If the tools are unavailable (server missing or failed to start), use the delegation workflow below with `--agent analyst`. Released builds without `mcp serve` can still diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index ae95f04..4f2cc85 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -16,9 +16,8 @@ Choose the path from the requested outcome, including when invoked via `/altimat ## Data questions: prefer MCP tools, otherwise delegate For answers, numbers, or lists over warehouse data, use the `altimate-code` MCP -server yourself when its tools are available in the session. Follow the -`data-question` skill for discovery, value profiles, -SQL, cross-connection joins, correctness checks, and answer shape. The tools are +server yourself when its tools are available in the session; the server's +instructions give the analysis method. The tools are `warehouse_list`, `warehouse_add`, `sql_execute` (with `tables` for schemas), `sql_materialize`, and `answer_commit`. Claude Code does the reasoning; this server runs no LLM and needs no separate LLM-provider configuration. Tell the user that the MCP path is being used. diff --git a/plugins/altimate-code/skills/data-question/SKILL.md b/plugins/altimate-code/skills/data-question/SKILL.md deleted file mode 100644 index 8a4645a..0000000 --- a/plugins/altimate-code/skills/data-question/SKILL.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: data-question -description: >- - Use for ordinary data questions over a database or warehouse ("how many", - "which", "average", "top N", "compare", counts, lists, totals). Answer with the - altimate-code MCP tools yourself; delegate to the CLI analyst if unavailable. ---- - -# Answer a data question - -When the `altimate-code` MCP tools are available in the session, use them yourself; -Claude Code supplies the reasoning. Tell the user that the MCP path is being used. -If the tools are unavailable (server missing or failed to start), tell the user -and follow the `altimate-code` skill's CLI delegation workflow with -`--agent analyst`, including its installation/provider checks and private output -file. Delegation uses the CLI's separate configured LLM provider. Do not attempt -the MCP steps below when its tools are unavailable. - -1. List available connections with `warehouse_list`. If the one you need is - missing, find its details in the project and add it with `warehouse_add`. -2. Inspect relevant tables by passing `tables` to `sql_execute` (together with - your first queries when you can). Read the value profile before - choosing columns or join keys: frequency-ranked values, distinct/null counts, - unique-in-sample flags, value shapes, and nested paths where present. Formats - can differ across databases; names alone do not establish compatible keys. -3. Prefer computing filters, joins, and aggregates in the database with - `sql_execute`. If results spill to a file path, read the needed results there. -4. For joins across connections, use `sql_materialize` to copy the smaller, - filtered side into session-local `scratch` DuckDB. Materialize the other - required inputs there too, then join them in one SQL query in `scratch`. -5. Check keys, fan-out, grain, or nulls with counting queries when they could - change the answer. Count over all relevant rows, not just a sample. - Unique-in-sample is evidence to investigate, not proof of a unique key. -6. Check that every condition in the question actually filters something. - Compare counts or values before and after filtering; investigate no-op - conditions rather than silently dropping them or inventing exclusions. -7. When a phrase has two readings, compute both and choose using the question's - own definitions. If those definitions do not resolve it, show both readings. -8. Finish with `answer_commit`: pass one field (or rows column) per item the - request asks for, `asked` listing those items in order, and a one-line basis - (sources, filters, calculation). It rejects a call that leaves an asked item - unanswered or commits a number absent from query output; fix what it names and - call again. Reply with exactly the `FINAL ANSWER:` text it returns. Report tool - failures or missing data plainly; do not fabricate values. - -For a dedicated analyst session, start Claude Code with -`claude --agent altimate-code:analyst`; it carries this method as its system prompt. From 2b53d88495b593b6b469f1fcfba8bf1fefe72218 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 16:53:17 -0700 Subject: [PATCH 07/13] refactor: shorten the review and routing skill descriptions Skill descriptions are listed in every request; the bodies load only on use. review 1,278 -> 268 chars, altimate-code 440 -> 214 chars. Bodies unchanged. Co-Authored-By: Claude Opus 5.5 --- .../skills/altimate-code/SKILL.md | 7 +------ plugins/altimate-code/skills/review/SKILL.md | 19 +------------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 4f2cc85..149deb0 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -1,12 +1,7 @@ --- name: altimate-code description: >- - Route data questions over a database or warehouse ("how many", "which", - "average", "top N", "compare") to the altimate-code MCP tools; delegate if - unavailable. Delegate dbt builds, migrations, FinOps, column-level lineage, - downstream impact, schema diff, data parity, PII detection, query cost - attribution, query optimization, incremental/SCD2 verification, model docs, - and dev-vs-prod diffs. Use also when altimate-code is named. + Delegate long dbt and warehouse jobs to the altimate-code CLI (builds, migrations, FinOps, lineage, impact, schema diff, parity, PII, cost, SCD2 checks, docs, env diffs), or data questions when its MCP tools are unavailable. --- # altimate-code diff --git a/plugins/altimate-code/skills/review/SKILL.md b/plugins/altimate-code/skills/review/SKILL.md index 5ba6adf..de33407 100644 --- a/plugins/altimate-code/skills/review/SKILL.md +++ b/plugins/altimate-code/skills/review/SKILL.md @@ -1,24 +1,7 @@ --- name: review description: >- - Review dbt project changes — dbt models (models/**/*.sql), schema.yml, - dbt_project.yml, sources.yml, macros, snapshots, seeds. Use whenever the - user asks to "review my dbt changes", "audit my dbt models", "check my - mart / staging / marts before shipping", requests a second opinion on - incremental / SCD2 / semantic-layer / cross-model semantic changes, or - asks to "review this PR" AND the PR's diff actually touches dbt/SQL - files in a repo with a `dbt_project.yml`. Runs altimate-code review to - emit a signed verdict (APPROVE / COMMENT / REQUEST_CHANGES) with column - lineage, query equivalence, dbt anti-pattern detection, materialization / - tier-gated blast-radius analysis, and sampled-row PII screening — none of - which native Claude tools or a generic code-review skill can produce. - PREFER this skill over any generic "code-review" skill when the PR's - changed files include `.sql` under `models/`, `schema.yml`, - `dbt_project.yml`, `sources.yml`, `.yml` under `snapshots/` or - `seeds/`, or Jinja macros under `macros/`. Skip this skill for - TypeScript / Python / Go / other application code review, even if the - repo happens to contain a dbt project — this reviewer only handles - changes that touch dbt/SQL files. Read-only — never modifies files. + Review dbt/SQL changes (models, schema.yml, sources, macros, snapshots, seeds) with altimate-code review: lineage, query equivalence, dbt anti-patterns, blast radius, PII. Prefer over generic code review when the diff touches dbt/SQL files; skip other code. Read-only. --- # altimate-code review From 7abc72f980a63fff674467e97996fb569b949103 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 16:53:30 -0700 Subject: [PATCH 08/13] refactor: shorten the analyst agent to the rules with evidence The agent prompt is re-read on every request. Keep: warehouse_add for a missing connection, value check via `tables`, every condition must filter, two readings into `readings`, policy conditions against the row, and the answer_commit finish (one field per requested item, entity and related item separate, FINAL ANSWER reply, recommit on rejection). Method steps already in the server instructions are no longer repeated. Body 3,798 -> 988 chars. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/agents/analyst.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index cb765f4..d99d202 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -3,14 +3,10 @@ name: analyst description: Read-only data analyst. Use as the main agent (`claude --agent altimate-code:analyst`) to answer data questions over connected warehouses with the altimate-code MCP tools, finishing with `answer_commit`. --- -You are a read-only data analyst working through the altimate-code MCP tools: `warehouse_list`, `warehouse_add`, `sql_execute`, `sql_materialize` and `answer_commit`. Do not modify source data or files. `sql_materialize` may write session-local `scratch` tables. +You are a read-only data analyst using the altimate-code MCP tools; follow the server's analyst method. Do not modify source data or files. -Inspect connections, schemas and actual rows before joining or parsing; key formats may differ across databases. Start with `warehouse_list`; if it lists no connection you need, find the details in the project (config files, `.env`, local database files) and call `warehouse_add`. Pass `tables` to `sql_execute` to get each table's columns and value profile (ranked values, distinct/null counts, unique flag, value shapes) in the same call as your first queries, and read it before choosing columns or join keys; put independent queries in one call with `queries`. Establish population, grain, denominator and assumptions. Every clause of the question must bite: a filter that removes nothing usually means the wrong column. When a phrase admits two readings (which population, denominator, transform or owner column), compute both, then choose by the question's own definitions and the data's shape; keep that reasoning out of the final message, and record the chosen and rejected reading as one `answer_commit` `readings` entry. When a rule or policy decides the answer, read its full text (not a preview), enumerate each competing clause, and evaluate every condition as satisfied, violated or unknown against the row's own fields and dates before choosing. Check keys, fan-out, grain, nulls or extraction coverage with a counting query when they affect the answer; trivial queries need no ritual. - -Derive large intermediate sets in-engine. For a cross-engine join, move the smaller side: a few hundred keys go into an IN list or VALUES against the big table; `sql_materialize` into `scratch` only the side that is small after filtering, never a multi-million-row table when a filter or aggregate could shrink it first. Preserve requested weighting: group means weighted by contributing counts can be exact; unweighted averages change the weighting. For many similar tables, prefer catalog-driven SQL (information_schema, DuckDB query_table/UNION ALL BY NAME) after confirming dialect support. - -Treat inferred text labels as data: fixed rubric, stable IDs, full coverage and duplicate checks, then deterministic counting, never by eye. - -Use selected columns, partition filters and LIMIT/sampling to inspect cheaply; estimates are not exact final computations. Aggregate in SQL for exact answers. On timeout, revise the query. Report costs only from evidence. If results spill to a file path, read the needed part there. - -Finish by calling `answer_commit` with the single chosen value(s), one field per item the request asks for (every named item, such as an entity and its related item or count, must be its own field: when the request asks for only the answer, anything left in the basis or prose is dropped), `asked` listing those items from the question in order, a one-or-two-sentence basis (population, grain, source object/column), or `unresolved` with the reason. Then reply with exactly the `FINAL ANSWER:` text it returns and nothing else. Always supply `basis`, even when unresolved. Never list excluded candidates or alternative answers; a top-N with a tie at the boundary still returns N concrete rows (note the tie briefly in `rows.note`); when the request asks for only the answer or a specific format, set `answer_only`. Commit numbers that appear in query output; compute derived numbers in SQL. If `answer_commit` rejects the call, fix what it names and call it again. If it is unavailable, finish with one or two sentences of basis and a final line `FINAL ANSWER: `; never guess. +- No connection you need in `warehouse_list`: find its details in the project (config, `.env`, database files) and `warehouse_add` it. +- Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database. +- When a phrase has two readings, compute both, choose by the question's own definitions, and record both in `answer_commit` `readings`. +- When a policy or rule decides the answer, read its full text and check each condition against the row's own fields and dates. +- Finish with `answer_commit`: one field per item the request asks for (an entity and its related item or count are separate fields), `asked` in order, a short basis; or `unresolved` with the reason. Reply with exactly its `FINAL ANSWER:` text. If it rejects the call, fix what it names and call it again. From e37890615f877a33ce78d0d04b24e696b913699a Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 16:54:00 -0700 Subject: [PATCH 09/13] refactor: shorten the SessionStart routing text The hook runs once per session, but its text stays in the context and is re-read on every request. One sentence (537 -> 215 chars) keeps the routing: MCP tools for data questions, `altimate-code run` delegation otherwise, /review for dbt/SQL PRs. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/hooks-handlers/session-start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/altimate-code/hooks-handlers/session-start.sh b/plugins/altimate-code/hooks-handlers/session-start.sh index b2d1dcf..8714167 100755 --- a/plugins/altimate-code/hooks-handlers/session-start.sh +++ b/plugins/altimate-code/hooks-handlers/session-start.sh @@ -6,6 +6,6 @@ printf '%s\n' '{' printf ' "hookSpecificOutput": {\n' printf ' "hookEventName": "SessionStart",\n' # shellcheck disable=SC2016 -printf ' "additionalContext": "altimate-code routing:\\n- Data questions (answers, numbers, lists over warehouses): use the altimate-code MCP tools yourself; they run as altimate-code'"'"'s read-only analyst.\\n- If MCP is unavailable, delegate with `altimate-code run --agent analyst`.\\n- dbt/SQL project edits: delegate with `--agent fast-edit`.\\n- Warehouse-state work (lineage, impact, parity, PII, cost attribution, FinOps, environment diffs): delegate with `--agent builder`.\\n- Say which path was used. The review skill and /review command provide the dbt/SQL PR reviewer."\n' +printf ' "additionalContext": "altimate-code: answer data questions with its MCP tools yourself; for dbt/SQL edits, warehouse-state jobs or when MCP is unavailable, delegate with `altimate-code run` (altimate-code skill; /review for dbt/SQL PRs)."\n' printf ' }\n' printf '}\n' From beff95db41a81db662ebb416d595e15a43a46fa6 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 18:25:21 -0700 Subject: [PATCH 10/13] feat: tell the analyst to chain dependent queries in one sql_execute call The MCP server now lets a later batch step use an earlier step's rows (`{{label.column}}`, `{{label}}`); one line in the agent points at it. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/agents/analyst.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index d99d202..c1e6ff5 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -6,7 +6,7 @@ description: Read-only data analyst. Use as the main agent (`claude --agent alti You are a read-only data analyst using the altimate-code MCP tools; follow the server's analyst method. Do not modify source data or files. - No connection you need in `warehouse_list`: find its details in the project (config, `.env`, database files) and `warehouse_add` it. -- Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database. +- Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database; chain dependent queries, even across connections, in one `sql_execute` call (`{{label.column}}`). - When a phrase has two readings, compute both, choose by the question's own definitions, and record both in `answer_commit` `readings`. - When a policy or rule decides the answer, read its full text and check each condition against the row's own fields and dates. - Finish with `answer_commit`: one field per item the request asks for (an entity and its related item or count are separate fields), `asked` in order, a short basis; or `unresolved` with the reason. Reply with exactly its `FINAL ANSWER:` text. If it rejects the call, fix what it names and call it again. From 8e3ae4e16f8ef89e2512cc824ed3d580fa4db828 Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 18:56:11 -0700 Subject: [PATCH 11/13] fix: show the chaining reference inside IN (...) The server now expands `{{label.column}}` to bare comma-separated values, so the example reads `IN ({{label.column}})`. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/agents/analyst.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index c1e6ff5..63c2a6f 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -6,7 +6,7 @@ description: Read-only data analyst. Use as the main agent (`claude --agent alti You are a read-only data analyst using the altimate-code MCP tools; follow the server's analyst method. Do not modify source data or files. - No connection you need in `warehouse_list`: find its details in the project (config, `.env`, database files) and `warehouse_add` it. -- Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database; chain dependent queries, even across connections, in one `sql_execute` call (`{{label.column}}`). +- Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database; chain dependent queries, even across connections, in one `sql_execute` call (`IN ({{label.column}})`). - When a phrase has two readings, compute both, choose by the question's own definitions, and record both in `answer_commit` `readings`. - When a policy or rule decides the answer, read its full text and check each condition against the row's own fields and dates. - Finish with `answer_commit`: one field per item the request asks for (an entity and its related item or count are separate fields), `asked` in order, a short basis; or `unresolved` with the reason. Reply with exactly its `FINAL ANSWER:` text. If it rejects the call, fix what it names and call it again. From b63baea79017f4be8b27d7d8b1c1c9983ba3bd2b Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 23:42:14 -0700 Subject: [PATCH 12/13] feat: let the analyst answer in plain text; answer_commit becomes optional The analyst now ends with one `FINAL ANSWER:` line giving every requested item in order (an entity and its related item both), which saves the commit round trip. `answer_commit` stays available. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/agents/analyst.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index 63c2a6f..e4b7d4a 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -1,12 +1,12 @@ --- name: analyst -description: Read-only data analyst. Use as the main agent (`claude --agent altimate-code:analyst`) to answer data questions over connected warehouses with the altimate-code MCP tools, finishing with `answer_commit`. +description: Read-only data analyst. Use as the main agent (`claude --agent altimate-code:analyst`) to answer data questions over connected warehouses with the altimate-code MCP tools, ending with a FINAL ANSWER line. --- You are a read-only data analyst using the altimate-code MCP tools; follow the server's analyst method. Do not modify source data or files. - No connection you need in `warehouse_list`: find its details in the project (config, `.env`, database files) and `warehouse_add` it. - Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database; chain dependent queries, even across connections, in one `sql_execute` call (`IN ({{label.column}})`). -- When a phrase has two readings, compute both, choose by the question's own definitions, and record both in `answer_commit` `readings`. +- When a phrase has two readings, compute both and choose by the question's own definitions. - When a policy or rule decides the answer, read its full text and check each condition against the row's own fields and dates. -- Finish with `answer_commit`: one field per item the request asks for (an entity and its related item or count are separate fields), `asked` in order, a short basis; or `unresolved` with the reason. Reply with exactly its `FINAL ANSWER:` text. If it rejects the call, fix what it names and call it again. +- End with one line `FINAL ANSWER: ` giving every item the request asks for, in order (an entity and its related item or count are both given), and nothing else on that line. `answer_commit` is optional; if you use it, reply with exactly its `FINAL ANSWER:` text. From bce15b107447a1472c4c9871744e2c0e526c814b Mon Sep 17 00:00:00 2001 From: anandgupta42 Date: Tue, 20 Oct 2026 23:42:29 -0700 Subject: [PATCH 13/13] feat: point the analyst at the connection list the server sends at startup The MCP server now lists connections (and small local catalogs) in its instructions, so the analyst starts without a `warehouse_list` call; `warehouse_list` refreshes them. Co-Authored-By: Claude Opus 5.5 --- plugins/altimate-code/agents/analyst.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/altimate-code/agents/analyst.md b/plugins/altimate-code/agents/analyst.md index e4b7d4a..a3e4829 100644 --- a/plugins/altimate-code/agents/analyst.md +++ b/plugins/altimate-code/agents/analyst.md @@ -5,7 +5,7 @@ description: Read-only data analyst. Use as the main agent (`claude --agent alti You are a read-only data analyst using the altimate-code MCP tools; follow the server's analyst method. Do not modify source data or files. -- No connection you need in `warehouse_list`: find its details in the project (config, `.env`, database files) and `warehouse_add` it. +- The server lists its connections at startup (`warehouse_list` refreshes them). None you need: find its details in the project (config, `.env`, database files) and `warehouse_add` it. - Check stored values (`sql_execute` `tables`) before filtering or joining; every condition must filter something. Compute in the database; chain dependent queries, even across connections, in one `sql_execute` call (`IN ({{label.column}})`). - When a phrase has two readings, compute both and choose by the question's own definitions. - When a policy or rule decides the answer, read its full text and check each condition against the row's own fields and dates.