# Altimate Docs > Documentation for Altimate Code, Power User for dbt, Altimate MCP, and the Enterprise Platform. # Overview # Altimate Documentation Guides, references, and quickstarts across Altimate Code, Power User for dbt, Altimate MCP, and the Enterprise Platform. Search the documentation… ## Altimate Platform Components Power User for dbt Altimate Code Altimate MCP Apps Model Router ### The VS Code and Cursor extension for dbt Build, document, and debug dbt models without leaving your editor. Navigate your project, preview query results, and generate docs — all from VS Code or Cursor. [Column lineage](https://help.altimate.ai/dbt-power-user/discover/viewlineage/index.md) [Query preview & export](https://help.altimate.ai/dbt-power-user/test/queryResults/index.md) [SQL → dbt model](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) [Doc generation to YAML](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md) `$ext install innoverio.vscode-dbt-power-user` Copy [Explore Documentation](https://help.altimate.ai/dbt-power-user/index.md) ### Open-source data engineering harness Run agents with deterministic data tools from a terminal, CI, or any LLM. [Context Compaction](https://help.altimate.ai/code/configure/context-management/index.md) [Validation Layer](https://help.altimate.ai/code/data-engineering/validators/index.md) [Session Traces](https://help.altimate.ai/code/configure/trace/index.md) [Memory Layer](https://help.altimate.ai/code/data-engineering/tools/memory-tools/index.md) `$npm install -g altimate-code` Copy [Explore Documentation](https://help.altimate.ai/code/index.md) ### Local-first MCP server Bring your data stack (Snowflake, dbt, Jira, Airflow) into Cursor, Claude Code, Cline and VS Code as tools. Credentials never leave your machine. [30+ Integrations](https://help.altimate.ai/datamates/user-guide/components/integrations/integrations/index.md) [Knowledge Hub](https://help.altimate.ai/datamates/user-guide/components/knowledgehub/index.md) [Memory Hub](https://help.altimate.ai/datamates/user-guide/components/memory/index.md) [Guardrails](https://help.altimate.ai/datamates/user-guide/components/guardrails/index.md) `$npx @anthropic-ai/claude-code mcp add datamates` Copy [Explore Documentation](https://help.altimate.ai/datamates/index.md) ### Customized UX for specific use cases Apps deliver tailored interfaces built on the Enterprise Platform — purpose-built for specific data workflows with additional functionality including governance studio, natural language analytics, cost intelligence, and autonomous warehouse savings. [Snowflake Optimization Enterprise App](https://help.altimate.ai/platform/) [Altimate Lite for Snowflake](https://help.altimate.ai/snowflake-native-app/index.md) [Databricks Optimization](https://help.altimate.ai/platform/) [Pipelines Migration](https://help.altimate.ai/platform/) [Explore Documentation](https://help.altimate.ai/platform/) ### Intelligent model routing across providers Stop managing API keys and pay a flat rate across models. Dynamic routing across Claude, GPT, Gemini and more. 60-80% cheaper than direct provider tokens. BYOK stays free. [Dynamic Routing](https://help.altimate.ai/resources/llm-gateway/index.md) [Multi-provider](https://help.altimate.ai/resources/llm-gateway/index.md) [Explore Documentation](https://help.altimate.ai/resources/llm-gateway/index.md) ## Quickstart With Popular Resources [**Quickstart**Install and run your first agent query in under 5 minutes.](https://help.altimate.ai/code/getting-started/quickstart/index.md) [**Agent Modes**Configure how agents interact with your data stack.](https://help.altimate.ai/code/data-engineering/agent-modes/index.md) [**Power User for dbt Setup**Install the extension and connect your dbt project.](https://help.altimate.ai/dbt-power-user/setup/installation/index.md) [**Altimate MCP Setup**Add the MCP server to your IDE in two commands.](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md) [**LLM Gateway**Multi-model routing at a flat rate. 10M free tokens included.](https://help.altimate.ai/resources/llm-gateway/index.md) [**Governance**Agent modes, rules, PII guardrails and data contracts.](https://help.altimate.ai/code/configure/governance/index.md) [**Examples & Recipes**End-to-end walkthroughs across dbt, Snowflake and more.](https://help.altimate.ai/resources/examples/index.md) [**Troubleshooting**Fixes and FAQs across every product.](https://help.altimate.ai/resources/troubleshooting/index.md) ## Browse By Need Find what you need by what you are trying to do. [**Write & generate SQL**Agent modes, SQL tools, and end-to-end walkthroughs.](https://help.altimate.ai/code/data-engineering/agent-modes/index.md) [**Build & test dbt**dbt tools, Power User features, validators and testing.](https://help.altimate.ai/dbt-power-user/index.md) [**Understand your data**Lineage, schema analysis, documentation and context graph.](https://help.altimate.ai/code/data-engineering/tools/lineage-tools/index.md) [**Secure & govern**PII guardrails, governance rules, permissions and data contracts.](https://help.altimate.ai/code/configure/governance/index.md) [**Optimize costs**FinOps tools, warehouse cost intelligence and autonomous savings.](https://help.altimate.ai/platform/) [**Connect everything**Integrations, MCP servers, CI/CD pipelines and LLM providers.](https://help.altimate.ai/datamates/user-guide/components/integrations/integrations/index.md) \[#1 ADE-Bench (74.4%)\](https://www.altimate.sh/benchmarks) 100+ Deterministic tools 80+ Integrations 10M Free LLM tokens # Altimate Code # Configure Set up your warehouses, LLM providers, and preferences. For agents, tools, skills, and commands, see the [Use](https://help.altimate.ai/code/data-engineering/agent-modes/index.md) section. For rules, permissions, and context management, see [Governance](https://help.altimate.ai/code/configure/rules/index.md). ## What's in this section - **Config File Reference** ______________________________________________________________________ JSON configuration file locations, schema, value substitution, and project structure. [Config File](https://help.altimate.ai/code/configure/config/index.md) - **Warehouses** ______________________________________________________________________ Connect to Snowflake, BigQuery, Databricks, PostgreSQL, Redshift, DuckDB, MySQL, and SQL Server. Includes key-pair auth, IAM, ADC, and SSH tunneling. [Warehouses](https://help.altimate.ai/code/configure/warehouses/index.md) - **LLMs** ______________________________________________________________________ Connect to 35+ LLM providers — Anthropic, OpenAI, Bedrock, Ollama, and more. Configure API keys and model selection. [Providers](https://help.altimate.ai/code/configure/providers/index.md) · [Models](https://help.altimate.ai/code/configure/models/index.md) - **MCPs & ACPs** ______________________________________________________________________ Extend Altimate Code with MCP servers (local and remote) and ACP-compatible editor integrations. [MCP Servers](https://help.altimate.ai/code/configure/mcp-servers/index.md) · [ACP Support](https://help.altimate.ai/code/configure/acp/index.md) - **Appearance** ______________________________________________________________________ Themes, keybinds, and visual customization for the TUI. [Themes](https://help.altimate.ai/code/configure/themes/index.md) · [Keybinds](https://help.altimate.ai/code/configure/keybinds/index.md) - **Additional Config** ______________________________________________________________________ LSP servers, network/proxy settings, and Windows/WSL setup. [LSP Servers](https://help.altimate.ai/code/configure/lsp/index.md) · [Network](https://help.altimate.ai/code/reference/network/index.md) · [Windows / WSL](https://help.altimate.ai/code/reference/windows-wsl/index.md) # ACP Support altimate implements the Agent Communication Protocol (ACP), allowing it to act as a backend for editors and IDEs. ## Usage ```bash altimate acp ``` This starts altimate in ACP mode, ready to accept connections from compatible editors. ## Editor Configuration ### Zed Add to your Zed settings: ```json { "language_models": { "altimate": { "command": ["altimate", "acp"] } } } ``` ### JetBrains IDEs Configure altimate as an external AI provider in your JetBrains IDE settings. ### Neovim Use an ACP-compatible Neovim plugin to connect to altimate: ```lua require("acp").setup({ command = { "altimate", "acp" } }) ``` ## Features ACP mode provides: - Model access through your configured providers - Tool execution (file operations, search, shell commands) - Agent selection and switching - Full data engineering tool access # Agents Agents define different AI personas with specific models, prompts, permissions, and capabilities. ## Built-in Agents | Agent | Description | Access Level | | --------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | `builder` | Create and modify dbt models, SQL pipelines, and data transformations | Full read/write. SQL mutations prompt for approval. | | `analyst` | Answer questions about your data — explore it, run SELECT queries, inspect schemas, generate insights | Read-only (enforced). SQL writes denied. Safe bash commands auto-allowed. | | `plan` | Plan before acting — restricted to planning files only | Minimal — no edits, no bash, no SQL | ### Builder Full access mode. Can read/write files, run any bash command (with approval), execute SQL, and modify dbt models. SQL write operations (`INSERT`, `UPDATE`, `DELETE`, `CREATE`, etc.) prompt for user approval. Destructive SQL (`DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE`) is hard-blocked. ### Analyst The agent for asking questions about your data. Truly read-only mode for safe data exploration: - **File access**: Read, grep, glob — no prompts - **SQL**: SELECT queries execute freely. Write queries are denied (not prompted — blocked entirely) - **Bash**: Safe commands auto-allowed (`ls`, `grep`, `cat`, `head`, `tail`, `find`, `wc`). dbt read commands allowed (`dbt list`, `dbt ls`, `dbt debug`). Everything else denied. - **Web**: Fetch and search allowed without prompts - **Schema/warehouse/finops**: All inspection tools available Tip Use `analyst` when exploring data to ensure no accidental writes. Switch to `builder` when you're ready to create or modify models. ### Plan Planning mode with minimal permissions. Can only read files and edit plan files in `.opencode/plans/`. No SQL, no bash, no file modifications. ## SQL Write Access Control All SQL queries are classified before execution: | Query Type | Builder | Analyst | | ----------------------------------------------- | ------------------------- | ------- | | `SELECT`, `SHOW`, `DESCRIBE`, `EXPLAIN` | Allowed | Allowed | | `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER` | Prompts for approval | Denied | | `DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE` | Blocked (cannot override) | Blocked | The classifier detects write operations including: `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `DROP`, `ALTER`, `TRUNCATE`, `GRANT`, `REVOKE`, `COPY INTO`, `CALL`, `EXEC`, `EXECUTE IMMEDIATE`, `BEGIN`, `DECLARE`, `REPLACE`, `UPSERT`, `RENAME`. Multi-statement queries (`SELECT 1; INSERT INTO ...`) are classified as write if any statement is a write. ## Custom Agents Define custom agents in `altimate-code.json`: ```json { "agent": { "reviewer": { "model": "anthropic/claude-sonnet-4-6", "prompt": "You are a data engineering code reviewer. Focus on SQL best practices, dbt conventions, and warehouse cost efficiency.", "description": "Reviews data engineering code", "permission": { "write": "deny", "edit": "deny", "bash": { "dbt docs generate": "allow", "*": "deny" } } } } } ``` ## Agent Configuration | Field | Type | Description | | ------------- | --------- | ------------------------------------- | | `model` | `string` | Model to use (`provider/model`) | | `variant` | `string` | Model variant | | `temperature` | `number` | Sampling temperature | | `top_p` | `number` | Nucleus sampling | | `prompt` | `string` | System prompt | | `description` | `string` | Agent description | | `disable` | `boolean` | Disable this agent | | `mode` | `string` | `"primary"`, `"subagent"`, or `"all"` | | `hidden` | `boolean` | Hide from agent list (subagents only) | | `color` | `string` | Hex color or theme color name | | `steps` | `number` | Max agentic iterations | | `permission` | `object` | Agent-specific permissions | | `options` | `object` | Custom options | ## Markdown Agent Definitions Create agents as markdown files in `.altimate-code/agents/`: ```markdown --- name: cost-reviewer model: anthropic/claude-sonnet-4-6 description: "Reviews queries for cost efficiency" --- You are a Snowflake cost optimization expert. For every query: 1. Estimate credit consumption 2. Suggest warehouse size optimization 3. Flag full table scans and cartesian joins 4. Recommend clustering keys where appropriate ``` Info Markdown agent files use YAML frontmatter for configuration and the body as the system prompt. ## Agent Permissions Each agent can have its own permission overrides: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "sql_execute_write": "deny", "bash": { "*": "deny", "dbt list *": "allow", "ls *": "allow" } } } } } ``` Warning Agent-specific permissions override global permissions. A `"deny"` at the agent level cannot be overridden by a global `"allow"`. ## Switching Agents - **TUI**: Press leader + `a` or use `/agent ` - **CLI**: `altimate --agent analyst` - **In conversation**: Type `/agent analyst` # Amazon Bedrock Custom Endpoints This guide covers using Altimate Code with a custom Amazon Bedrock endpoint — such as a corporate API gateway, reverse proxy, or VPC endpoint that sits in front of Bedrock. ## When to use this Use this setup when your organization: - Routes Bedrock traffic through a centralized API gateway - Requires a custom domain or proxy for compliance / network policy - Uses a bearer token instead of standard AWS IAM credentials ## Prerequisites You need one of the following: - A **bearer token** issued by your gateway (most common for custom endpoints) - Standard **AWS credentials** (access key, SSO profile, IAM role) if your gateway still delegates to the AWS credential chain ## Step 1: Set up authentication Export the token as an environment variable. Add this to your shell profile (`~/.zshrc`, `~/.bashrc`, or equivalent): ```bash export AWS_BEARER_TOKEN_BEDROCK="your-bearer-token-here" ``` Then reload your shell: ```bash source ~/.zshrc ``` Tip If your organization uses the Altimate Code TUI, you can store the token via `altimate-code auth login --provider amazon-bedrock` instead of exporting it in your shell profile. If your gateway forwards standard AWS credentials, no extra auth setup is needed. Altimate Code uses the standard AWS credential chain: 1. `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` environment variables 1. `AWS_PROFILE` (named profile from `~/.aws/config`) 1. IAM role / SSO session 1. Web identity token (`AWS_WEB_IDENTITY_TOKEN_FILE`) 1. ECS / EKS container credentials To use a specific AWS profile, set it in the config: ```json { "provider": { "amazon-bedrock": { "options": { "profile": "my-sso-profile" } } } } ``` Note When a bearer token is present, the AWS credential chain is bypassed entirely. The bearer token always takes precedence. ## Step 2: Create the config Create or edit `~/.config/altimate-code/altimate-code.json`: ```json { "model": "amazon-bedrock/anthropic.claude-sonnet-4-6-v1", "provider": { "amazon-bedrock": { "options": { "baseURL": "https://your-gateway.example.com/bedrock/v1", "region": "us-east-1" } } } } ``` | Field | Description | | --------- | --------------------------------------------------------------------- | | `model` | The model to use, prefixed with `amazon-bedrock/`. | | `baseURL` | Your custom gateway URL. Replace with your organization's endpoint. | | `region` | The AWS region your gateway targets (e.g., `us-east-1`, `eu-west-1`). | The `baseURL` path The path portion of the `baseURL` (e.g., `/bedrock/v1`) depends entirely on how your API gateway is configured. Ask your platform team for the correct URL — there is no universal standard path. ### Config scope | Config location | Scope | | -------------------------------------------- | -------------------------------------------------- | | `~/.config/altimate-code/altimate-code.json` | Global — applies to all projects | | `altimate-code.json` in a project root | Project — overrides global config for that project | ## Step 3: Launch ```bash altimate-code ``` The status bar should display your selected model under Amazon Bedrock. ## Cross-region model ID prefixing Altimate Code may prepend a region prefix to model IDs for cross-region inference when the selected model and region require it. For example, with `region: "us-east-1"` the model ID `anthropic.claude-sonnet-4-6-v1` is sent to the gateway as `us.anthropic.claude-sonnet-4-6-v1`. Prefixing is conditional on **both** the region and the model family: | Your region | Prefix | Models prefixed | | ---------------------------------------------- | ------- | ----------------------------------------- | | `us-*` (except GovCloud) | `us.` | Claude, Nova, DeepSeek | | `eu-*` | `eu.` | Claude, Nova Lite/Micro, Llama 3, Pixtral | | `ap-northeast-1` (Tokyo) | `jp.` | Claude, Nova Lite/Micro/Pro | | `ap-southeast-2`, `ap-southeast-4` (Australia) | `au.` | Claude Sonnet 4.5, Claude Haiku | | Other `ap-*` | `apac.` | Claude, Nova Lite/Micro/Pro | Models not listed in the table for a given region are **not** prefixed. **If your gateway expects the prefixed ID** (e.g., `us.anthropic.claude-sonnet-4-6-v1`), no changes are needed — this is the default behavior for supported models. **If your gateway requires a specific prefixed model ID**, you can force that exact ID by including the recognized prefix yourself: ```json { "model": "amazon-bedrock/us.anthropic.claude-sonnet-4-6-v1" } ``` When the model ID already starts with a recognized prefix (`us.`, `eu.`, `global.`, `jp.`, `apac.`, `au.`), auto-prefixing is skipped and the ID is passed through as-is. Note that this does **not** strip the prefix — the full prefixed ID is what gets sent to the gateway. Warning There is currently no config option to disable auto-prefixing entirely. If your gateway requires bare (unprefixed) model IDs and the model would normally be prefixed, contact your platform team or open an issue. ## Troubleshooting ### Verify credentials and config ```bash altimate-code providers list ``` This shows all stored credentials and active environment variables. You should see `Amazon Bedrock` listed under credentials or environment. ### Check config resolution Look for these lines in the logs (`~/.local/share/altimate-code/log/*.log`): | Log line | Meaning | | ---------------------------------------------------------- | ------------------------------ | | `service=config loading config from ...altimate-code.json` | Config file is being read | | `service=provider providerID=amazon-bedrock found` | Provider detected successfully | | `service=provider providerID=amazon-bedrock` + error | Auth or endpoint failure | ### Enable debug logging For detailed output including credential chain steps and SDK-level request info: ```bash altimate-code --log-level DEBUG ``` ## Full config reference ```json { "model": "amazon-bedrock/anthropic.claude-sonnet-4-6-v1", "provider": { "amazon-bedrock": { "options": { "baseURL": "https://your-gateway.example.com/bedrock/v1", "region": "us-east-1", "profile": "my-aws-profile" } } } } ``` | Option | Type | Description | | ---------- | -------- | ------------------------------------------------------------------ | | `baseURL` | `string` | Custom API gateway URL. Overrides the default Bedrock endpoint. | | `endpoint` | `string` | Alias for `baseURL`. If both are set, `endpoint` takes precedence. | | `region` | `string` | AWS region. Falls back to `AWS_REGION` env var, then `us-east-1`. | | `profile` | `string` | AWS named profile. Falls back to `AWS_PROFILE` env var. | # Commands ## Built-in Commands altimate ships with six built-in slash commands: | Command | Description | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `/init` | Create or update an AGENTS.md file with build commands and code style guidelines. | | `/discover` | Scan your data stack and set up warehouse connections. Detects dbt projects, warehouse connections from profiles/Docker/env vars, installed tools, and config files. Walks you through adding and testing new connections, then indexes schemas. | | `/review` | Review changes. Accepts `commit`, `branch`, or `pr` as an argument (defaults to uncommitted changes). | | `/feedback` | Submit product feedback as a GitHub issue. Guides you through title, category, description, and optional session context. | | `/configure-claude` | Configure altimate as a `/altimate` slash command in [Claude Code](https://claude.com/claude-code). Writes `~/.claude/commands/altimate.md` so you can invoke altimate from within Claude Code sessions. | | `/configure-codex` | Configure altimate as a skill in [Codex CLI](https://developers.openai.com/codex). Creates `~/.codex/skills/altimate/SKILL.md` so Codex can delegate data engineering tasks to altimate. | ### `/discover` The recommended way to set up a new data engineering project. Run `/discover` in the TUI and the agent will: 1. Call `project_scan` to detect your full environment 1. Present what was found (dbt project, connections, tools, config files) 1. Offer to add each new connection discovered (from dbt profiles, Docker, environment variables) 1. Test each connection with `warehouse_test` 1. Offer to index schemas for autocomplete and context-aware analysis 1. Show available skills and agent modes ### `/review` ```text /review # review uncommitted changes /review commit # review the last commit /review branch # review all changes on the current branch /review pr # review the current pull request ``` ### `/feedback` Submit product feedback directly from the CLI. The agent walks you through: 1. **Title**, a short summary of your feedback 1. **Category**: bug, feature, improvement, or ux 1. **Description** with a detailed explanation 1. **Session context** (opt-in), which includes working directory name and session ID for debugging ```text /feedback # start the guided feedback flow /feedback dark mode support # pre-fill the description ``` Requires the `gh` CLI to be installed and authenticated (`gh auth login`). ### `/configure-claude` Set up altimate as a tool inside Claude Code: ```text /configure-claude ``` This creates `~/.claude/commands/altimate.md`, which registers a `/altimate` slash command in Claude Code. After running this, you can use `/altimate` in any Claude Code session to delegate data engineering tasks: ```text # In Claude Code /altimate analyze the cost of our top 10 most expensive queries ``` ### `/configure-codex` Set up altimate as a skill inside Codex CLI: ```text /configure-codex ``` This creates `~/.codex/skills/altimate/SKILL.md`. Restart Codex after running this command. Codex will then automatically invoke altimate when you ask about data engineering tasks. ## Custom Commands Custom commands let you define reusable slash commands. ## Creating Commands Create markdown files in `.altimate-code/commands/`: ```text .altimate-code/ commands/ review.md optimize.md test-coverage.md ``` ### Command Format ```markdown --- name: review description: "Review SQL for anti-patterns and best practices" --- Review the following SQL file for: 1. Anti-patterns (SELECT *, missing WHERE clauses, implicit joins) 2. Cost efficiency (full table scans, unnecessary CTEs) 3. dbt best practices (ref() usage, naming conventions) File: $ARGUMENTS ``` ### Frontmatter Fields | Field | Required | Description | | ------------- | -------- | --------------------------------- | | `name` | Yes | Command name (used as `/name`) | | `description` | Yes | Description shown in command list | ### Variables | Variable | Description | | ------------ | --------------------------------------- | | `$ARGUMENTS` | Everything typed after the command name | ## Using Commands In the TUI: ```text /review models/staging/stg_orders.sql /optimize warehouse queries ``` ## Discovery Commands are loaded from: 1. `.altimate-code/commands/` in the project directory 1. `~/.config/altimate-code/commands/` globally Press leader + `/` to see all available commands. ## External CLI Integration The `/configure-claude` and `/configure-codex` commands write integration files to external CLI tools: | Command | File created | Purpose | | ------------------- | ----------------------------------- | -------------------------------------------------- | | `/configure-claude` | `~/.claude/commands/altimate.md` | Registers `/altimate` slash command in Claude Code | | `/configure-codex` | `~/.codex/skills/altimate/SKILL.md` | Registers altimate as a Codex CLI skill | These files allow you to invoke altimate's data engineering capabilities from within other AI coding agents. # Configuration altimate uses JSON (or JSONC) configuration files. The config file is named `altimate-code.json` or `altimate-code.jsonc`. ## Config File Locations Configuration is loaded from multiple sources, with later sources overriding earlier ones: | Priority | Source | Location | | ----------- | ---------------- | ----------------------------------------------------------------- | | 1 (lowest) | Remote defaults | `.well-known/altimate-code` (organization) | | 2 | Global config | `~/.config/altimate-code/altimate-code.json` | | 3 | Custom config | Path from `ALTIMATE_CLI_CONFIG` env var | | 4 | Project config | `altimate-code.json` (searched up directory tree) | | 5 | Directory config | `.altimate-code/altimate-code.json` (searched up tree) | | 6 | Inline config | `ALTIMATE_CLI_CONFIG_CONTENT` env var (JSON string) | | 7 (highest) | Managed config | `/Library/Application Support/altimate-code/` (macOS, enterprise) | Tip For most projects, create a `altimate-code.json` in your project root or use the `.altimate-code/` directory for a cleaner setup. ## Minimal Example ```json { "provider": { "anthropic": { "apiKey": "{env:ANTHROPIC_API_KEY}" } }, "model": "anthropic/claude-sonnet-4-6" } ``` ## Full Schema | Field | Type | Description | | --------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `$schema` | `string` | JSON schema URL for editor autocompletion | | `theme` | `string` | UI theme name | | `username` | `string` | Custom display username | | `model` | `string` | Default model (`provider/model`) | | `small_model` | `string` | Smaller model for lightweight tasks | | `default_agent` | `string` | Default agent to use on startup | | `logLevel` | `string` | Log level: `DEBUG`, `INFO`, `WARN`, `ERROR` | | `share` | `string` | Session sharing: `"manual"`, `"auto"`, `"disabled"` | | `autoupdate` | `boolean \| "notify"` | Auto-update behavior: `true` (default) auto-upgrades, `"notify"` shows an indicator without upgrading, `false` disables auto-upgrade but still shows the update indicator | | `provider` | `object` | Provider configurations (see [Providers](https://help.altimate.ai/code/configure/providers/index.md)) | | `mcp` | `object` | MCP server configurations (see [MCP Servers](https://help.altimate.ai/code/configure/mcp-servers/index.md)) | | `formatter` | `object \| false` | Formatter settings (see [Formatters](https://help.altimate.ai/code/configure/formatters/index.md)) | | `lsp` | `object \| false` | LSP server settings (see [LSP Servers](https://help.altimate.ai/code/configure/lsp/index.md)) | | `permission` | `object` | Permission rules (see [Permissions](https://help.altimate.ai/code/configure/permissions/index.md)) | | `agent` | `object` | Agent definitions (see [Agents](https://help.altimate.ai/code/configure/agents/index.md)) | | `keybinds` | `object` | Keybinding overrides (see [Keybinds](https://help.altimate.ai/code/configure/keybinds/index.md)) | | `tui` | `object` | TUI settings | | `server` | `object` | Server settings | | `skills` | `object` | Skill paths and URLs | | `plugin` | `string[]` | Plugin specifiers | | `instructions` | `string[]` | Glob patterns for instruction files | | `telemetry` | `object` | Telemetry settings (see [Telemetry](https://help.altimate.ai/code/reference/telemetry/index.md)) | | `compaction` | `object` | Context compaction settings (see [Context Management](https://help.altimate.ai/code/configure/context-management/index.md)) | | `experimental` | `object` | Experimental feature flags | ### Experimental Flags These flags are under `experimental` and may change or be removed in future releases. | Flag | Type | Default | Description | | --------------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `env_fingerprint_skill_selection` | `boolean` | `false` | Use environment fingerprint (dbt, airflow, databricks, SQL) to select relevant skills once per session via LLM. When enabled, the configured model runs once at session start to filter skills based on detected project environment. Results are cached per working directory. When disabled (default), all skills are shown. | | `auto_enhance_prompt` | `boolean` | `false` | Automatically rewrite prompts with AI before sending. Uses a small model to clarify rough prompts. | Example: ```json { "experimental": { "env_fingerprint_skill_selection": true } } ``` ## Value Substitution Config values support dynamic substitution so you never need to hardcode secrets. ### Environment Variables Use `{env:VAR_NAME}` to inject environment variables: ```json { "provider": { "anthropic": { "apiKey": "{env:ANTHROPIC_API_KEY}" } } } ``` ### File Contents Use `{file:path}` to read a secret from a file: ```json { "provider": { "anthropic": { "apiKey": "{file:~/.secrets/anthropic-key}" } } } ``` Warning Never commit plaintext API keys to version control. Always use `{env:...}` or `{file:...}` substitution. ## Project Structure A typical project layout using the `.altimate-code/` directory: ```text my-project/ .altimate-code/ altimate-code.json # Project config agents/ # Custom agent definitions commands/ # Custom slash commands plugins/ # Custom plugins tools/ # Custom tools skill/ # Custom skills altimate-code.json # Alternative project config location ``` ## Compaction Settings Control how context is managed when conversations grow long: ```json { "compaction": { "auto": true, "prune": true, "reserved": 4096 } } ``` | Field | Default | Description | | ---------- | ------- | --------------------------------- | | `auto` | `true` | Auto-compact when context is full | | `prune` | `true` | Prune old tool outputs | | `reserved` | (none) | Token buffer to reserve | Info Compaction automatically summarizes older messages to free up context window space, allowing longer conversations without losing important context. See [Context Management](https://help.altimate.ai/code/configure/context-management/index.md) for full details. # Context Management altimate automatically manages conversation context so you can work through long sessions without hitting model limits. When a conversation grows large, the CLI summarizes older messages, prunes stale tool outputs, and recovers from provider overflow errors, all without losing the important details of your work. ## How It Works Every LLM has a finite context window. As you work, each message, tool call, and tool result adds tokens to the conversation. When the conversation approaches the model's limit, altimate takes action: 1. **Prune.** Old tool outputs (file reads, command results, query results) are replaced with compact summaries 1. **Compact.** The entire conversation history is summarized into a continuation prompt 1. **Continue.** The agent picks up where it left off using the summary This happens automatically by default. You do not need to manually manage context. ## Auto-Compaction When enabled (the default), altimate monitors token usage after each model response. If the conversation is approaching the context limit, it triggers compaction automatically. During compaction: - A dedicated compaction agent summarizes the full conversation - The summary captures goals, progress, discoveries, relevant files, and next steps - The original messages are retained in session history but the model continues from the summary - After compaction, the agent automatically continues working if there are clear next steps You will see a compaction indicator in the TUI when this happens. The conversation continues seamlessly. Tip If you notice compaction happening frequently, consider using a model with a larger context window or breaking your task into smaller sessions. ## Observation Masking (Pruning) Before compaction, altimate prunes old tool outputs to reclaim context space. This is called "observation masking." When a tool output is pruned, it is replaced with a brief fingerprint: ```text [Tool output cleared — read_file(file: src/main.ts) returned 42 lines, 1.2 KB — "import { App } from './app'"] ``` This tells the model what tool was called, what arguments were used, how much output it produced, and the first line of the result. That is enough to maintain continuity without consuming tokens. **Pruning rules:** - Only tool outputs older than the most recent 2 turns are eligible - The most recent ~40,000 tokens of tool outputs are always preserved - Pruning only fires when at least 20,000 tokens can be reclaimed - `skill` tool outputs are never pruned (they contain critical session context) ## Data Engineering Context Compaction is aware of data engineering workflows. When summarizing a conversation, the compaction prompt preserves: - **Warehouse connections**, including which databases or warehouses are connected - **Schema context**, including discovered tables, columns, and relationships - **dbt project state**, including models, sources, tests, and project structure - **Lineage findings**, including upstream and downstream dependencies - **Query patterns**, including SQL dialects, anti-patterns, and optimization opportunities - **FinOps context**, including cost findings and warehouse sizing recommendations This means you can run a long data exploration session and compaction will not lose track of what schemas you discovered, what dbt models you were working with, or what cost optimizations you identified. ## Provider Overflow Detection If compaction does not trigger in time and the model returns a context overflow error, altimate detects it and automatically compacts the conversation. Overflow detection works with all major providers: | Provider | Detection | | ------------------------------ | --------------------------------------- | | Anthropic | "prompt is too long" | | OpenAI | "exceeds the context window" | | AWS Bedrock | "input is too long for requested model" | | Google Gemini | "input token count exceeds the maximum" | | Azure OpenAI | "the request was too long" | | Groq | "reduce the length of the messages" | | OpenRouter / DeepSeek | "maximum context length is N tokens" | | xAI (Grok) | "maximum prompt length is N" | | GitHub Copilot | "exceeds the limit of N" | | Ollama / llama.cpp / LM Studio | Various local server messages | When an overflow is detected, the CLI automatically compacts and retries. No action is needed on your part. ### Loop Protection If compaction fails to reduce context sufficiently and overflow keeps recurring, altimate stops after 3 consecutive compaction attempts within the same turn. You will see a message asking you to start a new conversation. The counter resets after each successful processing step, so compactions spread across different turns do not count against the limit. Note Some providers (such as z.ai) may accept oversized inputs silently. For these, the automatic token-based compaction trigger is the primary safeguard. ## Configuration Control context management behavior in `altimate-code.json`: ```json { "compaction": { "auto": true, "prune": true, "reserved": 20000 } } ``` | Field | Type | Default | Description | | ---------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `auto` | `boolean` | `true` | Automatically compact when the context window is nearly full | | `prune` | `boolean` | `true` | Prune old tool outputs before compaction | | `reserved` | `number` | `20000` | Token buffer to reserve below the context limit. The actual headroom is `max(reserved, model_max_output)`, so this value only takes effect when it exceeds the model's output token limit. Increase if you see frequent overflow errors | ### Disabling Auto-Compaction If you prefer to manage context manually (for example, by starting new sessions), disable auto-compaction: ```json { "compaction": { "auto": false } } ``` Warning With auto-compaction disabled, you may hit context overflow errors during long sessions. The CLI will still detect and recover from these, but the experience will be less smooth. ### Manual Compaction You can trigger compaction at any time from the TUI by pressing `leader` + `c`, or by using the `/compact` command in conversation. This is useful when you want to create a checkpoint before switching tasks. ## Token Estimation altimate uses content-aware heuristics to estimate token counts without calling a tokenizer. This keeps overhead low while maintaining accuracy. The estimator detects content type and adjusts its ratio: | Content Type | Characters per Token | Detection | | ------------ | -------------------- | -------------------------------------------------------- | | Code | ~3.0 | High density of `{}();=` characters | | JSON | ~3.2 | Starts with `{` or `[`, high density of `{}[]:,"` | | SQL | ~3.5 | Contains SQL keywords (`SELECT`, `FROM`, `JOIN`, etc.) | | Plain text | ~4.0 | Default for prose and markdown | | Mixed | ~3.7 | Fallback for content that does not match a specific type | These ratios are tuned against the cl100k_base tokenizer used by Claude and GPT-4 models. The estimator samples the first 500 characters of content to classify it, so the overhead is negligible. Limitations The heuristic uses JavaScript string length (UTF-16 code units), which over-estimates tokens for emoji (2 code units but ~1-2 tokens) and CJK characters. For precise token counting, a future update will integrate a native tokenizer. # Custom Tools Create custom tools using TypeScript and the altimate plugin system. ## Quick Start 1. Create a tools directory: ```bash mkdir -p .altimate-code/tools ``` 1. Create a tool file: ```typescript // .altimate-code/tools/my-tool.ts import { defineTool } from "@altimateai/altimate-code-plugin/tool" import { z } from "zod" export default defineTool({ name: "my_custom_tool", description: "Does something useful", parameters: z.object({ input: z.string().describe("The input to process"), }), async execute({ input }) { // Your tool logic here return { result: `Processed: ${input}` } }, }) ``` ## Plugin Package For more complex tools, create a plugin package: ```bash npm init npm install @altimateai/altimate-code-plugin zod ``` ```typescript // index.ts import { definePlugin } from "@altimateai/altimate-code-plugin" import { z } from "zod" export default definePlugin({ name: "my-plugin", tools: [ { name: "analyze_costs", description: "Analyze warehouse costs", parameters: z.object({ warehouse: z.string(), days: z.number().default(30), }), async execute({ warehouse, days }) { // Implementation return { costs: [] } }, }, ], }) ``` ## Registering Plugins Add plugins to your config: ```json { "plugin": [ "@altimateai/altimate-code-plugin-example", "./my-local-plugin" ] } ``` ## Plugin Hooks Plugins can hook into 30+ lifecycle events: - `onSessionStart` / `onSessionEnd` - `onMessage` / `onResponse` - `onToolCall` / `onToolResult` - `onFileEdit` / `onFileWrite` - `onError` - And more... ## Disabling Default Plugins ```bash export ALTIMATE_CLI_DISABLE_DEFAULT_PLUGINS=true ``` # Formatters altimate auto-formats files after editing using language-specific formatters. ## How It Works When a file is modified by an agent, altimate: 1. Detects the file extension 1. Finds a matching formatter 1. Checks if the formatter is available (binary in PATH or project dependency) 1. Runs the formatter on the modified file ## Supported Formatters | Formatter | Extensions | Detection | Command | | ------------------ | ----------------------------------------------------- | ---------------------------------- | ------------------------------------------ | | **prettier** | `.js`, `.jsx`, `.ts`, `.tsx`, `.json`, `.yaml`, `.md` | `package.json` deps | `bun x prettier --write $FILE` | | **biome** | `.ts`, `.js`, `.json`, `.css`, `.html` | `biome.json` | `bun x @biomejs/biome check --write $FILE` | | **gofmt** | `.go` | `gofmt` in PATH | `gofmt -w $FILE` | | **rustfmt** | `.rs` | `rustfmt` in PATH | `rustfmt $FILE` | | **ruff** | `.py`, `.pyi` | `ruff` binary + config | `ruff format $FILE` | | **clang-format** | `.c`, `.cpp`, `.h` | `.clang-format` file | `clang-format -i $FILE` | | **ktlint** | `.kt`, `.kts` | `ktlint` in PATH | `ktlint -F $FILE` | | **mix** | `.ex`, `.exs`, `.eex`, `.heex` | `mix` in PATH | `mix format $FILE` | | **dart** | `.dart` | `dart` in PATH | `dart format $FILE` | | **shfmt** | `.sh`, `.bash` | `shfmt` in PATH | `shfmt -w $FILE` | | **terraform** | `.tf`, `.tfvars` | `terraform` in PATH | `terraform fmt $FILE` | | **gleam** | `.gleam` | `gleam` in PATH | `gleam format $FILE` | | **nixfmt** | `.nix` | `nixfmt` in PATH | `nixfmt $FILE` | | **rubocop** | `.rb`, `.rake`, `.gemspec` | `rubocop` in PATH | `rubocop --autocorrect $FILE` | | **standardrb** | `.rb`, `.rake`, `.gemspec` | `standardrb` in PATH | `standardrb --fix $FILE` | | **pint** | `.php` | `composer.json` has `laravel/pint` | `./vendor/bin/pint $FILE` | | **ormolu** | `.hs` | `ormolu` in PATH | `ormolu -i $FILE` | | **cljfmt** | `.clj`, `.cljs`, `.cljc`, `.edn` | `cljfmt` in PATH | `cljfmt fix --quiet $FILE` | | **ocamlformat** | `.ml`, `.mli` | `.ocamlformat` file | `ocamlformat -i $FILE` | | **zig** | `.zig`, `.zon` | `zig` in PATH | `zig fmt $FILE` | | **air** | `.R` | `air --help` output | `air format $FILE` | | **latexindent** | `.tex` | `latexindent` in PATH | `latexindent -w -s $FILE` | | **htmlbeautifier** | `.erb` | `htmlbeautifier` in PATH | `htmlbeautifier $FILE` | | **dfmt** | `.d` | `dfmt` in PATH | `dfmt -i $FILE` | | **uv** | `.py`, `.pyi` | `uv` binary (fallback) | `uv format -- $FILE` | ## Configuration ### Disable All Formatting ```json { "formatter": false } ``` ### Disable a Specific Formatter ```json { "formatter": { "prettier": { "disabled": true } } } ``` ### Custom Formatter Configuration ```json { "formatter": { "prettier": { "command": ["npx", "prettier", "--write", "$FILE"], "extensions": [".ts", ".tsx", ".js"], "environment": { "NODE_ENV": "production" } } } } ``` | Field | Type | Description | | ------------- | ---------- | ---------------------------------------------------- | | `command` | `string[]` | Override the formatter command (`$FILE` is replaced) | | `extensions` | `string[]` | Override file extensions | | `environment` | `object` | Extra environment variables | | `disabled` | `boolean` | Disable this formatter | # Governance Most people think of governance as a cost — something you bolt on for compliance. In practice, governance makes agents produce **better results**, not just safer ones. LLMs have built-in randomization. Give them too much freedom and they explore dead ends, burn tokens, and produce inconsistent output. Constrain the solution space and they get to correct results faster, in fewer tokens, with more consistency. Task-scoped permissions aren't just about safety — they're about **focus**. When an Analyst agent knows it can only `SELECT`, it doesn't waste cycles considering whether to `CREATE` a temp table. When it has prescribed, deterministic tools for tracing lineage instead of trying to figure it out from scratch, the results are the same every time. There's an audit angle too. In regulated industries, prescribed tooling eliminates unnecessary audit cycles. When your tools generate SQL the same way every time, auditors can verify consistency. Change the SQL — even if the results are conceptually identical — and you trigger an investigation to prove equivalence. Deterministic tooling removes that overhead entirely. Altimate Code enforces governance at the **harness level**, not via prompt instructions the model can ignore. Four mechanisms work together: ## Rules Project rules via `AGENTS.md` files guide agent behavior — coding conventions, naming standards, warehouse policies, and workflow instructions. Rules are loaded automatically from well-known file patterns and merged into the agent's system prompt. Place them at your project root, in subdirectories for scoped guidance, or host them remotely for organization-wide standards. [Rules reference](https://help.altimate.ai/code/configure/rules/index.md) ## Permissions Every tool has a permission level — `allow`, `ask`, or `deny` — configurable globally or per agent. The Analyst agent can't `INSERT`, `UPDATE`, `DELETE`, or `DROP`. That's not a prompt instruction the model can choose to ignore. It's enforced at the tool level. Pattern-based permissions give you fine-grained control: allow `dbt build *` but deny `rm -rf *`. [Permissions reference](https://help.altimate.ai/code/configure/permissions/index.md) ## Context Management Long sessions produce large conversation histories that can exceed model context windows. Altimate Code automatically prunes old tool outputs, compacts conversations into summaries, and recovers from provider overflow errors — all while preserving critical data engineering context like warehouse connections, schema discoveries, lineage findings, and cost analysis results. [Context Management reference](https://help.altimate.ai/code/configure/context-management/index.md) ## Formatters Every file edit is auto-formatted before it's written. This isn't optional consistency — it's enforced consistency. Altimate Code detects file types and runs the appropriate formatter (prettier, ruff, gofmt, sqlfluff, and 20+ others) automatically. The agent can't produce code that violates your formatting standards. [Formatters reference](https://help.altimate.ai/code/configure/formatters/index.md) ______________________________________________________________________ Together, these four mechanisms mean governance is not an afterthought — it's built into every agent interaction. The harness enforces the rules so your team doesn't have to police the output. # Keybinds altimate supports 85+ customizable keybindings for the TUI. ## Leader Key The leader key (default: `Ctrl+X`) is the prefix for most keybindings. Press the leader key first, then the action key. Override it in your config: ```json { "keybinds": { "leader": "ctrl+space" } } ``` ## Default Keybindings ### Session Management | Keybind | Action | | ------------------ | --------------- | | Leader + `n` | New session | | Leader + `l` | List sessions | | Leader + `Shift+D` | Delete session | | Leader + `Shift+R` | Rename session | | Leader + `Shift+F` | Fork session | | Leader + `Shift+E` | Export session | | Leader + `Shift+C` | Compact session | | Leader + `Shift+S` | Share session | ### Navigation | Keybind | Action | | ----------- | ----------------------------- | | `Page Up` | Scroll messages up one page | | `Page Down` | Scroll messages down one page | | `Home` | Jump to first message | | `End` | Jump to last message | | `Ctrl+Up` | Previous message | | `Ctrl+Down` | Next message | ### Models & Agents | Keybind | Action | | -------------------- | --------------------- | | Leader + `m` | Model list | | Leader + `Shift+M` | Model provider list | | Leader + `a` | Agent list | | Leader + `Tab` | Cycle agent | | Leader + `Shift+Tab` | Cycle agent (reverse) | ### UI Toggles | Keybind | Action | | ------------ | ---------------------------------------------------------------------------------- | | Leader + `s` | Toggle sidebar | | Leader + `t` | Theme list | | Leader + `k` | Keybind list | | Leader + `e` | Open editor | | Leader + `q` | Quit | | `Ctrl+Y` | Toggle YOLO mode for this session (confirms when enabling; instant when disabling) | ### Input Editing | Keybind | Action | | -------------- | --------------------------- | | `Ctrl+A` | Move to beginning of line | | `Ctrl+E` | Move to end of line | | `Ctrl+W` | Delete word backward | | `Ctrl+U` | Delete to beginning of line | | `Ctrl+K` | Delete to end of line | | `Ctrl+Z` | Undo | | `Ctrl+Shift+Z` | Redo | ### Prompt | Keybind | Action | | ------------ | ----------------------------------------------- | | Leader + `i` | Enhance prompt (AI-powered rewrite for clarity) | ### Other | Keybind | Action | | ----------------- | ----------------- | | Leader + `/` | Command list | | Leader + `Ctrl+C` | Interrupt session | | Leader + `d` | Tool details | | `Up` | Previous history | | `Down` | Next history | ## Custom Keybindings Override any keybinding in your config: ```json { "keybinds": { "leader": "ctrl+space", "session_new": "ctrl+n", "sidebar_toggle": "ctrl+b", "theme_list": "ctrl+t" } } ``` Tip Use `/keybinds` or leader + `k` in the TUI to see all current keybindings and their assigned keys. ## Full Keybind Reference All configurable keybind identifiers: ### Session `session_export`, `session_new`, `session_list`, `session_timeline`, `session_fork`, `session_rename`, `session_delete`, `session_child_cycle`, `session_parent`, `session_share`, `session_unshare`, `session_interrupt`, `session_compact`, `session_yolo_toggle` ### Messages `messages_page_up`, `messages_page_down`, `messages_line_up`, `messages_line_down`, `messages_half_page_up`, `messages_half_page_down`, `messages_first`, `messages_last`, `messages_next`, `messages_previous`, `messages_copy`, `messages_undo`, `messages_redo`, `messages_toggle_conceal` ### Input `input_move_left`, `input_move_right`, `input_move_up`, `input_move_down`, `input_undo`, `input_redo` ### UI `leader`, `sidebar_toggle`, `scrollbar_toggle`, `username_toggle`, `theme_list`, `status_view`, `editor_open`, `app_exit` ### Models & Agents `model_list`, `model_cycle_recent`, `model_cycle_favorite`, `model_favorite_toggle`, `model_provider_list`, `variant_cycle`, `variant_list`, `agent_list`, `agent_cycle`, `agent_cycle_reverse` ### Misc `tool_details`, `history_previous`, `history_next`, `command_list`, `terminal_suspend`, `terminal_title_toggle`, `display_thinking`, `tips_toggle` # LSP Servers altimate integrates with Language Server Protocol (LSP) servers for diagnostics, completions, and code intelligence. ## Built-in Servers | Server | Languages | Auto-install | Root Detection | | -------------- | ---------------------------------------------- | ----------------- | -------------------------------------------- | | **TypeScript** | `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs` | Yes | `package-lock.json`, `bun.lock`, `yarn.lock` | | **Deno** | `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs` | Yes | `deno.json`, `deno.jsonc` | | **Vue** | `.vue` | Yes | `package-lock.json`, `bun.lock` | | **ESLint** | `.ts`, `.tsx`, `.js`, `.jsx`, `.vue` | Yes | `package-lock.json`, `bun.lock` | | **Oxlint** | `.ts`, `.js`, `.json`, `.css`, `.html`, `.vue` | Yes | `.oxlintrc.json`, `package.json` | | **Biome** | `.ts`, `.js`, `.json`, `.vue`, `.css`, `.html` | Yes | `biome.json`, `biome.jsonc` | | **Gopls** | `.go` | Yes | `go.mod`, `go.sum` | | **Ruby-LSP** | `.rb`, `.rake`, `.gemspec` | Yes | `Gemfile` | | **Pyright** | `.py`, `.pyi` | Yes | `pyproject.toml`, `setup.py` | | **Ty** | `.py`, `.pyi` | No (experimental) | `pyproject.toml`, `setup.py` | | **Elixir-LS** | `.ex`, `.exs` | Yes | `mix.exs` | | **ZLS** | `.zig`, `.zon` | Yes | `build.zig` | | **C#** | `.cs` | Yes | `.sln`, `.csproj` | | **F#** | `.fs`, `.fsi`, `.fsx` | Yes | `.sln`, `.fsproj` | ## Configuration ### Disable All LSP ```json { "lsp": false } ``` ### Disable a Specific Server ```json { "lsp": { "eslint": { "disabled": true } } } ``` ### Custom Server ```json { "lsp": { "my-lsp": { "command": ["my-language-server", "--stdio"], "extensions": [".myext"], "env": { "MY_LSP_LOG": "debug" }, "initialization": { "customSetting": true } } } } ``` | Field | Type | Description | | ---------------- | ---------- | --------------------------------------------- | | `command` | `string[]` | Command to start the LSP server | | `extensions` | `string[]` | File extensions (required for custom servers) | | `disabled` | `boolean` | Disable this server | | `env` | `object` | Environment variables | | `initialization` | `object` | LSP initialization options | ## Auto-Install LSP servers are automatically downloaded when needed. Disable with: ```bash export ALTIMATE_CLI_DISABLE_LSP_DOWNLOAD=true ``` ## Experimental Servers Enable experimental LSP servers: ```bash export ALTIMATE_CLI_EXPERIMENTAL_LSP_TY=true # Ty (Python) export ALTIMATE_CLI_EXPERIMENTAL_LSP_TOOL=true # LSP as tool ``` # MCP Servers altimate supports the Model Context Protocol (MCP) for connecting to external tool servers. ## Local MCP Servers Run an MCP server as a local subprocess: ```json { "mcp": { "my-tools": { "type": "local", "command": ["npx", "-y", "@my-org/mcp-server"], "environment": { "API_KEY": "{env:MY_API_KEY}" } } } } ``` ### Environment variable interpolation Both syntaxes work anywhere in the config: | Syntax | Injection mode | Example | | ----------------- | -------------------------- | --------------------------------------------------------------------------- | | `${VAR}` | String-safe (JSON-escaped) | `"API_KEY": "${MY_API_KEY}"` — shell / dotenv style | | `${VAR:-default}` | String-safe with fallback | `"MODE": "${APP_MODE:-production}"` — used when `VAR` is unset or empty | | `{env:VAR}` | Raw text | `"count": {env:NUM}` — use for unquoted structural injection | | `$${VAR}` | Escape hatch | `"template": "$${VAR}"` — preserves literal `${VAR}` (docker-compose style) | If the variable is not set and no default is given, it resolves to an empty string. Bare `$VAR` (without braces) is **not** interpolated — use `${VAR}` or `{env:VAR}`. **Why two syntaxes?** `${VAR}` JSON-escapes the value so tokens containing quotes or braces can't break the config structure — the safe default for secrets. `{env:VAR}` does raw text injection for the rare case where you need to inject numbers or structure into unquoted JSON positions. | Field | Type | Description | | ------------- | ---------- | -------------------------------- | | `type` | `"local"` | Local subprocess server | | `command` | `string[]` | Command to start the server | | `environment` | `object` | Environment variables | | `enabled` | `boolean` | Enable/disable (default: `true`) | | `timeout` | `number` | Timeout in ms (default: `5000`) | ## Remote MCP Servers Connect to a remote MCP server over HTTP: ```json { "mcp": { "remote-tools": { "type": "remote", "url": "https://mcp.example.com/sse", "headers": { "Authorization": "Bearer {env:MCP_TOKEN}" } } } } ``` | Field | Type | Description | | ---------------- | ----------------- | ------------------------------------------------------------------ | | `type` | `"remote"` | Remote HTTP server | | `url` | `string` | Server URL | | `headers` | `object` | Static custom HTTP headers | | `headersCommand` | `object` | Headers whose values are produced by running a command (see below) | | `enabled` | `boolean` | Enable/disable (default: `true`) | | `oauth` | `object \| false` | OAuth configuration | | `timeout` | `number` | Timeout in ms (default: `5000`) | ## Dynamic / Bearer-Token Headers (`headersCommand`) For servers gated by short-lived bearer tokens (e.g. **Microsoft Fabric Core MCP**, Azure Entra ID), use `headersCommand` to compute a header value by running a command. Each value is an **argv array** run directly via `execFile` (no shell — values are not subject to shell injection unless you explicitly invoke one like `sh -c`). It is **re-resolved on every connect**, so expiring tokens refresh automatically without editing config: ```json { "mcp": { "fabric": { "type": "remote", "url": "https://api.fabric.microsoft.com/v1/mcp/core", "headersCommand": { "Authorization": ["sh", "-c", "printf 'Bearer %s' \"$(az account get-access-token --resource https://api.fabric.microsoft.com --query accessToken -o tsv)\""] } } } } ``` Values from `headersCommand` override matching keys in `headers` (case-insensitively). When an `Authorization` header is supplied (via `headers` or `headersCommand`) and `oauth` is not explicitly configured, **OAuth auto-detection is disabled** so the static/dynamic bearer token is not overridden by a competing OAuth flow. ## OAuth Authentication For remote servers requiring OAuth: ```json { "mcp": { "protected-server": { "type": "remote", "url": "https://mcp.example.com", "oauth": { "client_id": "my-app", "authorization_url": "https://auth.example.com/authorize", "token_url": "https://auth.example.com/token" } } } } ``` ## CLI Management Manage MCP servers from the command line with `altimate-code mcp`: ```bash # List configured servers and their connection status (alias: ls) altimate-code mcp list # Add a local (stdio) server altimate-code mcp add --name my-tools --type local --command "node ./server.js" \ --env API_KEY=secret # Add a remote (HTTP) server, with an extra header altimate-code mcp add --name remote-tools --type remote \ --url https://example.com/mcp --header "Authorization=Bearer TOKEN" # Authenticate / re-authenticate an OAuth-enabled server altimate-code mcp auth my-tools # Remove stored OAuth credentials for a server altimate-code mcp logout my-tools # Remove a server from the config (alias: rm) altimate-code mcp remove my-tools # Debug an OAuth connection for a server altimate-code mcp debug my-tools ``` `altimate-code mcp add` writes to the project config (`.altimate-code/altimate-code.json`) by default; pass `--global` to write to the global config (`~/.config/altimate-code/`) instead. Use `--type local` with `--command` for stdio servers, or `--type remote` with `--url` for HTTP servers; `--env` and `--header` are repeatable. OAuth is enabled by default (`--oauth`). ## Experimental Settings ```json { "experimental": { "mcp_timeout": 10000 } } ``` # Models altimate supports models from all configured providers. Use the `model` and `small_model` fields to set defaults. ## Configuration ```json { "model": "anthropic/claude-sonnet-4-6", "small_model": "anthropic/claude-haiku-4-5-20251001" } ``` The model format is `provider/model-name`. ## Browsing Models In the TUI: | Action | Method | | ------------------ | ------------------ | | List all models | `/models` command | | Model picker | Leader + `m` | | Filter by provider | Leader + `Shift+M` | ## Model Variants Some providers offer model variants (e.g., different context lengths or capabilities): ```json { "agent": { "analyst": { "model": "anthropic/claude-sonnet-4-6", "variant": "extended-thinking" } } } ``` Cycle through variants in the TUI with the variant cycle keybind. ## Per-Agent Models Set different models for different agents: ```json { "model": "anthropic/claude-sonnet-4-6", "agent": { "analyst": { "model": "anthropic/claude-haiku-4-5-20251001" }, "builder": { "model": "anthropic/claude-opus-4-6" } } } ``` Tip Use a fast, inexpensive model for the `analyst` agent (which runs many read-only queries) and a more capable model for the `builder` agent (which produces code). ## Favorites Mark models as favorites for quick cycling with the TUI keybind (leader + `Shift+F`). ## Model Format Reference Models are referenced as `provider/model-name`: | Provider | Example Model | | ---------------- | ----------------------------------------------- | | Anthropic | `anthropic/claude-sonnet-4-6` | | OpenAI | `openai/gpt-4o` | | Amazon Bedrock | `amazon-bedrock/anthropic.claude-sonnet-4-6-v1` | | Azure | `azure/gpt-4o` | | Google | `google/gemini-2.5-pro` | | Ollama | `ollama/llama3.1` | | OpenRouter | `openrouter/anthropic/claude-sonnet-4-6` | | Copilot | `copilot/gpt-4o` | | Snowflake Cortex | `snowflake-cortex/claude-sonnet-4-6` | | Custom | `my-provider/my-model` | See [Providers](https://help.altimate.ai/code/configure/providers/index.md) for full provider configuration details. # Permissions Permissions control which tools agents can use and what actions they can perform. ## Permission Levels | Level | Behavior | | --------- | -------------------------------- | | `"allow"` | Tool runs without confirmation | | `"ask"` | User is prompted before each use | | `"deny"` | Tool is blocked entirely | ## Global Permissions Set in `altimate-code.json`: ```json { "permission": { "read": "allow", "glob": "allow", "grep": "allow", "list": "allow", "edit": "ask", "write": "ask", "bash": "ask", "webfetch": "ask", "websearch": "ask" } } ``` ## Pattern-Based Permissions For tools that accept arguments (like `bash`), use pattern matching: ```json { "permission": { "bash": { "*": "ask", "dbt *": "allow", "git status": "allow", "git diff *": "allow", "rm *": "deny", "DROP *": "deny" } } } ``` Patterns are matched in order, and the **last matching rule wins**. Use `*` as a wildcard. Place your catch-all `"*"` rule first and more specific rules after it. For example, with `"*": "ask"` first and `"rm *": "deny"` after it, all `rm` commands are denied while everything else prompts. If you put `"*": "ask"` last, it would override the deny rule. ## Per-Agent Permissions Override permissions for specific agents: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "bash": { "SELECT *": "allow", "dbt docs *": "allow", "*": "deny" } } } } } ``` ## All Permissioned Tools | Tool | Supports Patterns | Description | | -------------------- | ----------------- | --------------------------------------------------- | | `read` | Yes | Read files | | `edit` | Yes | Edit files | | `write` | Yes | Write files | | `glob` | Yes | Find files | | `grep` | Yes | Search files | | `list` | Yes | List directories | | `bash` | Yes | Shell commands | | `sql_execute_write` | Yes | SQL write operations (INSERT, UPDATE, DELETE, etc.) | | `task` | Yes | Spawn subagents | | `lsp` | Yes | LSP operations | | `skill` | Yes | Execute skills | | `external_directory` | Yes | Access outside project | | `webfetch` | No | Fetch web pages | | `websearch` | No | Web search | | `codesearch` | No | Code search | | `question` | No | Ask user questions | | `todowrite` | No | Write tasks | | `todoread` | No | Read tasks | | `doom_loop` | No | Loop detection | ## Environment Variable Set permissions via environment variable: ```bash export ALTIMATE_CLI_PERMISSION='{"bash":"deny","write":"deny"}' altimate ``` ## Yolo Mode Auto-approve all permission prompts without asking. Useful for CI/CD pipelines, benchmarks, scripted workflows, and trusted environments. **CLI flag (works with any subcommand):** ```bash altimate-code --yolo run "build all dbt models" altimate-code --yolo # launches TUI in yolo mode ``` **Environment variable:** ```bash export ALTIMATE_CLI_YOLO=true altimate-code run "analyze my queries" ``` The fallback `OPENCODE_YOLO` env var is also supported. When both are set, `ALTIMATE_CLI_YOLO` takes precedence. Setting it to `false` disables yolo even if `OPENCODE_YOLO=true`. **Safety:** Explicit `deny` rules in your config are still enforced. Deny rules throw an error *before* any permission prompt is created, so yolo mode never sees them. If you've denied `rm *` or `DROP *`, those remain blocked even with `--yolo`. When yolo mode is active in the TUI, a `△ YOLO` indicator appears in the footer status bar. ## Recommended Configurations ### Data Engineering (Default, Balanced) A good starting point for most data engineering workflows. Allows safe read operations, prompts for writes and commands: ```json { "permission": { "read": "allow", "glob": "allow", "grep": "allow", "list": "allow", "edit": "ask", "write": "ask", "bash": { "*": "ask", "dbt *": "allow", "git status": "allow", "git diff *": "allow", "git log *": "allow", "ls *": "allow", "cat *": "allow", "rm *": "deny", "DROP *": "deny", "DELETE *": "deny", "TRUNCATE *": "deny" }, "external_directory": "ask" } } ``` ### Strict (Production-Adjacent Work) When working near production systems. Blocks destructive operations entirely and requires confirmation for everything else: ```json { "permission": { "read": "allow", "glob": "allow", "grep": "allow", "list": "allow", "edit": "ask", "write": "ask", "bash": { "*": "ask", "dbt *": "ask", "git status": "allow", "rm *": "deny", "DROP *": "deny", "DELETE *": "deny", "TRUNCATE *": "deny", "ALTER *": "deny", "git push *": "deny", "git reset *": "deny" }, "external_directory": "deny" } } ``` ### Per-Agent Lockdown Give each agent only the permissions it needs: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "sql_execute_write": "deny", "bash": { "*": "deny", "ls *": "allow", "cat *": "allow", "dbt list *": "allow" } } }, "builder": { "permission": { "sql_execute_write": "ask", "bash": { "*": "ask", "dbt *": "allow", "rm -rf *": "deny" } } } } } ``` ## How Permissions Work When the agent wants to use a tool, the permission system evaluates your rules in order: 1. **Config rules** from `altimate-code.json` 1. **Agent-level rules** for per-agent overrides 1. **Session approvals** for patterns you've approved with "Allow always" during the current session If a rule matches, it applies. If no rule matches, the default is `"ask"`, which means you'll be prompted. When prompted, you have three choices: | Choice | Effect | | ---------------- | ---------------------------------------------------------- | | **Allow once** | Approves this single action | | **Allow always** | Approves this pattern for the rest of the session | | **Reject** | Blocks the action (optionally with feedback for the agent) | "Allow always" approvals persist for your current session only. They reset when you restart Altimate Code. ## Tips - **Start with `"ask"` and relax as you build confidence.** You can always approve patterns with "Allow always" during a session. - **Use `"deny"` for truly dangerous commands** like `rm *`, `DROP *`, `git push --force *`, and `git reset --hard *`. These are blocked even if other rules would allow them. - **Use per-agent permissions** to enforce least-privilege. An analyst doesn't need write access. A builder doesn't need `DROP`. - **Review the prompt before approving.** The TUI shows you exactly what will run, including diffs for file edits and the full command for bash operations. # Providers altimate supports 35+ LLM providers. Configure them in the `provider` section of your config file. ## Provider Configuration Each provider has a key in the `provider` object: ```json { "provider": { "": { "apiKey": "{env:API_KEY}", "baseURL": "https://custom.endpoint.com/v1", "headers": { "X-Custom-Header": "value" } } } } ``` Tip Use `{env:...}` substitution for API keys so you never commit secrets to version control. ## Altimate LLM Gateway Managed LLM access with dynamic routing across Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, and more. No API keys to manage — 10M tokens free to get started. ```json { "provider": { "altimate": {} }, "model": "altimate/auto" } ``` For pricing, security, and data handling details, see the [Altimate LLM Gateway guide](/datamates/user-guide/components/llm-gateway/). Automatic model selection When Altimate credentials are configured and no model is explicitly chosen, the Altimate LLM Gateway is selected automatically. You can override this by setting `model` in your config or by restricting the `provider` section to specific providers only. ## Altimate Base Altimate Base is Altimate's own hosted free model. It requires no signup or user-managed API key and is subject to rate limits and abuse protection. **Data handling:** Requests and responses are logged and may be used to improve Altimate's products, including the model. Secrets are automatically masked before storage, but don't rely on it — avoid sending secrets or confidential code. Altimate Base is pseudonymous, not anonymous: a stable per-installation identifier links your requests across launches and `altimate providers logout altimate-base` does not reset it (see the [security FAQ](https://help.altimate.ai/code/reference/security-faq/index.md)). Usage is rate limited. If you need stronger guarantees — no training on your data, metadata-only retention — use the [Altimate LLM Gateway](/datamates/user-guide/components/llm-gateway/) instead. Choose **Altimate Base** from the first-run picker or `/connect`. A disclosure is shown before any registration request; **No** is selected by default. After registration, the model is available as `altimate-free/altimate-base` and becomes the free fallback when no paid Altimate Gateway or explicit model is selected. Big Pickle is retired as a new selection — it no longer appears in the picker or the full model catalog for users choosing a model for the first time. Users already on Big Pickle are still detected on launch and offered Altimate Base through the same consent gate. If you decline the default switch, `declinedManagedBaseDefault: true` in the state directory's `model.json` keeps public Zen ahead of registered Base for headless and ACP defaults, with Base used only as a last resort; accepting migration or explicitly selecting Base clears the flag. Registration is per machine, not per host. Once any host on a machine has registered Altimate Base (the TUI's consent gate, or the HTTP registration route used by IDE integrations), every other host on that machine treats Base as the default free model without showing its own prompt: the TUI migrates an implicit free default silently, and headless `altimate run`, `altimate serve`, and ACP sessions resolve to Base ahead of the keyless public Zen tier. The disclosure is therefore shown once per machine, by whichever host registers. Declining as described above applies to all hosts on the machine too. Administrators auditing a fleet can check `model.json` for `declinedManagedBaseDefault` and the registered `altimate-free` provider entry in `auth.json`. Official release binaries embed the current gateway endpoint at build time. Operators and local development can override it without changing code: ```bash export ALTIMATE_BASE_GATEWAY_URL=https://your-gateway.example altimate ``` The URL must use HTTPS. Credentials, query strings, and fragments in the URL are rejected. `ALTIMATE_FREE_GATEWAY_URL` is retained as a legacy fallback, but `ALTIMATE_BASE_GATEWAY_URL` takes precedence. If the configured gateway host changes, credentials issued by the previous host are not loaded and the consented registration flow must run again. Altimate Base waits up to **5 minutes** for the gateway to send response headers, because the backend can queue, cold-start, or reason before the first token arrives (a shorter wait would abort healthy requests with `Provider response headers timed out`). Override this in the field with `ALTIMATE_BASE_HEADER_TIMEOUT_MS` — a whole number of milliseconds, minimum `1000`; values below the floor or non-numeric values are ignored and fall back to the default: ```bash export ALTIMATE_BASE_HEADER_TIMEOUT_MS=600000 # wait up to 10 minutes for the first byte ``` This bounds only the wait for the first response byte; once the stream starts, a separate 5-minute watchdog guards against mid-stream stalls. Altimate Base credentials are stored separately from the shared provider-auth file and are never returned to the TUI. The installation secret is hashed before registration; the gateway receives the hash, not the local secret. That hash is stable across launches, so it links this installation's logged requests together — it is what enforces the free allowance. Running `altimate providers logout altimate-base` clears the credential but keeps the installation identity on purpose, so logging out is not a way to reset the allowance. Each inference request additionally carries a session identifier used for rate limiting. See the security FAQ for what this means for privacy and how to reset the local identity. ## Anthropic ```json { "provider": { "anthropic": { "apiKey": "{env:ANTHROPIC_API_KEY}" } }, "model": "anthropic/claude-sonnet-4-6" } ``` Available models: `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001` ## OpenAI ```json { "provider": { "openai": { "apiKey": "{env:OPENAI_API_KEY}" } }, "model": "openai/gpt-4o" } ``` ## Amazon Bedrock ```json { "provider": { "amazon-bedrock": { "options": { "region": "us-east-1" } } }, "model": "amazon-bedrock/anthropic.claude-sonnet-4-6-v1" } ``` Uses the standard AWS credential chain: environment variables (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`), named profiles (`AWS_PROFILE`), SSO sessions, IAM roles, and container credentials. Note If you have AWS SSO, IAM roles, or environment credentials (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`) configured, Bedrock will use your default credential chain automatically. ### Custom Endpoints (API Gateways) If your organization routes Bedrock traffic through a custom API gateway or proxy, set the `baseURL` in the provider options: ```json { "provider": { "amazon-bedrock": { "options": { "baseURL": "https://your-gateway.example.com/v1", "region": "us-east-1" } } }, "model": "amazon-bedrock/anthropic.claude-sonnet-4-6-v1" } ``` For a complete walkthrough — including bearer token authentication, cross-region model IDs, and troubleshooting — see the [Amazon Bedrock Custom Endpoints guide](https://help.altimate.ai/code/configure/bedrock-custom-endpoints/index.md). ## Azure OpenAI ```json { "provider": { "azure": { "apiKey": "{env:AZURE_OPENAI_API_KEY}", "baseURL": "https://your-resource.openai.azure.com/openai/deployments/your-deployment" } }, "model": "azure/gpt-4o" } ``` ## Google (Gemini) ```json { "provider": { "google": { "apiKey": "{env:GOOGLE_API_KEY}" } }, "model": "google/gemini-2.5-pro" } ``` ## Google Vertex AI ```json { "provider": { "google-vertex": { "project": "my-gcp-project", "location": "us-central1" } }, "model": "google-vertex/gemini-2.5-pro" } ``` Uses Google Cloud Application Default Credentials. Authenticate with: ```bash gcloud auth application-default login ``` The `project` and `location` fields can also be set via environment variables: | Field | Environment Variables (checked in order) | | ---------- | -------------------------------------------------------------------- | | `project` | `GOOGLE_CLOUD_PROJECT`, `GCP_PROJECT`, `GCLOUD_PROJECT` | | `location` | `GOOGLE_VERTEX_LOCATION`, `GOOGLE_CLOUD_LOCATION`, `VERTEX_LOCATION` | If `location` is not set, it defaults to `us-central1`. Tip You can also access Anthropic models through Vertex AI using the `google-vertex` provider (e.g., `google-vertex/claude-sonnet-4-6`). ## Ollama (Local) ```json { "provider": { "ollama": { "baseURL": "http://localhost:11434" } }, "model": "ollama/llama3.1" } ``` No API key needed. Runs entirely on your local machine. Info Make sure Ollama is running before starting altimate. Install it from [ollama.com](https://ollama.com) and pull your desired model with `ollama pull llama3.1`. ## LM Studio (Local) Run local models through [LM Studio](https://lmstudio.ai)'s OpenAI-compatible server: ```json { "provider": { "lmstudio": { "name": "LM Studio", "npm": "@ai-sdk/openai-compatible", "env": ["LMSTUDIO_API_KEY"], "options": { "apiKey": "lm-studio", "baseURL": "http://localhost:1234/v1" }, "models": { "qwen2.5-7b-instruct": { "name": "Qwen 2.5 7B Instruct", "tool_call": true, "limit": { "context": 131072, "output": 8192 } } } } }, "model": "lmstudio/qwen2.5-7b-instruct" } ``` **Setup:** 1. Open LM Studio → **Developer** tab → **Start Server** (default port: 1234) 1. Load a model in LM Studio 1. Find your model ID: `curl http://localhost:1234/v1/models` 1. Add the model ID to the `models` section in your config 1. Use it: `altimate-code run -m lmstudio/` Tip The model key in your config must match the model ID returned by LM Studio's `/v1/models` endpoint. If you change models in LM Studio, update the config to match. Note If you changed LM Studio's default port, update the `baseURL` accordingly. No real API key is needed — the `"lm-studio"` placeholder satisfies the SDK requirement. ## OpenRouter ```json { "provider": { "openrouter": { "apiKey": "{env:OPENROUTER_API_KEY}" } }, "model": "openrouter/anthropic/claude-sonnet-4-6" } ``` Access 150+ models through a single API key. ## Copilot ```json { "provider": { "copilot": {} }, "model": "copilot/gpt-4o" } ``` Uses your GitHub Copilot subscription. Authenticate with `altimate auth`. Codespaces & GitHub Actions In GitHub Codespaces and GitHub Actions, the machine-scoped `GITHUB_TOKEN` lacks `models:read` permission and cannot be used for GitHub Copilot or GitHub Models inference. altimate automatically skips these providers in machine environments. To use them, authenticate explicitly with `altimate auth` or set a personal access token with `models:read` scope as a Codespace secret. ## Snowflake Cortex ```json { "provider": { "snowflake-cortex": {} }, "model": "snowflake-cortex/claude-sonnet-4-6" } ``` Authenticate with `altimate auth snowflake-cortex` using a Programmatic Access Token (PAT). Enter credentials as `account-identifier::pat-token`. Create a PAT in Snowsight: **Admin > Security > Programmatic Access Tokens**. Billing flows through your Snowflake credits — no per-token costs. Prompt caching is applied automatically for Claude models: cache markers are placed on the system prompt and trailing messages, so repeated context in long sessions is billed at Snowflake's reduced cached-input rate (5-minute TTL; exact cache-read and cache-write rates vary by model — see Snowflake's Cortex pricing). Savings are workload-dependent: long agent sessions with large stable prefixes benefit most, while very short sessions may see little change — monitor `cache_read_input`/`cache_write_input` in Snowflake's `CORTEX_FUNCTIONS_QUERY_USAGE_HISTORY`/`TOKENS_GRANULAR` telemetry after upgrading (these columns were previously always NULL for altimate-code workloads and now populate). OpenAI models are cached automatically by Cortex itself; other model families don't support caching. **Available models** (catalog verified live against Cortex on 2026-07-20): | Model | Tool Calling | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | | `claude-sonnet-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-opus-4-6`, `claude-sonnet-4-5`, `claude-opus-4-5`, `claude-haiku-4-5`, `claude-4-sonnet` | Yes | | `openai-gpt-4.1`, `openai-gpt-5`, `openai-gpt-5.1`, `openai-gpt-5.2`, `openai-gpt-5.4`, `openai-gpt-5.4-mini`, `openai-gpt-5.4-nano`, `openai-gpt-5-mini`, `openai-gpt-5-nano` | Yes | | `llama4-maverick`, `llama3.3-70b`, `llama3.1-70b`, `llama3.1-8b` | No | | `mistral-large2`, `mistral-7b` | No | Snowflake deprecated `deepseek-r1`, `mistral-large`, `llama3.1-405b`, and `snowflake-llama-3.3-70b` on July 8, 2026, and has delisted `claude-3-7-sonnet`, `claude-3-5-sonnet`, `openai-gpt-5-chat`, `llama4-scout`, `mixtral-8x7b`, and `gemini-3.1-pro` — requests to these now fail. Note Model availability depends on your Snowflake region. Enable cross-region inference with `ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'ANY_REGION'` for full model access. ### Adding a model not in the list Snowflake Cortex adds models faster than this list can be updated. If a model is available on your Cortex account but not yet listed above, you can register it locally without forking the CLI — add it under `provider["snowflake-cortex"].models` in your `altimate-code.json` (or `.altimate-code/altimate-code.json`): ```json { "provider": { "snowflake-cortex": { "models": { "your-new-model-id": { "name": "Your New Model", "limit": { "context": 200000, "output": 32000 }, "tool_call": true } } } } } ``` The entry merges with the built-in list, so the model appears in the picker and can be selected as `snowflake-cortex/your-new-model-id`. Set `"tool_call": false` for models that don't support tools on Cortex (Llama and Mistral today) — otherwise requests with tools will fail. The `tool_call` field uses snake_case (matching the rest of the `altimate-code.json` schema) and maps to the picker's `capabilities.toolcall`. The request transform reads the same value, so a user-added model marked `tool_call: true` keeps `tools` and `tool_choice` in outgoing requests — and one marked `tool_call: false` has them stripped, the same as the built-in non-tool entries. ## Databricks AI Gateway Connect to Databricks serving endpoints (Foundation Model APIs) via your workspace PAT. Use Databricks-hosted Llama, Claude, GPT, Gemini, DBRX, or Mixtral for agent reasoning — billing flows through your Databricks account. ```json { "provider": { "databricks": {} }, "model": "databricks/databricks-claude-sonnet-4-6" } ``` Authenticate with `altimate auth databricks` and enter credentials as `workspace-host::pat-token`: ```text myworkspace.cloud.databricks.com::dapi1234567890abcdef ``` Or set environment variables: ```bash export DATABRICKS_HOST=myworkspace.cloud.databricks.com export DATABRICKS_TOKEN=dapi1234567890abcdef ``` Create a PAT in Databricks: **Settings → Developer → Access Tokens → Generate New Token**. **Supported workspace domains:** `*.cloud.databricks.com` (AWS), `*.azuredatabricks.net` (Azure), `*.gcp.databricks.com` (GCP). **Available models:** | Provider | Models | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | Meta Llama | `databricks-meta-llama-3-1-405b-instruct`, `databricks-meta-llama-3-1-70b-instruct`, `databricks-meta-llama-3-1-8b-instruct` | | Anthropic via Databricks | `databricks-claude-sonnet-4-6`, `databricks-claude-opus-4-6` | | OpenAI via Databricks | `databricks-gpt-5-4`, `databricks-gpt-5-mini` | | Google via Databricks | `databricks-gemini-3-1-pro` | | Databricks native | `databricks-dbrx-instruct` | | Mistral (tool calls unsupported) | `databricks-mixtral-8x7b-instruct` | Note Databricks bills directly for these models — altimate-code reports `$0` cost for Databricks-routed requests since pricing depends on your Databricks contract. ## Custom / OpenAI-Compatible Any OpenAI-compatible endpoint can be used as a provider: ```json { "provider": { "my-provider": { "api": "openai", "baseURL": "https://my-llm-proxy.example.com/v1", "apiKey": "{env:MY_API_KEY}" } }, "model": "my-provider/my-model" } ``` Tip This works with any service that exposes an OpenAI-compatible chat completions API, including vLLM, LiteLLM, and self-hosted inference servers. ## Model Selection Set your default model and a smaller model for lightweight tasks: ```json { "model": "anthropic/claude-sonnet-4-6", "small_model": "anthropic/claude-haiku-4-5-20251001" } ``` The `small_model` is used for lightweight tasks like summarization and context compaction. ## Provider Options Reference | Field | Type | Description | | ----------------- | -------- | ------------------------------------------------------------------- | | `apiKey` | `string` | API key (supports `{env:...}` and `{file:...}`) | | `baseURL` | `string` | Custom API endpoint URL | | `api` | `string` | API type (e.g., `"openai"` for compatible endpoints) | | `headers` | `object` | Custom HTTP headers to include with requests | | `options.region` | `string` | AWS region (Amazon Bedrock only, default: `us-east-1`) | | `options.profile` | `string` | AWS named profile (Amazon Bedrock only) | | `options.baseURL` | `string` | Custom endpoint URL for Bedrock gateway/proxy (Amazon Bedrock only) | | `project` | `string` | GCP project ID (Google Vertex AI only) | | `location` | `string` | GCP region (Google Vertex AI only, default: `us-central1`) | # Rules Rules are instructions that guide agent behavior. They are loaded automatically from well-known file patterns and merged into the agent's system prompt. ## Instruction Files altimate looks for instruction files in these locations: - `AGENTS.md`: Primary instruction file (searched up directory tree) - `CLAUDE.md`: Fallback instruction file - `.altimate-code/AGENTS.md`: Project-specific instructions - Custom patterns via the `instructions` config field Tip Start with a single `AGENTS.md` in your project root. Add more instruction files as your project grows. ### Config-based Instructions Specify additional instruction sources in your config: ```json { "instructions": [ "AGENTS.md", ".altimate-code/**/*.md", "docs/ai-guidelines.md", "https://example.com/team-guidelines.md" ] } ``` Patterns support: - **Glob patterns** such as `*.md`, `docs/**/*.md` - **URLs**, which are fetched at startup - **Relative paths**, which are resolved from project root ## Writing Effective Rules A good `AGENTS.md` file provides project context, coding conventions, and workflow guidance: ```markdown # AGENTS.md ## Project Context This is a dbt project for our analytics warehouse on Snowflake. ## Conventions - Always use `ref()` instead of hardcoded table names - Follow our naming convention: `stg_`, `int_`, `fct_`, `dim_` - Run `dbt build --select state:modified+` to test changes ## Warehouse Rules - Never run DDL on production - Always use the ANALYST_ROLE for queries - Prefer incremental models over full refreshes ``` Tips for effective rules - Be specific and actionable, since vague rules get ignored - Include project-specific terminology and conventions - Reference file paths and commands that agents should use - Keep rules concise; overly long instructions dilute focus ## Instruction Scope Instructions apply based on file location: | Location | Scope | | ------------------------------------------ | ----------------------------------- | | Project root `AGENTS.md` | All agents in project | | `.altimate-code/AGENTS.md` | Project-specific | | Subdirectory `AGENTS.md` | Active when working in that subtree | | Global `~/.config/altimate-code/AGENTS.md` | All projects | Note When multiple instruction files match, they are merged together. More specific files (deeper in the directory tree) take precedence for conflicting guidance. ## Remote Instructions Organizations can host shared instructions at a well-known URL: ```text https://your-domain.com/.well-known/altimate-code ``` These are loaded as the lowest-priority configuration source, allowing individual projects and users to override them. ## Instruction Format Instruction files are plain Markdown. Use headings and lists to organize your rules clearly: ```markdown # Project: Analytics Pipeline ## Stack - Warehouse: Snowflake - Orchestrator: Airflow - Transform: dbt 1.8 ## SQL Style - Use CTEs instead of subqueries - Alias all columns in SELECT - One join condition per line ## Testing - Every model must have a `unique` test on its primary key - Use `dbt_expectations` for data quality checks ``` # Agent Skills Skills are reusable prompt templates that extend agent capabilities. ## Skill Format Skills are markdown files named `SKILL.md`: ```markdown --- name: cost-review description: "Review SQL queries for cost optimization" --- Analyze the SQL query for cost optimization opportunities: 1. Check for full table scans 2. Evaluate partition pruning 3. Suggest clustering keys 4. Estimate credit impact 5. Recommend cheaper alternatives Focus on the query: $ARGUMENTS ``` ### Frontmatter Fields | Field | Required | Description | | ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | Yes | Skill name | | `description` | Yes | Short description shown in the agent's `` listing | | `alwaysApply` | No | When `true`, the skill's full body is inlined into the system prompt at session start — the agent does not need to invoke the `Skill` tool to see it. See [Auto-loading skills](#auto-loading-skills). | | `applyPaths` | No | A glob (string) or list of globs. When at least one file under the worktree matches, the skill's full body is inlined into the system prompt at session start. Useful for project-aware skills (e.g. `dbt_project.yml` for dbt projects). | ## Auto-loading skills By default, skills are **lazy-loaded**: only the `name` and `description` appear in the system prompt, and the full body is fetched only when the model invokes the `Skill` tool. This keeps the prompt small but relies on the model choosing to load the skill at the right moment. For skills that should always be in context for a given kind of project (e.g. "every dbt session should see the dbt-development pitfalls"), declare one of: ```yaml --- name: dbt-develop applyPaths: - "dbt_project.yml" # matches if any dbt_project.yml exists in the worktree - "**/dbt_project.yml" description: "..." --- ``` or, for unconditional loading: ```yaml --- name: house-rules alwaysApply: true description: "..." --- ``` At session start, every matched skill body is prepended to the system prompt (BEFORE the standard `` listing — placement matters: putting the auto-loaded block first frames the bodies as binding "rules of the road" rather than background reference) under: ```xml ... full skill body ... ``` The agent is told it does not need to invoke the `Skill` tool again to access these — they are binding guidance for the session. ### When to use | Pattern | Mode | | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | Project-type-specific guidance (dbt project, Snowflake project, BigQuery project) | `applyPaths` with the project marker file | | Team conventions that apply to every session in a repo | `alwaysApply: true` in a project-level `.opencode/skills//SKILL.md` | | Skill that's only relevant when the user asks for it explicitly (e.g. test generation, cost review) | Leave both fields unset — keep lazy loading | ### Context-size implications When a skill auto-loads, its full body lands in the system prompt. A 250-line skill (~5K tokens) bumps the system prompt by roughly 25%. Two mitigators: 1. **Prompt caching amortizes the cost** — the system prompt is the most-cached part of the request. Across a long agent loop (~26 steps per task is typical) the auto-loaded body is read from cache, not re-billed as fresh input. 1. **Match the glob narrowly** — `applyPaths: "dbt_project.yml"` only fires inside dbt projects; non-dbt sessions are unaffected. The mechanism is opt-in per skill and per worktree. If you find auto-loaded bodies are crowding out task-specific context, prefer `applyPaths` over `alwaysApply` so the skill only loads when the project markers indicate it's relevant. ## Discovery Paths Skills are loaded from these locations (in priority order): 1. **Project directories** (project-scoped, highest priority): - `.opencode/skills/` - `.altimate-code/skill/` - `.altimate-code/skills/` 1. **Global user directories**: - `~/.altimate-code/skills/` 1. **Custom paths** (from config): ```json { "skills": { "paths": ["./my-skills", "~/shared-skills"] } } ``` 1. **External directories & remote URLs** (if not disabled): - `~/.claude/skills/` - `~/.agents/skills/` - `.claude/skills/` (project, searched up tree) - `.agents/skills/` (project, searched up tree) ```json { "skills": { "urls": ["https://example.com/skills-registry.json"] } } ``` ## Built-in Data Engineering Skills altimate ships with built-in skills for common data engineering tasks. Type `/` in the TUI to browse what's available and get autocomplete on skill names. | Skill | Description | | ------------------- | --------------------------------------------------------------------------------- | | `/sql-review` | SQL quality gate that lints 26 anti-patterns, validates syntax, and checks safety | | `/sql-translate` | Cross-dialect SQL translation | | `/schema-migration` | Schema migration planning and execution | | `/pii-audit` | PII detection and compliance audits | | `/cost-report` | Snowflake FinOps analysis | | `/lineage-diff` | Column-level lineage comparison | | `/query-optimize` | Query optimization suggestions | | `/data-viz` | Interactive data visualization and dashboards | | `/dbt-develop` | dbt model development and scaffolding | | `/dbt-test` | dbt schema test generation | | `/dbt-unit-tests` | Automated dbt unit test generation (v1.8+) | | `/dbt-docs` | dbt documentation generation | | `/dbt-analyze` | dbt project analysis | | `/dbt-troubleshoot` | dbt issue diagnosis | | `/teach` | Teach patterns from example files | | `/train` | Learn standards from documents/style guides | | `/training-status` | Dashboard of all learned knowledge | ## CLI Commands Manage skills from the command line: ```bash # Browse skills altimate-code skill list # table view altimate-code skill list --json # JSON (for scripting) altimate-code skill show dbt-develop # view full skill content # Create altimate-code skill create my-tool # scaffold skill + bash tool altimate-code skill create my-tool --language python # python tool stub altimate-code skill create my-tool --language node # node tool stub altimate-code skill create my-tool --skill-only # skill only, no CLI tool # Validate altimate-code skill test my-tool # check frontmatter + tool --help # Install from GitHub altimate-code skill install owner/repo # GitHub shorthand altimate-code skill install https://github.com/... # full URL (web URLs work too) altimate-code skill install ./local-path # local directory altimate-code skill install owner/repo --global # install globally # Remove altimate-code skill remove my-tool # remove skill + paired tool ``` ### TUI Open the skill browser with `ctrl+i` when no other dialog is open, or type `/skills` in the prompt: **Keyboard shortcuts:** | Key | Action | | -------- | --------------------------------------------------------------------------------- | | `ctrl+i` | Open skill browser (when no dialog is open) / Install skill (when inside browser) | | Enter | Use — inserts `/` into the prompt | | `ctrl+a` | Actions — show, edit, test, or remove the selected skill | | `ctrl+n` | New — scaffold a new skill + CLI tool | | Esc | Back — returns to previous screen | **Create skill** (`ctrl+n`): **Install skill** (`ctrl+i` inside browser): ## Adding Custom Skills The fastest way to create a custom skill is with the scaffolder: ```bash altimate-code skill create freshness-check ``` This creates two files: - `.opencode/skills/freshness-check/SKILL.md` — teaches the agent when and how to use your tool - `.opencode/tools/freshness-check` — executable CLI tool stub ### Pairing Skills with CLI Tools Skills become powerful when paired with CLI tools. Drop any executable into `.opencode/tools/` and it's automatically available on the agent's PATH: ```text .opencode/tools/ # Project-level tools (auto-discovered) ~/.config/altimate-code/tools/ # Global tools (shared across projects) ``` A skill references its paired CLI tool through bash code blocks: ```markdown --- name: freshness-check description: "Check data freshness across tables" --- # Freshness Check ## CLI Reference \`\`\`bash freshness-check --table users --threshold 24h freshness-check --all --report \`\`\` ## Workflow 1. Ask the user which tables to check 2. Run `freshness-check` with appropriate flags 3. Interpret the output and suggest fixes ``` The tool can be written in any language (bash, Python, Node.js, etc.) — as long as it's executable. ### Skill-Only (No CLI Tool) You can also create skills as plain prompt templates: ```markdown --- name: cost-review description: "Review SQL queries for cost optimization" --- Analyze the SQL query for cost optimization opportunities. Focus on: $ARGUMENTS ``` `$ARGUMENTS` is replaced with whatever the user types after the skill name (e.g., `/cost-review SELECT * FROM orders` passes `SELECT * FROM orders`). ### Skill Paths Skills are loaded from these paths (highest priority first): 1. `.opencode/skills/` and `.altimate-code/skill/` (project) 1. `~/.altimate-code/skills/` (global) 1. Custom paths via config: ```json { "skills": { "paths": ["./my-skills", "~/shared-skills"] } } ``` ### Remote Skills Host skills at a URL and load them at startup: ```json { "skills": { "urls": ["https://example.com/skills-registry.json"] } } ``` ## Disabling External Skills ```bash export ALTIMATE_CLI_DISABLE_EXTERNAL_SKILLS=true ``` This disables skill discovery from `~/.claude/skills/` and `~/.agents/skills/` but keeps `.altimate-code/skill/` discovery active. ## Duplicate Handling If multiple skills share the same name, project-level skills override global skills. A warning is logged when duplicates are found. # Themes altimate includes 12+ built-in themes and supports custom themes. ## Switching Themes - **TUI**: Press leader + `t` or use `/theme` - **Config**: Set `"theme": "catppuccin"` in your config file ```json { "theme": "catppuccin" } ``` ## Built-in Themes | Theme | Description | | ----------------- | ---------------------------------- | | `catppuccin` | Pastel colors on a dark background | | `dracula` | Dark theme with vibrant colors | | `gruvbox` | Retro groove colors | | `monokai` | Classic dark theme | | `nord` | Arctic-inspired colors | | `one-dark` | Atom-inspired dark theme | | `solarized-dark` | Solarized dark variant | | `solarized-light` | Solarized light variant | | `tokyo-night` | Tokyo Night color scheme | | `rose-pine` | Soho vibes | | `kanagawa` | Inspired by Katsushika Hokusai | ## Custom Themes Create a custom theme JSON file and reference it by name: ```json { "theme": "my-theme" } ``` Custom themes define colors for UI elements including: - Primary, secondary, and accent colors - Background and foreground - Success, warning, and error states - Diff added/removed highlights - Agent colors ### Theme File Location Place custom themes in one of these directories: | Location | Scope | | --------------------------------- | ------------------------- | | `~/.config/altimate-code/themes/` | Available in all projects | | `.altimate-code/themes/` | Project-specific | Tip Name your theme file `my-theme.json` and set `"theme": "my-theme"` in your config. altimate will find it automatically in the theme directories. # Tools altimate includes built-in tools that agents use to interact with your codebase and environment. ## Built-in Tools | Tool | Description | | ------------ | ----------------------------------------------------- | | `bash` | Execute shell commands | | `read` | Read file contents | | `edit` | Edit files with find-and-replace | | `write` | Create or overwrite files | | `glob` | Find files by pattern | | `grep` | Search file contents with regex | | `list` | List directory contents | | `patch` | Apply multi-file patches | | `lsp` | Language server operations (diagnostics, completions) | | `webfetch` | Fetch and process web pages | | `websearch` | Search the web | | `question` | Ask the user a question | | `todo_read` | Read task list | | `todo_write` | Create/update tasks | | `skill` | Execute a skill | ## Data Engineering Tools In addition to built-in tools, altimate provides 100+ specialized data engineering tools. See the [Data Engineering Tools](https://help.altimate.ai/code/data-engineering/tools/index.md) section for details. ## Tool Permissions Control which tools agents can use via the [permission system](https://help.altimate.ai/code/configure/permissions/index.md): ```json { "permission": { "bash": { "dbt *": "allow", "rm *": "deny", "*": "ask" }, "write": "ask", "read": "allow" } } ``` Info Permission values can be `"allow"`, `"deny"`, or `"ask"`. The `"ask"` permission prompts the user for confirmation before executing. ## Disabling Tools Disable a tool for a specific agent by setting its permission to `"deny"`: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "bash": { "dbt run *": "deny", "*": "ask" } } } } } ``` Read-only analyst The configuration above creates an analyst agent that cannot modify files. It can only read and explore the codebase, and must ask before running shell commands (except `dbt run`, which is blocked entirely). ## Tool Behavior ### Bash Tool The `bash` tool executes shell commands in the project directory. Commands run in a non-interactive shell with the user's environment. ```json { "permission": { "bash": { "dbt *": "allow", "git *": "allow", "python *": "allow", "rm -rf *": "deny", "*": "ask" } } } ``` Warning Bash permissions use glob-style pattern matching. Be specific with `"deny"` rules to prevent destructive commands while allowing productive ones. ### Read / Write / Edit Tools File tools respect the project boundaries and permission settings: - **`read`** reads file contents and supports line ranges - **`write`** creates or overwrites entire files - **`edit`** performs surgical find-and-replace edits within files ### LSP Tool When [LSP servers](https://help.altimate.ai/code/configure/lsp/index.md) are configured, the `lsp` tool provides: - Diagnostics (errors, warnings) - Go-to-definition - Hover information - Completions ### MCP Discover Tool The `mcp_discover` tool finds MCP servers configured in other AI coding tools and can add them to your altimate-code config permanently. **Supported sources:** | Tool | Config Path | Key | | ----------------- | ----------------------------- | ------------ | | VS Code / Copilot | `.vscode/mcp.json` | `servers` | | Cursor | `.cursor/mcp.json` | `mcpServers` | | GitHub Copilot | `.github/copilot/mcp.json` | `mcpServers` | | Claude Code | `.mcp.json`, `~/.claude.json` | `mcpServers` | | Gemini CLI | `.gemini/settings.json` | `mcpServers` | **Actions:** - `mcp_discover(action: "list")` — Show discovered servers and which are already in your config - `mcp_discover(action: "add", scope: "project")` — Write new servers to `.altimate-code/altimate-code.json` - `mcp_discover(action: "add", scope: "global")` — Write to the global config dir (`~/.config/altimate-code/`) **Auto-discovery:** At startup, altimate-code discovers external MCP servers and shows a toast notification. Servers from your home directory (`~/.claude.json`, `~/.gemini/settings.json`) are auto-enabled since they're user-owned. Servers from project-level files (`.vscode/mcp.json`, `.mcp.json`, `.cursor/mcp.json`) are discovered but **disabled by default** for security — ask the assistant to add them or use `mcp_discover(action: "add")`. Tip Home-directory MCP servers (from `~/.claude.json`, `~/.gemini/settings.json`) are loaded automatically. Project-scoped servers require explicit approval via `mcp_discover(action: "add")`. Security: untrusted repositories Project-level MCP configs (`.vscode/mcp.json`, `.mcp.json`, `.cursor/mcp.json`) are discovered but not auto-connected. This prevents malicious repositories from executing arbitrary commands. You must explicitly approve project-scoped servers before they run. To disable auto-discovery, set in your config: ```json { "experimental": { "auto_mcp_discovery": false } } ``` # Trace Altimate Code captures detailed traces (session recordings) of every session, including LLM generations, tool calls, token usage, cost, and timing, and saves them locally as JSON files. Traces are invaluable for debugging agent behavior, optimizing cost, and understanding how the agent solves problems. Tracing is **enabled by default** and requires no configuration. Traces are stored locally and never leave your machine unless you configure a remote exporter. ## Quick Start ```bash # Run a prompt (trace is saved automatically) altimate-code run "optimize my most expensive queries" # → Trace saved: ~/.local/share/altimate-code/traces/abc123.json # List recent traces altimate-code trace list # View a trace in the browser altimate-code trace view abc123 ``` ## What's Captured Each trace records the full agent session: | Data | Description | | ------------------------ | --------------------------------------------------------------------------- | | **Generations** | Each LLM call with model, provider, finish reason, and variant | | **Token usage** | Input, output, reasoning, cache read, and cache write tokens per generation | | **Cost** | Per-generation and total session cost in USD | | **Tool calls** | Every tool invocation with input, output, duration, and status | | **Timing** | Start/end timestamps for every span (session, generation, tool) | | **Errors** | Error messages and status on failed tool calls or generations | | **Metadata** | Model, provider, agent, prompt, user ID, environment, tags | | **Loop Detection** | Automatic detection of repeated tool call patterns | | **Post-Session Summary** | AI-generated summary of the session's key actions and outcomes | ### Data Engineering Attributes When using SQL and dbt tools, traces automatically capture domain-specific data: | Category | Examples | | -------------------- | --------------------------------------------------------------------------------------------------------- | | **Warehouse** | Bytes scanned/billed, execution time, queue time, partitions pruned, cache hits, query ID, estimated cost | | **SQL** | Query text, dialect, validation results, lineage (input/output tables), schema changes | | **dbt** | Command, model status, materialization, rows affected, compiled SQL, test results, Jinja errors | | **Data Quality** | Row counts, null percentages, freshness, anomaly detection | | **Cost Attribution** | LLM cost + warehouse compute cost + storage delta = total cost, per user/team/project | These attributes are purely optional. Traces are valid without them. They're populated automatically by tools that have access to warehouse metadata. ## Configuration Add to your config file (`~/.config/altimate-code/altimate-code.json` or project-level `altimate-code.json`): ```json { "tracing": { "enabled": true, "dir": "~/.local/share/altimate-code/traces/", "maxFiles": 100, "exporters": [] } } ``` | Option | Type | Default | Description | | ----------- | --------- | -------------------------------------- | ------------------------------------------------------------------------------- | | `enabled` | `boolean` | `true` | Enable or disable tracing | | `dir` | `string` | `~/.local/share/altimate-code/traces/` | Custom directory for trace files | | `maxFiles` | `number` | `100` | Max trace files to keep (oldest pruned automatically). Set to `0` for unlimited | | `exporters` | `array` | `[]` | Remote HTTP exporters (see below) | ### Disabling Tracing ```json { "tracing": { "enabled": false } } ``` Or per-run with the `--no-trace` flag: ```bash altimate-code run --no-trace "quick question" ``` ## Viewing Traces ### List Traces ```bash altimate-code trace list ``` Shows a table of recent traces with session ID, timestamp, duration, tokens, cost, tool calls, and status. ```text SESSION WHEN DURATION TOKENS COST TOOLS STATUS PROMPT abc123def456 2m ago 45.2s 12,500 $0.0150 8 ok optimize my most expensive queries xyz789abc012 1h ago 12.8s 3,200 $0.0040 3 ok explain this model err456def789 3h ago 5.1s 1,800 $0.0020 2 error run dbt tests ``` Options: | Flag | Description | | --------------- | -------------------------------------- | | `-n`, `--limit` | Number of traces to show (default: 20) | ### View a Trace ```bash altimate-code trace view ``` Opens a local web server with an interactive trace viewer in your browser. The viewer has 5 tabs: - **Summary** (default) — The story of the session: what was asked, files changed with diff previews, outcome (dbt/pytest/Airflow results), what happened timeline, and cost breakdown - **Waterfall** — Gantt-style timeline bars for every span, color-coded by type - **Tree** — Nested indentation view showing parent/child span relationships - **Chat** — Conversation flow with user prompt and agent responses - **Log** — Flat chronological list of all events The Summary tab shows what matters most to data engineers: - **What was asked** — Your prompt, truncated with expand toggle - **Files changed** — Each file with NEW/EDIT badge and SQL diff preview - **Outcome** — dbt build results, test results, SQL query results (clickable to jump to waterfall) - **What happened** — Smart timeline grouping boring commands, showing meaningful actions - **Loop warnings** — Automatic detection when the agent repeats the same tool call - **Cost details** — Collapsible token breakdown with visual bar chart Options: | Flag | Description | | -------- | ---------------------------------------------- | | `--port` | Port for the viewer server (default: random) | | `--live` | Auto-refresh every 2s for in-progress sessions | Partial session ID matching is supported. For example, `altimate-code trace view abc` matches `abc123def456`. ### Live Viewing (In-Progress Sessions) Traces are written incrementally. After every tool call and generation, a snapshot is flushed to disk. This means you can view a trace while the session is still running: ```bash # In terminal 1: run a long task altimate-code run "refactor the entire pipeline" # In terminal 2: watch the trace live altimate-code trace view --live ``` The `--live` flag adds a green "LIVE" indicator and polls for updates every 2 seconds. The page auto-refreshes when new spans appear. ### From the TUI Type `/trace` in the TUI to open a trace history dialog listing all recent sessions. Select any trace to open it in your browser with the interactive viewer. The current session appears at the top, and traces are grouped by date with duration and timestamp info. The viewer launches in live mode automatically for in-progress sessions, so you can watch spans appear as the agent works. ### Sharing Traces The trace viewer includes a **Share Trace** button that exports a self-contained HTML file. This file includes all session data and can be opened in any browser without a server — perfect for sharing with teammates, attaching to tickets, or archiving sessions. ## Remote Exporters Traces can be sent to remote backends via HTTP POST. Each exporter receives the full trace JSON on session completion. ```json { "tracing": { "exporters": [ { "name": "my-backend", "endpoint": "https://api.example.com/v1/traces", "headers": { "Authorization": "Bearer " } } ] } } ``` | Field | Type | Description | | ---------- | -------- | ------------------------------------------- | | `name` | `string` | Identifier for this exporter (used in logs) | | `endpoint` | `string` | HTTP endpoint to POST trace JSON to | | `headers` | `object` | Custom headers (e.g., auth tokens) | **How it works:** - All exporters run concurrently with the local file write via `Promise.allSettled` - A failing exporter never blocks local file storage or other exporters - If the server responds with `{ "url": "..." }`, the URL is displayed to the user - Exporters have a 10-second timeout - All export operations are best-effort and never crash the CLI ## Trace File Format Traces are stored as JSON files in the traces directory. The schema is versioned for forward compatibility. ```json { "version": 2, "traceId": "019cf4e2-...", "sessionId": "session-abc123", "startedAt": "2026-03-15T10:00:00.000Z", "endedAt": "2026-03-15T10:00:45.200Z", "metadata": { "model": "anthropic/claude-sonnet-4-20250514", "providerId": "anthropic", "agent": "builder", "variant": "high", "prompt": "optimize my most expensive queries", "userId": "user@example.com", "environment": "production", "version": "2.0.0", "tags": ["benchmark", "nightly"] }, "spans": [ { "spanId": "...", "parentSpanId": null, "name": "session-abc123", "kind": "session", "startTime": 1710500000000, "endTime": 1710500045200, "status": "ok" }, { "spanId": "...", "parentSpanId": "", "name": "generation-1", "kind": "generation", "startTime": 1710500000100, "endTime": 1710500003500, "status": "ok", "model": { "modelId": "anthropic/claude-sonnet-4-20250514", "providerId": "anthropic" }, "finishReason": "stop", "cost": 0.005, "tokens": { "input": 1500, "output": 300, "reasoning": 100, "cacheRead": 200, "cacheWrite": 50, "total": 2150 } }, { "spanId": "...", "parentSpanId": "", "name": "sql_execute", "kind": "tool", "startTime": 1710500001000, "endTime": 1710500003000, "status": "ok", "tool": { "callId": "call-1", "durationMs": 2000 }, "input": { "query": "SELECT ..." }, "output": "10 rows returned", "attributes": { "de.warehouse.system": "snowflake", "de.warehouse.bytes_scanned": 45000000, "de.warehouse.estimated_cost_usd": 0.0012, "de.sql.validation.valid": true } } ], "summary": { "totalTokens": 2150, "totalCost": 0.005, "totalToolCalls": 1, "totalGenerations": 1, "duration": 45200, "status": "completed", "tokens": { "input": 1500, "output": 300, "reasoning": 100, "cacheRead": 200, "cacheWrite": 50 } } } ``` ### Span Types | Kind | Description | Key Fields | | ------------ | ---------------------------------------- | --------------------------------------------------- | | `session` | Root span for the entire session | `input` (prompt), `output` (summary) | | `generation` | One LLM call (step-start to step-finish) | `model`, `finishReason`, `tokens`, `cost` | | `tool` | A tool invocation | `tool.callId`, `tool.durationMs`, `input`, `output` | ### Domain Attribute Namespaces All domain-specific attributes use the `de.*` prefix and are stored in the `attributes` map on tool spans: | Prefix | Domain | | ---------------- | ------------------------------------------------------ | | `de.warehouse.*` | Warehouse metrics (bytes, credits, partitions, timing) | | `de.sql.*` | SQL quality (validation, lineage, schema changes) | | `de.dbt.*` | dbt operations (model status, tests, Jinja, DAG) | | `de.quality.*` | Data quality (row counts, freshness, anomalies) | | `de.cost.*` | Cost attribution (LLM + warehouse + storage) | ## Crash Recovery Traces are designed to survive process crashes: 1. **Immediate snapshot.** A trace file is written as soon as the session starts, before any LLM interaction. Even if the process crashes immediately, a minimal trace file exists. 1. **Incremental snapshots.** After every tool call and generation completion, the trace file is updated atomically (write to temp file, then rename). The file on disk always contains a valid, complete JSON document. 1. **Crash handlers.** The `run` and `serve` commands register `SIGINT`/`SIGTERM`/`beforeExit` handlers that finalize in-flight traces on shutdown. (`run` flushes synchronously with a `"crashed"` status; `serve` drains and finalizes its active sessions.) 1. **Status indicators.** Trace status tells you exactly what happened: | Status | Meaning | | ----------- | ---------------------------------------------------- | | `completed` | Session finished normally | | `error` | Session finished with an error | | `running` | Session is still in progress (visible in live mode) | | `crashed` | Process was interrupted before the session completed | Crashed traces contain all data up to the last successful snapshot. You can view them normally with `altimate-code trace view`. ## Historical Traces All traces are stored in the traces directory and persist across sessions. Use `trace list` to browse history: ```bash # Show the last 50 traces altimate-code trace list -n 50 # Navigate to the next page altimate-code trace list --offset 50 -n 50 # View any historical trace altimate-code trace view ``` Traces are automatically pruned when `maxFiles` is exceeded (default: 100). The oldest traces are removed first. Set `maxFiles: 0` for unlimited retention. ## Privacy Traces are stored **locally only** by default. They contain: - The prompt you sent - Tool inputs and outputs (SQL queries, file contents, command results) - Model responses If you configure remote exporters, trace data is sent to those endpoints. No trace data is included in the anonymous telemetry described in [Telemetry](https://help.altimate.ai/code/reference/telemetry/index.md). Sensitive Data Traces may contain SQL queries, file paths, and command outputs from your session. If you share trace files or configure remote exporters, be aware that this data will be included. # Warehouses Altimate Code connects to 13 warehouse types. Configure them in `.altimate-code/connections.json` (project-local) or `~/.altimate-code/connections.json` (global). ## Configuration Each warehouse has a key (the connection name) and a config object: ```json { "my-connection-name": { "type": "", ... } } ``` Tip Use `{env:...}` substitution for passwords and tokens so you never commit secrets to version control. ## Snowflake ```json { "prod-snowflake": { "type": "snowflake", "account": "xy12345.us-east-1", "user": "analytics_user", "password": "{env:SNOWFLAKE_PASSWORD}", "warehouse": "COMPUTE_WH", "database": "ANALYTICS", "role": "ANALYST_ROLE" } } ``` | Field | Required | Description | | ------------------------ | -------- | ------------------------------------------------------- | | `account` | Yes | Snowflake account identifier (e.g. `xy12345.us-east-1`) | | `user` | Yes | Username | | `password` | Auth | Password (use one auth method) | | `private_key_path` | Auth | Path to private key file (alternative to password) | | `private_key_passphrase` | No | Passphrase for encrypted private key | | `warehouse` | No | Warehouse name | | `database` | No | Database name | | `schema` | No | Schema name | | `role` | No | User role | ### Key-pair authentication ```json { "prod-snowflake": { "type": "snowflake", "account": "xy12345.us-east-1", "user": "svc_altimate", "private_key_path": "~/.ssh/snowflake_rsa_key.p8", "private_key_passphrase": "{env:SNOWFLAKE_KEY_PASSPHRASE}", "warehouse": "COMPUTE_WH", "database": "ANALYTICS", "role": "TRANSFORM_ROLE" } } ``` ## BigQuery ```json { "bigquery-prod": { "type": "bigquery", "project": "my-gcp-project", "credentials_path": "/code/path/to/service-account.json", "location": "US" } } ``` | Field | Required | Description | | ------------------ | -------- | ------------------------------------------------------------------------------------ | | `project` | Yes | Google Cloud project ID | | `credentials_path` | No | Path to service account JSON file. Omit to use Application Default Credentials (ADC) | | `location` | No | Default location (default: `US`) | ### Using Application Default Credentials If you're already authenticated via `gcloud`, omit `credentials_path`: ```json { "bigquery-prod": { "type": "bigquery", "project": "my-gcp-project" } } ``` ## Databricks ```json { "databricks-prod": { "type": "databricks", "server_hostname": "adb-1234567890.1.azuredatabricks.net", "http_path": "/code/sql/1.0/warehouses/abcdef1234567890", "access_token": "{env:DATABRICKS_TOKEN}", "catalog": "main", "schema": "default" } } ``` | Field | Required | Description | | ----------------- | -------- | -------------------------------- | | `server_hostname` | Yes | Databricks workspace hostname | | `http_path` | Yes | HTTP path from compute resources | | `access_token` | Yes | Personal Access Token (PAT) | | `catalog` | No | Unity Catalog name | | `schema` | No | Schema/database name | ## Trino ```json { "trino-prod": { "type": "trino", "host": "trino.example.com", "port": 8443, "protocol": "https", "catalog": "iceberg", "schema": "analytics", "user": "analyst", "password": "{env:TRINO_PASSWORD}" } } ``` | Field | Required | Description | | ------------------- | ----------- | --------------------------------------------------------------------------------- | | `connection_string` | No | Full server URL (alternative to host/port, e.g. `https://trino.example.com:8443`) | | `host` | No | Hostname (default: `localhost`) | | `port` | No | Port (default: `8080`, or `8443` when `protocol` is `https`) | | `protocol` | No | `http` or `https` (default: `http`) | | `catalog` | Recommended | Default catalog for query execution and required for schema/table introspection | | `schema` | No | Default schema | | `user` | No | Trino user (default sent by the client if omitted) | | `password` | Auth | Basic authentication password | | `access_token` | Auth | Bearer/JWT token | | `extra_headers` | No | Additional HTTP headers to send to Trino | ### Using a bearer token ```json { "trino-prod": { "type": "trino", "connection_string": "https://trino.example.com:8443", "catalog": "hive", "schema": "default", "access_token": "{env:TRINO_TOKEN}" } } ``` ## PostgreSQL ```json { "my-postgres": { "type": "postgres", "host": "localhost", "port": 5432, "database": "analytics", "user": "analyst", "password": "{env:PG_PASSWORD}" } } ``` | Field | Required | Description | | ------------------- | -------- | --------------------------------------------------------- | | `connection_string` | No | Full connection string (alternative to individual fields) | | `host` | No | Hostname (default: `localhost`) | | `port` | No | Port (default: `5432`) | | `database` | No | Database name (default: `postgres`) | | `user` | No | Username | | `password` | No | Password | ### Using a connection string ```json { "my-postgres": { "type": "postgres", "connection_string": "postgresql://analyst:secret@localhost:5432/analytics" } } ``` Special characters in passwords Passwords with special characters (`@`, `#`, `:`, `/`) are automatically percent-encoded. No manual escaping required. ## Redshift ```json { "redshift-prod": { "type": "redshift", "host": "my-cluster.abc123.us-east-1.redshift.amazonaws.com", "port": 5439, "database": "analytics", "user": "admin", "password": "{env:REDSHIFT_PASSWORD}" } } ``` | Field | Required | Description | | -------------------- | -------- | --------------------------------------------------------- | | `connection_string` | No | Full connection string (alternative to individual fields) | | `host` | No | Hostname | | `port` | No | Port (default: `5439`) | | `database` | No | Database name (default: `dev`) | | `user` | No | Username | | `password` | No | Password | | `iam_role` | No | IAM role ARN (alternative to password) | | `region` | No | AWS region (default: `us-east-1`) | | `cluster_identifier` | No | Cluster identifier (required for IAM auth) | ### IAM authentication ```json { "redshift-prod": { "type": "redshift", "host": "my-cluster.abc123.us-east-1.redshift.amazonaws.com", "database": "analytics", "user": "admin", "iam_role": "arn:aws:iam::123456789012:role/RedshiftReadOnly", "cluster_identifier": "my-cluster", "region": "us-east-1" } } ``` ## DuckDB ```json { "dev-duckdb": { "type": "duckdb", "path": "./dev.duckdb" } } ``` | Field | Required | Description | | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `path` | Yes | Database file path, or `":memory:"` for in-memory. Cannot be omitted — a missing `path` is rejected rather than silently falling back to `":memory:"` | | `create` | No | Create the database file if it is missing (default: `false`) | The store must already exist Connecting never creates the database. If the file is missing, the connection fails with an error naming the path it looked for — an empty database would otherwise answer every query with no rows and no error, which reads as a successful query against an empty warehouse. Set `"create": true` only when you intend this store to be created. How a relative `path` is resolved A relative `path` is resolved once, when the config is loaded, against the directory that declares it: - `~/.altimate-code/connections.json` → resolved against `~/.altimate-code` - `/.altimate-code/connections.json` → resolved against `` - `ALTIMATE_CODE_CONN_*` environment variables → resolved against the project root It is never resolved against the current working directory, so `--dir` cannot re-point an existing connection at a different file. Absolute paths are always safest. Bare `word:target` values are treated as local files A `path` shaped like `word:target` with no `//` (for example `data:warehouse.duckdb`) is treated as an ordinary local filename by default. The only exceptions are `md:`, `motherduck:`, and `ducklake:` — these specific bare prefixes are recognized remote storage schemes and are always forwarded as remote targets. To force any other value to be treated as remote, use its full `scheme://` form (`s3://...`, `md://...`) instead of a bare prefix. Concurrent access DuckDB does not support concurrent write access to the same file. If another process holds a write lock, Altimate Code automatically retries the connection in **read-only** mode so you can still query the data. A clear error message is shown if read-only access also fails. ## MySQL ```json { "mysql-prod": { "type": "mysql", "host": "localhost", "port": 3306, "database": "analytics", "user": "analyst", "password": "{env:MYSQL_PASSWORD}" } } ``` | Field | Required | Description | | ---------- | -------- | ------------------------------- | | `host` | No | Hostname (default: `localhost`) | | `port` | No | Port (default: `3306`) | | `database` | No | Database name | | `user` | No | Username | | `password` | No | Password | | `ssl_ca` | No | Path to CA certificate file | | `ssl_cert` | No | Path to client certificate file | | `ssl_key` | No | Path to client key file | ## MongoDB ```json { "my-mongodb": { "type": "mongodb", "host": "localhost", "port": 27017, "database": "analytics", "user": "analyst", "password": "{env:MONGO_PASSWORD}" } } ``` | Field | Required | Description | | ------------------- | -------- | --------------------------------------------------------- | | `connection_string` | No | Full connection string (alternative to individual fields) | | `host` | No | Hostname (default: `127.0.0.1`) | | `port` | No | Port (default: `27017`) | | `database` | No | Database name | | `user` | No | Username | | `password` | No | Password | | `auth_source` | No | Authentication database (default: `admin`) | | `replica_set` | No | Replica set name | | `tls` | No | Enable TLS (default: `false`) | | `direct_connection` | No | Connect directly to a single host | ### Using a connection string ```json { "my-mongodb": { "type": "mongodb", "connection_string": "mongodb://analyst:secret@localhost:27017/analytics" } } ``` Note MongoDB uses MQL (MongoDB Query Language) instead of SQL. Queries are submitted as JSON objects via the `execute` method. Supported commands: `find`, `aggregate`, `countDocuments`, `distinct`, `insertOne`, `insertMany`, `updateOne`, `updateMany`, `deleteOne`, `deleteMany`, `createIndex`, `listIndexes`, `createCollection`, `dropCollection`, `ping`. Blocked operators For safety, aggregate pipelines block `$out` and `$merge` (write stages) and `$function` and `$accumulator` (arbitrary JavaScript execution). Use `find`, `countDocuments`, or safe aggregate stages for read-only analysis. Server compatibility The MongoDB driver (v6.x) supports MongoDB server versions 3.6 through 8.0, covering all releases from the last 3+ years. ## ClickHouse ```json { "clickhouse-prod": { "type": "clickhouse", "host": "localhost", "port": 8123, "database": "analytics", "user": "default", "password": "{env:CLICKHOUSE_PASSWORD}" } } ``` | Field | Required | Description | | --------------------- | -------- | ------------------------------------------------------------------------------ | | `connection_string` | No | Full URL (alternative to individual fields, e.g. `http://user:pass@host:8123`) | | `host` | No | Hostname (default: `localhost`) | | `port` | No | HTTP port (default: `8123`) | | `database` | No | Database name (default: `default`) | | `user` | No | Username (default: `default`) | | `password` | No | Password | | `protocol` | No | `http` or `https` (default: `http`) | | `request_timeout` | No | Request timeout in ms (default: `30000`) | | `tls_ca_cert` | No | Path to CA certificate for TLS | | `tls_cert` | No | Path to client certificate for mutual TLS | | `tls_key` | No | Path to client key for mutual TLS | | `clickhouse_settings` | No | Object of ClickHouse server settings | ### ClickHouse Cloud ```json { "clickhouse-cloud": { "type": "clickhouse", "host": "abc123.us-east-1.aws.clickhouse.cloud", "port": 8443, "protocol": "https", "user": "default", "password": "{env:CLICKHOUSE_CLOUD_PASSWORD}", "database": "default" } } ``` ### Using a connection string ```json { "clickhouse-prod": { "type": "clickhouse", "connection_string": "https://default:secret@my-ch.cloud:8443" } } ``` Server compatibility The ClickHouse driver supports ClickHouse server versions 23.3 and later, covering all non-EOL releases. This includes LTS releases 23.8, 24.3, 24.8, and all stable releases through the current version. ## Oracle ```json { "oracle-prod": { "type": "oracle", "host": "localhost", "port": 1521, "service_name": "ORCL", "user": "analyst", "password": "{env:ORACLE_PASSWORD}" } } ``` | Field | Required | Description | | ------------------- | -------- | ----------------------------------------------------------------------------- | | `connection_string` | No | Full connect string (alternative to individual fields, e.g. `host:1521/ORCL`) | | `host` | No | Hostname (default: `127.0.0.1`) | | `port` | No | Port (default: `1521`) | | `service_name` | No | Oracle service name (default: `ORCL`) | | `database` | No | Alias for `service_name` | | `user` | No | Username | | `password` | No | Password | Pure JavaScript driver The Oracle driver uses `oracledb` in thin mode (pure JavaScript) — no Oracle Instant Client installation is required. ## SQLite ```json { "dev-sqlite": { "type": "sqlite", "path": "./dev.sqlite" } } ``` | Field | Required | Description | | ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `path` | Yes | Database file path, or `":memory:"` for in-memory. Cannot be omitted — a missing `path` is rejected rather than silently falling back to `":memory:"` | | `readonly` | No | Open in read-only mode (default: `false`) | | `create` | No | Create the database file if it is missing (default: `false`) | Note SQLite uses Bun's built-in `bun:sqlite` driver. WAL journal mode is enabled automatically for writable databases. The store must already exist As with DuckDB, connecting never creates the database, and a relative `path` resolves against the directory of the config that declares it — not the current working directory. See the DuckDB section above for the full rules. ## SQL Server ```json { "sqlserver-prod": { "type": "sqlserver", "host": "localhost", "port": 1433, "database": "analytics", "user": "sa", "password": "{env:MSSQL_PASSWORD}" } } ``` | Field | Required | Description | | -------------------------- | -------- | -------------------------------------------------------------- | | `host` | No | Hostname (default: `localhost`) | | `port` | No | Port (default: `1433`) | | `database` | No | Database name | | `user` | No | Username | | `password` | No | Password | | `driver` | No | ODBC driver name (default: `ODBC Driver 18 for SQL Server`) | | `azure_auth` | No | Use Azure AD authentication (default: `false`) | | `trust_server_certificate` | No | Trust server certificate without validation (default: `false`) | ## Unsupported Databases The following databases are not yet natively supported, but workarounds are available: | Database | Workaround | | ----------- | ------------------------------------------------ | | Cassandra | Use the bash tool with `cqlsh` to query directly | | CockroachDB | PostgreSQL-compatible — use `type: postgres` | | TimescaleDB | PostgreSQL extension — use `type: postgres` | ## SSH Tunneling All warehouse types support SSH tunneling for connections behind a bastion host: ```json { "prod-via-bastion": { "type": "postgres", "host": "10.0.1.50", "database": "analytics", "user": "analyst", "password": "{env:PG_PASSWORD}", "ssh_host": "bastion.example.com", "ssh_port": 22, "ssh_user": "ubuntu", "ssh_auth_type": "key", "ssh_key_path": "~/.ssh/id_rsa" } } ``` | Field | Required | Description | | --------------- | -------- | ------------------------ | | `ssh_host` | Yes | SSH bastion hostname | | `ssh_port` | No | SSH port (default: `22`) | | `ssh_user` | Yes | SSH username | | `ssh_auth_type` | No | `"key"` or `"password"` | | `ssh_key_path` | No | Path to SSH private key | | `ssh_password` | No | SSH password | ## Auto-Discovery The `/discover` command can automatically detect warehouse connections from: | Source | Detection | | --------------------- | ---------------------------------------------------------------------------------------------- | | dbt profiles | Searches for `profiles.yml` (see resolution order below) | | Docker containers | Finds running PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, ClickHouse, and Trino containers | | Environment variables | Scans for `SNOWFLAKE_ACCOUNT`, `PGHOST`, `DATABRICKS_HOST`, etc. | ### dbt profiles.yml resolution order When discovering dbt profiles, altimate checks the following locations **in priority order** and uses the first one found: | Priority | Location | Description | | -------- | ---------------------------- | ---------------------------------------------------------------------------------------------- | | 1 | Explicit path | If you pass a `path` parameter to the `dbt_profiles` tool | | 2 | `DBT_PROFILES_DIR` env var | Standard dbt environment variable — set it to the directory containing your `profiles.yml` | | 3 | Project-local `profiles.yml` | A `profiles.yml` in your dbt project root (next to `dbt_project.yml`) | | 4 | `/.dbt/profiles.yml` | The global default location (e.g., `~/.dbt/` on macOS/Linux, `%USERPROFILE%\.dbt\` on Windows) | This means teams that keep `profiles.yml` in their project repo (a common pattern for CI/CD) will have it detected automatically — no extra configuration needed. ```bash # Option 1: Set the environment variable export DBT_PROFILES_DIR=/path/to/your/project # Option 2: Just put profiles.yml next to dbt_project.yml # Copy from default location (macOS/Linux) cp ~/.dbt/profiles.yml ./profiles.yml altimate /discover ``` See [Warehouse Tools](https://help.altimate.ai/code/data-engineering/tools/warehouse-tools/index.md) for the full list of environment variable signals. ## Testing Connections After configuring a warehouse, verify it works: ```text > warehouse_test prod-snowflake Testing connection to prod-snowflake (snowflake)... ✓ Connected successfully Account: xy12345.us-east-1 User: analytics_user Role: ANALYST_ROLE Warehouse: COMPUTE_WH Database: ANALYTICS ``` ## Post-Connection Suggestions After you successfully connect a warehouse, altimate suggests next steps to help you get the most out of your connection. Suggestions are shown progressively based on what you've already done: 1. **Index your schemas** — populate the schema cache for autocomplete and context-aware analysis 1. **Run SQL analysis** — scan your query history for anti-patterns and optimization opportunities 1. **Inspect schema structure** — review tables, columns, and relationships 1. **Check lineage** — trace column-level data flow across your models If altimate detects a dbt project in your workspace, it also recommends relevant dbt skills (`/dbt-develop`, `/dbt-troubleshoot`, `/dbt-analyze`). Each suggestion is shown **once per session** — dismissing or acting on a suggestion removes it from the queue. You can also run a suggested action later via its corresponding tool or slash command. # Tools Reference Altimate Code has 100+ specialized tools organized by function. | Category | Tools | Purpose | | ------------------------------------------------------------------------------------------------ | ------------------- | ----------------------------------------------------------------------------------------- | | [Built-in Tools](https://help.altimate.ai/code/configure/tools/config/index.md) | 14 tools | File operations, search, shell, subagents, and other core agent tools | | [Core Tools](https://help.altimate.ai/code/configure/tools/core-tools/index.md) | 28 tools | Rust-based SQL engine — validation, linting, safety, lineage, formatting, PII, governance | | [SQL Tools](https://help.altimate.ai/code/data-engineering/tools/sql-tools/index.md) | 10 tools | Analysis, optimization, translation, formatting, cost prediction | | [Schema Tools](https://help.altimate.ai/code/data-engineering/tools/schema-tools/index.md) | 7 tools | Inspection, search, PII detection, tagging, diffing | | [FinOps Tools](https://help.altimate.ai/code/data-engineering/tools/finops-tools/index.md) | 8 tools | Cost analysis, warehouse sizing, unused resources, RBAC | | [Lineage Tools](https://help.altimate.ai/code/data-engineering/tools/lineage-tools/index.md) | 1 tool | Column-level lineage tracing with confidence scoring | | [dbt Tools](https://help.altimate.ai/code/data-engineering/tools/dbt-tools/index.md) | 4 tools + 11 skills | Run, manifest, lineage, profiles, test generation, scaffolding | | [Warehouse Tools](https://help.altimate.ai/code/data-engineering/tools/warehouse-tools/index.md) | 6 tools | Environment scanning, connection management, discovery, testing | | [Custom Tools](https://help.altimate.ai/code/configure/tools/custom/index.md) | — | Build your own tools with TypeScript plugins | All tools are available in the interactive TUI. The agent automatically selects the right tools based on your request. # Tools altimate includes built-in tools that agents use to interact with your codebase and environment. ## Built-in Tools | Tool | Description | | ------------ | ----------------------------------------------------- | | `bash` | Execute shell commands | | `read` | Read file contents | | `edit` | Edit files with find-and-replace | | `write` | Create or overwrite files | | `glob` | Find files by pattern | | `grep` | Search file contents with regex | | `list` | List directory contents | | `patch` | Apply multi-file patches | | `lsp` | Language server operations (diagnostics, completions) | | `webfetch` | Fetch and process web pages | | `websearch` | Search the web | | `question` | Ask the user a question | | `todo_read` | Read task list | | `todo_write` | Create/update tasks | | `skill` | Execute a skill | ## Data Engineering Tools In addition to built-in tools, altimate provides 100+ specialized data engineering tools. See the [Data Engineering Tools](https://help.altimate.ai/code/configure/tools/index.md) section for details. ## Tool Permissions Control which tools agents can use via the [permission system](https://help.altimate.ai/code/configure/permissions/index.md). For full details, pattern-based rules, and recommended configurations, see the [Permissions reference](https://help.altimate.ai/code/configure/permissions/index.md). ## Tool Behavior ### Bash Tool The `bash` tool executes shell commands in the project directory. Commands run in a non-interactive shell with the user's environment. ### Read / Write / Edit Tools File tools respect the project boundaries and permission settings: - **`read`** — Reads file contents, supports line ranges - **`write`** — Creates or overwrites entire files - **`edit`** — Surgical find-and-replace edits within files ### LSP Tool When [LSP servers](https://help.altimate.ai/code/configure/lsp/index.md) are configured, the `lsp` tool provides: - Diagnostics (errors, warnings) - Go-to-definition - Hover information - Completions ### Tool Retrieval With the full data-engineering toolset (~78 tools), sending every tool definition on every turn floods the context window and adds distractors that hurt the model's tool selection. **Tool retrieval** trims the exposed set per turn to a relevant subset, cutting input tokens substantially at the same task quality. It is **off by default** and enabled with an environment variable: ```bash ALTIMATE_TOOL_RETRIEVAL=1 altimate-code run "..." ``` When enabled, each turn exposes: - an always-on **core** set of essentials that are never trimmed (`bash`, `read`, `write`, `edit`, `glob`, `grep`, `list`, `task`, `todowrite`, `skill`), - any tool already **referenced by an in-flight tool call** (so a mid-trajectory tool is never dropped), and - the highest-scoring remaining tools by a deterministic lexical match against the turn's request, up to a fixed budget. Selection is deterministic and dependency-free; small tool sets are left untouched (nothing to gain). In internal benchmarks this cut input tokens by ~50% at an identical task-resolution rate. # Core Tools The `altimate_core_*` tools are powered by a Rust-based SQL engine that provides fast, deterministic analysis without LLM calls. These tools handle validation, linting, safety scanning, lineage, formatting, and more. ## Analysis & Validation ### altimate_core_check Run the full analysis pipeline — validate + lint + safety scan + PII check — in a single call. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_validate Validate SQL syntax and schema references. Checks if tables and columns exist in the schema and if SQL is valid for the target dialect. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_lint Lint SQL for anti-patterns — NULL comparisons, implicit casts, unused CTEs, and dialect-specific problems. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_grade Grade SQL quality on an A–F scale. Evaluates readability, performance, correctness, and best practices. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ## Safety & Governance ### altimate_core_safety Scan SQL for injection patterns, dangerous statements (DROP, TRUNCATE), and security threats. **Parameters:** `sql` (required) ______________________________________________________________________ ### altimate_core_is_safe Quick boolean safety check — returns true/false indicating whether SQL is safe to execute. **Parameters:** `sql` (required) ______________________________________________________________________ ### altimate_core_policy Check SQL against YAML-based governance policy guardrails. Validates compliance with custom rules like allowed tables, forbidden operations, and data access restrictions. **Parameters:** `sql` (required), `policy_json` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_classify_pii Classify PII columns in a schema by name patterns and data types. Identifies columns likely containing personal identifiable information. **Parameters:** `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_query_pii Analyze query-level PII exposure. Checks if a SQL query accesses columns classified as PII and reports the exposure risk. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ## SQL Transformation ### altimate_core_fix Auto-fix SQL errors using fuzzy matching and iterative re-validation to correct syntax errors, typos, and schema reference issues. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional), `max_iterations` (optional) ______________________________________________________________________ ### altimate_core_correct Iteratively correct SQL using a propose-verify-refine loop. More thorough than `fix` — applies multiple correction rounds. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_format Format SQL with dialect-aware keyword casing and indentation. Fast and deterministic. **Parameters:** `sql` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_rewrite Suggest query optimization rewrites — analyzes SQL and proposes concrete rewrites for better performance. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_transpile Translate SQL between dialects using the Rust engine. **Parameters:** `sql` (required), `source_dialect` (required), `target_dialect` (required) ______________________________________________________________________ ## Comparison & Equivalence ### altimate_core_compare Structurally compare two SQL queries. Identifies differences in table references, join conditions, filters, projections, and aggregations. **Parameters:** `left_sql` (required), `right_sql` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_equivalence Check semantic equivalence of two SQL queries — determines if they produce the same result set regardless of syntactic differences. **Parameters:** `sql1` (required), `sql2` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ## Lineage & Metadata ### altimate_core_column_lineage Trace schema-aware column lineage. Maps how columns flow through a query from source tables to output. **Parameters:** `sql` (required), `dialect` (optional), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_track_lineage Track lineage across multiple SQL statements. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_extract_metadata Extract metadata from SQL — identifies tables, columns, functions, CTEs, and other structural elements referenced in a query. **Parameters:** `sql` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_resolve_term Resolve a business glossary term to schema elements using fuzzy matching. Maps human-readable terms like "revenue" or "customer" to actual table/column names. **Parameters:** `term` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_semantics Analyze semantic meaning of SQL elements. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ## Schema Operations ### altimate_core_schema_diff Diff two schema versions to detect structural changes. **Parameters:** `old_ddl` (required), `new_ddl` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_migration Analyze DDL migration safety. Detects potential data loss, type narrowing, missing defaults, and other risks in schema migration statements. **Parameters:** `old_ddl` (required), `new_ddl` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_export_ddl Export a YAML/JSON schema as CREATE TABLE DDL statements. **Parameters:** `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_import_ddl Convert CREATE TABLE DDL into a structured YAML schema definition that other core tools can consume. **Parameters:** `ddl` (required), `dialect` (optional) ______________________________________________________________________ ### altimate_core_fingerprint Compute a SHA-256 fingerprint of a schema. Useful for cache invalidation and change detection. **Parameters:** `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_introspection_sql Generate INFORMATION_SCHEMA introspection queries for a given database type. Supports postgres, bigquery, snowflake, mysql, mssql, redshift. **Parameters:** `db_type` (required), `database` (required), `schema_name` (optional) ______________________________________________________________________ ## Context Optimization ### altimate_core_optimize_context Optimize schema for LLM context window. Applies 5-level progressive disclosure to reduce schema size while preserving essential information. **Parameters:** `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_optimize_for_query Prune schema to only tables and columns relevant to a specific query. Reduces context size for LLM prompts. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_prune_schema Filter schema to only tables and columns referenced by a SQL query. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ## dbt & Autocomplete ### altimate_core_parse_dbt Parse a dbt project directory. Extracts models, sources, tests, and project structure for analysis. **Parameters:** `project_dir` (required) ______________________________________________________________________ ### altimate_core_complete Get cursor-aware SQL completion suggestions. Returns table names, column names, functions, and keywords relevant to the cursor position. **Parameters:** `sql` (required), `cursor_pos` (required), `schema_path` (optional), `schema_context` (optional) ______________________________________________________________________ ### altimate_core_testgen Generate test cases for SQL queries. **Parameters:** `sql` (required), `schema_path` (optional), `schema_context` (optional) # Custom Tools There are two ways to extend altimate-code with custom tools: 1. **CLI tools** (recommended) — simple executables paired with skills 1. **Plugin tools** — TypeScript-based tools using the plugin API ## CLI Tools (Recommended) The simplest way to add custom functionality. Drop any executable into `.altimate-code/tools/` and it's automatically available to the agent via bash. ### Quick Start ```bash # Scaffold a skill + CLI tool pair altimate-code skill create my-tool # Or create manually: mkdir -p .altimate-code/tools cat > .altimate-code/tools/my-tool << 'EOF' #!/usr/bin/env bash set -euo pipefail echo "Hello from my-tool!" EOF chmod +x .altimate-code/tools/my-tool ``` Tools in `.altimate-code/tools/` are automatically prepended to PATH when the agent runs bash commands. No configuration needed. The legacy `.opencode/tools/` directory is also loaded for back-compat. ### Tool Locations | Location | Scope | Auto-discovered | | -------------------------------- | --------------------- | --------------- | | `.altimate-code/tools/` | Project | Yes | | `.opencode/tools/` | Project (legacy) | Yes | | `~/.config/altimate-code/tools/` | Global (all projects) | Yes | ### Pairing with Skills Create a `SKILL.md` that teaches the agent when and how to use your tool: ```bash altimate-code skill create my-tool --language python ``` This scaffolds a `SKILL.md` and a paired executable under the project config dir. Edit both files to implement your tool. (Both `.altimate-code/` and `.opencode/` locations are auto-discovered, so either works.) ### Validating ```bash altimate-code skill test my-tool ``` This checks that the SKILL.md is valid and the paired tool is executable. ### Installing Community Skills Install skills (with their paired tools) from GitHub: ```bash # From a GitHub repo altimate-code skill install anthropics/skills altimate-code skill install dagster-io/skills # From a GitHub web URL (pasted from browser) altimate-code skill install https://github.com/owner/repo/tree/main/skills/my-skill # Remove an installed skill altimate-code skill remove my-skill ``` Or use the TUI: type `/skills`, then `ctrl+i` to install or `ctrl+a` → Remove to delete. ### Output Conventions For best results with the AI agent: - **Default output:** Human-readable text (the agent reads this well) - **`--json` flag:** Structured JSON for scripting - **Summary first:** "Found 12 matches:" or "3 issues detected:" - **Errors to stderr**, results to stdout - **Exit code 0** = success, **1** = error ## Plugin Tools (Advanced) For more complex tools that need access to the altimate-code runtime, use the TypeScript plugin system. ### Quick Start 1. Create a tools directory: ```bash mkdir -p .altimate-code/tools ``` 1. Create a tool file: ```typescript // .altimate-code/tools/my-tool.ts import { defineTool } from "@altimateai/altimate-code-plugin/tool" import { z } from "zod" export default defineTool({ name: "my_custom_tool", description: "Does something useful", parameters: z.object({ input: z.string().describe("The input to process"), }), async execute({ input }) { // Your tool logic here return { result: `Processed: ${input}` } }, }) ``` ## Plugin Package For more complex tools, create a plugin package: ```bash npm init npm install @altimateai/altimate-code-plugin zod ``` ```typescript // index.ts import { definePlugin } from "@altimateai/altimate-code-plugin" import { z } from "zod" export default definePlugin({ name: "my-plugin", tools: [ { name: "analyze_costs", description: "Analyze warehouse costs", parameters: z.object({ warehouse: z.string(), days: z.number().default(30), }), async execute({ warehouse, days }) { // Implementation return { costs: [] } }, }, ], }) ``` ## Registering Plugins Add plugins to your config: ```json { "plugin": [ "@altimateai/altimate-code-plugin-example", "./my-local-plugin" ] } ``` ## Plugin Hooks Plugins can hook into 30+ lifecycle events: - `onSessionStart` / `onSessionEnd` - `onMessage` / `onResponse` - `onToolCall` / `onToolResult` - `onFileEdit` / `onFileWrite` - `onError` - And more... ## Disabling Default Plugins ```bash export ALTIMATE_CLI_DISABLE_DEFAULT_PLUGINS=true ``` # Agent Modes altimate runs in one of three specialized modes. Each mode has different permissions, tool access, and behavioral guardrails. | Mode | Access | Purpose | | ----------- | ---------- | ------------------------------------------------------------------------ | | **Builder** | Read/Write | Create and modify data pipelines | | **Analyst** | Read-only | Answering questions about your data — safe exploration and cost analysis | | **Plan** | Minimal | Planning only, no edits or execution | ## Builder **Full read/write access. For creating and modifying data pipelines.** ```bash altimate --agent builder ``` > Tip: `--yolo` auto-approves permission prompts for faster iteration (`altimate --yolo --agent builder`). Not recommended with live warehouse connections. Use on local/dev environments only. See [Permissions: Yolo Mode](https://help.altimate.ai/code/configure/permissions/#yolo-mode). Builder mode classifies every SQL query before execution. Read queries run freely. Write queries (`INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER`) prompt for approval. Destructive SQL (`DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE`) is hard-blocked and cannot be overridden. ### Example: Create a staging model ```text You: Create a staging model for the raw_orders table Builder: Let me inspect the source table first. > schema_inspect raw_orders Columns: order_id (NUMBER), customer_id (NUMBER), order_date (TIMESTAMP), amount (FLOAT), status (VARCHAR), _loaded_at (TIMESTAMP) > lineage_check "SELECT * FROM raw.raw_orders" Lineage: raw.raw_orders → all columns flow through I'll create a staging model with proper typing, deduplication, and column naming: > write models/staging/stg_orders.sql WITH source AS ( SELECT * FROM {{ source('raw', 'raw_orders') }} ), deduplicated AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY _loaded_at DESC) AS rn FROM source ) SELECT order_id, customer_id, order_date, amount::DECIMAL(12,2) AS order_amount, LOWER(status) AS order_status FROM deduplicated WHERE rn = 1 > sql_analyze [the above SQL] ✓ No anti-patterns detected (confidence: high) > dbt_run --select stg_orders ✓ Compiled and ran successfully ``` ### What builder can do - Create and edit SQL files, dbt models, YAML configs - Execute SQL (DDL/DML/DQL) with write approval prompts - Run dbt commands - Generate tests and documentation - Scaffold new models from templates ______________________________________________________________________ ## Analyst **Read-only access. The agent for asking questions about your data and exploring it safely — use it whenever you just want answers, not changes. Safe for production environments.** ```bash altimate --agent analyst ``` Analyst mode enforces strict guardrails: - **SELECT only.** INSERT, UPDATE, DELETE, DROP are denied (not prompted, blocked entirely) - **No file writes.** Cannot modify your codebase - **Safe bash only.** `ls`, `grep`, `cat`, `head`, `tail`, `find`, `wc` auto-allowed. dbt read commands allowed (`dbt list`, `dbt ls`, `dbt debug`, `dbt deps`). Everything else denied. - **Full web access.** Fetch and search allowed without prompts - **All inspection tools.** Schema, warehouse, finops, lineage, and core analysis tools available ### Example: Investigate expensive queries ```text You: What's driving our Snowflake costs this week? Analyst: Let me pull the query history and credit analysis. > finops_analyze_credits prod-snowflake --days 7 Total credits: 847.2 Top warehouse: TRANSFORM_WH (523.1 credits, 62%) Daily trend: ↑ 15% vs last week > finops_expensive_queries prod-snowflake --days 7 --limit 5 1. SELECT * FROM events JOIN users... (89.3 credits, 47 runs) 2. CREATE TABLE AS SELECT... (45.1 credits, 1 run) 3. SELECT COUNT(DISTINCT...) (23.7 credits, 312 runs) The #1 cost driver is a query running 47 times that scans the full events table with a SELECT *. Let me analyze it: > sql_analyze "SELECT * FROM events JOIN users ON events.user_id = users.id" ⚠ SELECT_STAR: Use explicit column list (severity: warning) ⚠ MISSING_LIMIT: Add LIMIT for exploratory queries (severity: info) Recommendations: 1. Replace SELECT * with only the 6 columns actually used downstream 2. Add a date filter, since the events table has 2.1B rows but most queries only need the last 7 days 3. Consider materializing this as a view with the filter baked in Estimated savings: ~60 credits/week (71% reduction on this query alone) ``` ### What analyst can do - Run SELECT queries (enforced) - Inspect schemas and metadata - Check column-level lineage - Analyze costs and credit consumption - Search warehouse metadata - Detect PII columns - Save training entries ______________________________________________________________________ ## Plan **Minimal permissions. For planning before acting.** ```bash altimate --agent plan ``` Plan mode restricts the agent to reading files and editing plan files only. No SQL, no bash, no file modifications. Use this to outline an approach before switching to builder to execute it. The plan agent investigates the repo before drafting: it makes at least one read-only call (`read`/`grep`/`glob`/`explore`) to ground the plan in your actual code, rather than guessing from the prompt alone. For a genuinely trivial, fully-specified change it will say so and skip straight to the plan. ### Two-step workflow Plan mode uses a two-step approach to keep you in control: 1. **Outline** — The agent produces a short outline (3-5 bullet points) summarizing what it intends to do. 1. **Expand** — After you confirm, the agent expands the outline into a full, detailed plan. This prevents wasted effort on plans that are heading in the wrong direction. ### Refinement loop You don't have to start over if the plan isn't quite right. After the agent presents its outline or full plan, you can: - **Approve** — Accept the plan as-is (e.g., "looks good", "approved", "let's go"). - **Refine** — Edit specific parts and ask the agent to revise (e.g., "change step 3 to use incremental instead of table"). - **Reject** — Discard the plan entirely (e.g., "scrap this", "start over", "reject"). Refinements are capped at **5 revisions per session** to avoid endless loops. After the cap is reached, the agent asks you to approve or reject the current version. ### Example conversation ```text You: Plan a migration of our raw_events table from a view to an incremental model Plan: Here's my proposed approach: • Inspect the current raw_events view and its downstream dependencies • Design an incremental model with a timestamp-based strategy • Add schema tests for the new model • Create a cutover checklist for swapping the view to the model • Update the dbt DAG documentation You: Change the second bullet — use insert_overwrite instead of timestamp-based Plan: Updated outline: • Inspect the current raw_events view and its downstream dependencies • Design an incremental model with an insert_overwrite strategy • Add schema tests for the new model • Create a cutover checklist for swapping the view to the model • Update the dbt DAG documentation You: Approved Plan: [expands into a full detailed plan] ``` ______________________________________________________________________ ## SQL Write Access Control All SQL queries are classified before execution using AST-based parsing: | Query Type | Builder | Analyst | | ----------------------------------------------- | ------------------------- | ------- | | `SELECT`, `SHOW`, `DESCRIBE`, `EXPLAIN` | Allowed | Allowed | | `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER` | Prompts for approval | Denied | | `DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE` | Blocked (cannot override) | Blocked | The classifier detects write operations including: `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `DROP`, `ALTER`, `TRUNCATE`, `GRANT`, `REVOKE`, `COPY INTO`, `CALL`, `EXEC`, `EXECUTE IMMEDIATE`, `BEGIN`, `DECLARE`, `REPLACE`, `UPSERT`, `RENAME`. Multi-statement queries (`SELECT 1; INSERT INTO ...`) are classified as write if any statement is a write. ______________________________________________________________________ ## Custom Agent Modes You can create custom agents with tailored permissions for specialized workflows like validation, migration, research, or executive reporting. See [Agent Configuration](https://help.altimate.ai/code/configure/agents/#custom-agents) for details. For training your AI teammate, see [Training](https://help.altimate.ai/code/data-engineering/training/index.md). # Validators (completion gates) Validators are harness-side checks that run **after** the agent declares done. Unlike tools, they are not visible to the agent — the framework dispatches them automatically once the LLM emits `finishReason === "stop"`. If a validator fails, the framework injects a synthetic user turn with the failure body, giving the agent one more turn to fix the issue (bounded by a per-session retry budget). This catches a class of error that prompt engineering alone cannot: the agent claiming "done" while the work is actually broken (failing dbt tests, schema drift, etc.). Opt-in by default The validator dispatch is gated behind a feature flag. By default (`ALTIMATE_VALIDATORS_ENABLED=0`) the entire dispatch path is skipped — no filesystem scan, no subprocess spawn, no performance overhead for non-opted-in users. See [Enabling validators](#enabling-validators). ## When validators fire The framework triggers the validator dispatch when **all** of the following are true on a turn: 1. `ALTIMATE_VALIDATORS_ENABLED=1` (enforcement) **or** `ALTIMATE_VALIDATORS_SHADOW=1` (telemetry-only) is set 1. The processor returned `continue` (i.e. the loop is about to consume the next message — not a hard stop / compaction event) 1. The LLM's last message has `finish === "stop"` 1. There is no `error` on the last message 1. At least one validator is registered If any of these is false, the dispatch is skipped and the session ends normally. ## Built-in validators altimate-code ships seven validators out of the box. All apply only to sessions inside a dbt project (their `appliesTo` check looks for a `dbt_project.yml`). Two are enabled whenever validators run (`dbt-tests-pass`, `dbt-schema-verify`); the other five are **completion gates** added in the deterministic-validators work and are currently soak-tested in shadow mode — see [Enabling validators](#enabling-validators) before relying on them. ### `dbt-tests-pass` After the agent declares done, runs `altimate-dbt test --model ` against every dbt model the agent modified during this session. Refuses to terminate if any model's tests fail or error. **Catches**: row-data correctness errors (`relationships`, `unique`, `not_null`, `accepted_values`, `AUTO_*_equality` tests) — the kind of bug that column-shape verification cannot detect because the schema can be green while the SELECT logic produces wrong values or wrong row counts. ### `dbt-schema-verify` After the agent declares done, runs `altimate-dbt schema-verify --model ` on every modified model. Reports a mismatch if the produced column shape diverges from the `schema.yml` spec (extra, missing, reordered, or type-mismatched columns). **Catches**: column-level drift that wouldn't be caught by `dbt build` alone — equality tests against the spec would fail later but the agent has already declared done. ## Completion gates (shadow mode) The following five validators are the deterministic **completion gates**. They are soak-tested in shadow mode (`ALTIMATE_VALIDATORS_SHADOW=1`, which records outcomes without blocking) and are **not** recommended for enforcement (`ALTIMATE_VALIDATORS_ENABLED=1`) yet. Each applies only inside a dbt project. ### `dbt-build-green` After the agent declares done, refuses to terminate unless a fresh successful `dbt build` artifact (`run_results.json` newer than the session start, no failing status) covers every model the session edited. **Catches**: the agent declaring "done" while the build is red or stale. ### `dbt-nothing-built` Inverse completion gate. When the workspace carries a task document that literally names required models or files (or the require-artifacts opt-in is set), refuses to terminate a session that authored no project files and produced no fresh successful build artifact. **Catches**: a vacuous "done" where the task named deliverables but nothing was actually built. ### `dbt-deliverable-names` After the agent declares done, compares the deliverable names the task document states literally against the model, seed and snapshot names the project actually defines, and refuses to terminate when a required name is absent. **Catches**: renames and self-chosen substitutes — the agent building something *like* the requested deliverable under a different name. ### `dbt-incremental-config` After the agent declares done, lints the incremental models the session edited for self-contradictory configuration: upsert semantics declared without a `unique_key`, a missing `is_incremental()` guard where the task demands idempotent re-runs, and non-deterministic functions inside the incremental predicate. **Catches**: incremental models that will silently duplicate or drop rows on re-run. ### `dbt-dialect-guard` After the agent declares done, flags warehouse-specific SQL functions used in the models the session edited without the project's prescribed `target.type` Jinja guard. Only active in projects that already establish the guard convention. **Catches**: dialect-specific SQL that runs on one warehouse but breaks on another. *Known limitation*: a call already wrapped in a `{% if target.type != '...' %}` branch is treated as guarded even when it is live on every other target — see the internal follow-up notes. ## Enabling validators Two opt-in modes: | Env var | Effect | | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ALTIMATE_VALIDATORS_ENABLED=1` | Full enforcement. Failing validators inject a synthetic user turn for the agent to fix (bounded by retries). | | `ALTIMATE_VALIDATORS_SHADOW=1` | Telemetry-only. Validators run and emit `validator_check` events (with `enforced: false`), but do **not** block the session. Use this to measure "would have caught a real bug" rates against production traffic. | Set in your shell, your `~/.altimate-code/altimate-code.json`'s `env` block, or in your CI runner config. Either flag is enough to activate the dispatch path; if neither is set the framework is completely inert. ```bash # Enforcement (blocks session on failure, with retries) export ALTIMATE_VALIDATORS_ENABLED=1 # Telemetry-only (no enforcement, no perf-blocking retry) export ALTIMATE_VALIDATORS_SHADOW=1 ``` ## Configuration knobs | Env var | Default | Meaning | | --------------------------------- | ----------- | ------------------------------------------------------------------------------- | | `ALTIMATE_VALIDATORS_ENABLED` | unset (off) | Master enforcement switch | | `ALTIMATE_VALIDATORS_SHADOW` | unset (off) | Telemetry-only mode | | `ALTIMATE_VALIDATORS_MAX_RETRIES` | `3` | How many synthetic-message retries per session before giving up | | `ALTIMATE_VALIDATORS_TIMEOUT_MS` | `60000` | Per-subprocess kill timeout (NaN/0/negative falls back to default) | | `ALTIMATE_VALIDATORS_CONCURRENCY` | `4` | Max concurrent `altimate-dbt` subprocesses (clamped to `items.length`) | | `ALTIMATE_VALIDATORS_DEBUG` | unset | When `1`, mirror dispatch diagnostics to stderr (file logs always include them) | ## Performance characteristics When **off** (default): zero cost — the dispatch returns immediately after the diagnostic log. When **on** in a dbt project: - Filesystem scan: 50–500 ms (walks up to 8 levels deep under the project root, stats every `.sql` file) - Per-model subprocess: 5–30 s each (`altimate-dbt test` or `altimate-dbt schema-verify`) - Concurrency cap of 4 → worst case `ceil(N/4) × 30 s` for N modified models - 5 touched models ≈ 1–2 minutes of "agent said done, you're still waiting" For interactive sessions, this is real latency. For batch / CI use the trade-off is usually worth it because correctness wins over a minute of wall time. ## Telemetry When validators run (either mode), they emit one `validator_check` event per applied validator: ```json { "type": "validator_check", "session_id": "...", "validator_name": "dbt-tests-pass", "ok": true, "step": 12, "retry_count": 0, "enforced": true, "details": { "models_touched": 3, "checked": 3, "dbt_root": "/code/work/my-dbt-project", "elapsed_ms": 14523, "concurrency_limit": 4 } } ``` When `ALTIMATE_VALIDATORS_ENABLED=1` retries are exhausted with outstanding failures, a `validator_retries_exhausted` event marks the session as completed-with-unresolved-validator-failures. See [Telemetry reference](https://help.altimate.ai/code/reference/telemetry/index.md) for the event catalogue and what's collected. ## Result shape When a validator runs, it returns: ```ts { ok: boolean reason?: string // human-readable failure summary fixHint?: string // the body injected into the synthetic user turn details: { models_touched: number dbt_root: string | null session_id: string elapsed_ms: number // present only when at least one model was touched: checked?: number concurrency_limit?: number // validator-specific extras: // dbt-tests-pass: passed?: number failed?: number errored?: number spawn_failures?: number failing_models?: string[] errored_models?: string[] // dbt-schema-verify: verified?: number match?: number mismatch?: number no_spec?: number mismatch_models?: string[] } } ``` `reason` names the failing models inline (e.g. `"2 of 3 models you edited have a column-shape mismatch against schema.yml: foo, bar"`). ## Phased rollout plan The framework is intentionally opt-in until we have: 1. **Sufficient shadow telemetry** — "would have caught a real bug" rate well above "false positive" rate, against representative traffic. 1. **Build / schema-verify sync resolved** — currently a freshly-built model can briefly report `mismatch` while `altimate-dbt`'s manifest catches up; enabling by default would block sessions where the agent did the right thing. 1. **Coverage gaps closed** — custom `model-paths` (anything other than `models/`), Python models (`.py`), and workspace projects nested below the first subdirectory are not currently detected. 1. **Performance**: today the dispatch is synchronous on session end. For interactive UX we want to either move it to a background job that the agent can `await` only when needed, or surface progress to the user. Once those are met, validators will be opt-out for dbt projects and default-on. Track progress in [#849](https://github.com/AltimateAI/altimate-code/pull/849). ## Known limitations - Only `.sql` model files inside a `models/` ancestor are scanned (case-insensitive). Python models (`.py`, dbt 1.3+) and custom `model-paths` are not. - `findDbtProjectRoot` checks the cwd and one level of subdirectories, skipping `.hidden`, `node_modules`, `target`. Projects nested deeper (workspace layouts) are not detected. - Multiple `dbt_project.yml` candidates pick the alphabetically-first match deterministically. - The validator surfaces "schema mismatch" even when the real cause is "model never materialized" — distinguishing these requires changes inside `altimate-dbt`. ## Writing custom validators The framework is generic — only the built-in two are dbt-specific. A validator is any object satisfying: ```ts interface Validator { name: string description: string appliesTo(ctx: ValidatorContext): Promise check(ctx: ValidatorContext): Promise } ``` Register it with `ValidatorRegistry.register(yourValidator)` at module load. The framework will then dispatch it on every gated turn. Keep `appliesTo` fast (it runs on every session end) and `check` idempotent (it may run multiple times across retries). See `packages/opencode/src/altimate/validators/dbt-tests-pass.ts` for a worked example. # Guides Practical guides for common data engineering workflows. | Guide | Description | | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | [Cost Optimization](https://help.altimate.ai/code/data-engineering/guides/cost-optimization/index.md) | Find and fix expensive queries, right-size warehouses | | [Migration](https://help.altimate.ai/code/data-engineering/guides/migration/index.md) | Translate SQL across warehouse dialects | | [Using with Claude Code](https://help.altimate.ai/code/data-engineering/guides/using-with-claude-code/index.md) | Run altimate tools from Claude Code sessions | | [Using with Codex](https://help.altimate.ai/code/data-engineering/guides/using-with-codex/index.md) | Use your ChatGPT subscription as the LLM backend | | [ClickHouse](https://help.altimate.ai/code/data-engineering/guides/clickhouse/index.md) | ClickHouse-specific workflows: MergeTree optimization, materialized views, dialect translation, dbt integration | # ClickHouse Guide Altimate Code has first-class ClickHouse support — connect to self-hosted clusters, ClickHouse Cloud, or local Docker instances and use the full suite of SQL analysis, schema inspection, and optimization tools. ## Quick Start ### 1. Connect ```bash # Add a local ClickHouse > warehouse_add my-clickhouse {"type": "clickhouse", "host": "localhost", "port": 8123, "database": "analytics"} # Or ClickHouse Cloud > warehouse_add ch-cloud {"type": "clickhouse", "host": "abc.clickhouse.cloud", "port": 8443, "protocol": "https", "user": "default", "password": "..."} ``` ### 2. Verify ```bash > warehouse_test my-clickhouse ✓ Connected successfully ``` ### 3. Explore ```bash > "Show me all tables in my ClickHouse analytics database" > "Describe the events table schema" ``` ## What Can Altimate Code Do for ClickHouse Users? ### Analyze Query Performance ClickHouse queries can be deceptively fast — until they scan terabytes. Altimate Code can analyze your queries and spot issues. ```text > "Analyze this query for performance issues" SELECT user_id, count() FROM events WHERE toDate(timestamp) = today() GROUP BY user_id ORDER BY count() DESC # Altimate Code spots: # ⚠ toDate(timestamp) prevents partition pruning — use timestamp >= toStartOfDay(now()) # ⚠ No LIMIT clause — consider adding LIMIT for large result sets # ✓ GROUP BY + ORDER BY is efficient with MergeTree ``` ### Optimize MergeTree Table Design The choice of `ORDER BY` key, partitioning, and engine variant dramatically affects ClickHouse performance. Altimate Code understands these nuances. ```text > "Review my table design for the events table" # Altimate Code analyzes: # - ORDER BY key alignment with common query patterns # - Partition granularity (too fine = too many parts, too coarse = slow scans) # - Column types (String vs LowCardinality, DateTime vs DateTime64) # - Engine choice (MergeTree vs ReplacingMergeTree vs AggregatingMergeTree) ``` ### Translate SQL Across Dialects Moving from PostgreSQL, BigQuery, or Snowflake to ClickHouse? Altimate Code translates SQL between dialects. ```text > "Translate this Snowflake query to ClickHouse" -- Snowflake SELECT DATE_TRUNC('month', created_at) AS month, APPROX_COUNT_DISTINCT(user_id) AS unique_users FROM events WHERE created_at >= DATEADD('month', -6, CURRENT_TIMESTAMP()) GROUP BY 1 -- ClickHouse (translated) SELECT toStartOfMonth(created_at) AS month, uniqHLL12(user_id) AS unique_users FROM events WHERE created_at >= subtractMonths(now(), 6) GROUP BY month ORDER BY month ``` ### Inspect Schema & Lineage ```text > "What are the columns in the events table?" > "Show me column-level lineage for the daily_metrics materialized view" > "Which tables reference the users table?" ``` ### Monitor Cluster Health via system Tables ClickHouse exposes rich operational data in `system.*` tables. Altimate Code can query them for you. ```text > "Show me the top 10 slowest queries in the last hour" > "How many parts does the events table have? Is it healthy?" > "What's the current merge activity?" > "Show disk usage by table" ``` ### Write and Debug ClickHouse SQL ClickHouse SQL has unique features — `arrayJoin`, `WITH FILL`, window functions over `ORDER BY` tuples, `PREWHERE`, and more. Altimate Code understands them natively. ```text > "Write a query that uses arrayJoin to explode the tags array in the events table and count occurrences" SELECT tag, count() AS cnt FROM events ARRAY JOIN tags AS tag GROUP BY tag ORDER BY cnt DESC LIMIT 20 ``` ### dbt + ClickHouse If you use dbt with the [dbt-clickhouse adapter](https://github.com/ClickHouse/dbt-clickhouse), Altimate Code detects your dbt project and ClickHouse profile automatically. ```text > /discover ## dbt Project ✓ Project "analytics" (profile: clickhouse_prod) ## Warehouse Connections ### From dbt profiles.yml Name | Type | Source dbt_clickhouse | clickhouse | dbt-profile ``` All dbt skills work with ClickHouse: - `/dbt-develop` — develop new models with ClickHouse-aware SQL - `/dbt-troubleshoot` — debug dbt run failures - `/dbt-analyze` — analyze model performance ### Materialized View Pipelines ClickHouse materialized views are real-time transformation pipelines. Altimate Code helps design and debug them. ```text > "Help me create a materialized view that aggregates events into hourly metrics" CREATE TABLE analytics.hourly_metrics ( hour DateTime, event_type LowCardinality(String), total UInt64, unique_users AggregateFunction(uniq, UInt64) ) ENGINE = AggregatingMergeTree() PARTITION BY toYYYYMM(hour) ORDER BY (hour, event_type); CREATE MATERIALIZED VIEW analytics.hourly_metrics_mv TO analytics.hourly_metrics AS SELECT toStartOfHour(timestamp) AS hour, event_type, count() AS total, uniqState(user_id) AS unique_users FROM analytics.events GROUP BY hour, event_type; ``` ## ClickHouse-Specific Tips ### LowCardinality for Repeated Strings ```text > "Which String columns in my events table should use LowCardinality?" # Altimate Code checks cardinality: # ✓ event_type — 47 distinct values → use LowCardinality(String) # ✓ country — 195 distinct values → use LowCardinality(String) # ✗ user_agent — 12M distinct values → keep as String ``` ### Partition Pruning ```text > "Is my events query using partition pruning?" # Altimate Code checks EXPLAIN output and warns if: # - WHERE clause doesn't match partition key # - Date functions prevent pruning (e.g., toDate(ts) vs ts >= ...) ``` ### Codec Selection ```text > "Suggest compression codecs for my events table columns" # Altimate Code recommends based on data patterns: # timestamp — Delta + ZSTD (monotonic timestamps) # user_id — ZSTD (random integers) # event_type — LowCardinality is better than codec here # payload — ZSTD(3) (JSON strings, higher ratio) ``` ## Version Compatibility Altimate Code supports all non-EOL ClickHouse server versions: | Version | Type | Status | | ------- | ------ | ---------- | | 25.x | Stable | Supported | | 24.8 | LTS | Supported | | 24.3 | LTS | Supported | | 23.8 | LTS | Supported | | < 23.3 | EOL | Not tested | The driver uses the official `@clickhouse/client` package which communicates over HTTP(S), ensuring compatibility across versions and deployment models (self-hosted, ClickHouse Cloud, Altinity.Cloud). ## Auto-Discovery Altimate Code automatically detects ClickHouse from: | Source | Detection | | ------------------------- | --------------------------------------------- | | **dbt profiles** | `type: clickhouse` in `~/.dbt/profiles.yml` | | **Docker containers** | Running `clickhouse/clickhouse-server` images | | **Environment variables** | `CLICKHOUSE_HOST` or `CLICKHOUSE_URL` | # Cost Optimization Guide altimate is your cost advocate. Here's how to use it to cut warehouse spend. ## Step 1: Find where money is going ```text You: What's driving our Snowflake costs? > finops_analyze_credits prod-snowflake --days 30 > finops_expensive_queries prod-snowflake --days 30 --limit 20 ``` This gives you: - Credit breakdown by warehouse, user, and time - Top 20 most expensive queries with anti-pattern flags - Trend data (are costs increasing?) ## Step 2: Fix the worst offenders For each expensive query, the agent automatically runs `sql_analyze` to find anti-patterns: ### SELECT * → explicit columns **Before:** 89.3 credits/week ```sql SELECT * FROM events e JOIN users u ON e.user_id = u.id ``` **After:** ~25 credits/week (72% savings) ```sql SELECT e.event_id, e.event_type, e.created_at, u.name, u.email FROM events e JOIN users u ON e.user_id = u.id ``` ### Missing date filter on partitioned tables **Before:** 45.1 credits (full table scan) ```sql SELECT DISTINCT customer_id FROM orders WHERE status = 'active' ``` **After:** ~2.3 credits (95% savings) ```sql SELECT DISTINCT customer_id FROM orders WHERE status = 'active' AND order_date >= DATEADD(day, -90, CURRENT_DATE()) ``` ### Non-sargable predicates **Before:** Scans entire column, can't use clustering ```sql WHERE YEAR(order_date) = 2026 ``` **After:** Enables partition pruning ```sql WHERE order_date >= '2026-01-01' AND order_date < '2027-01-01' ``` ## Step 3: Right-size warehouses ```text You: Are our warehouses the right size? > finops_warehouse_advice prod-snowflake --days 14 ``` Common findings: - **Over-provisioned warehouses.** Utilization below 30% means you're paying for idle compute. - **Missing auto-suspend.** Warehouses running 24/7 when only used during business hours. - **Wrong size for workload.** Small queries on XL warehouses waste credits. ## Step 4: Clean up unused resources ```text You: What tables and warehouses are unused? > finops_unused_resources prod-snowflake --days 30 ``` This finds: - Tables with no reads in 30+ days (costing storage) - Warehouses with no queries in 7+ days - Temporary tables from old migrations ## Quick wins checklist | Action | Typical savings | Effort | | ------------------------------------------ | ---------------- | ------ | | Replace SELECT * with explicit columns | 50-80% per query | Low | | Add date filters to large table scans | 80-95% per query | Low | | Fix non-sargable WHERE clauses | 30-60% per query | Low | | Downsize over-provisioned warehouses | 30-50% monthly | Medium | | Enable auto-suspend (1 min) | 10-20% monthly | Low | | Drop unused tables | Storage savings | Low | | Materialized views for repeated queries | 90%+ per query | Medium | | Incremental models instead of full refresh | 50-90% per run | Medium | # Data Parity (Table Diff) Validate that two tables — or two query results — are identical across databases, or diagnose exactly how they differ. Use for **migration validation**, **ETL regression**, and **query refactor verification**. altimate-code ships a dedicated `data_diff` tool and a `data-parity` skill that orchestrates the full workflow: plan, inspect schema, confirm keys, profile, then diff. ## Supported warehouse pairs Works across any combination of: - PostgreSQL - Snowflake - BigQuery - Databricks (SQL Warehouses) - ClickHouse - MySQL - Redshift - SQL Server - Microsoft Fabric - DuckDB - SQLite - Oracle Same-dialect comparisons use a fast FULL OUTER JOIN. Cross-database comparisons use a bisection hashing algorithm that streams checksums rather than raw rows — so you can diff a 100M-row Postgres table against its Snowflake replica without pulling the data out. ## Quick start ```bash altimate ``` In the TUI, just describe what you want to compare: ```text Compare orders in postgres_prod with orders in snowflake_dw using id as the primary key. ``` The agent will: 1. List your warehouse connections. 1. Inspect both schemas, propose primary keys, and flag audit/timestamp columns to exclude. 1. Confirm your choices. 1. Run a column profile first (cheap — no row scan). 1. Run the row-level diff only on columns that diverged. ## Algorithms | Algorithm | When to use | Cost | | ---------- | ---------------------------------------------------------------------------------------------- | -------------------------------- | | `auto` | Default. Picks JoinDiff for same-dialect, HashDiff for cross-database. | Cheapest valid choice | | `joindiff` | Same-database comparison. Fast. | One FULL OUTER JOIN | | `hashdiff` | Cross-database. Works at any scale. | Bisection over checksums | | `profile` | Compliance-safe. Column stats only — no row values leave the database. | Cheapest | | `cascade` | Profile first, then HashDiff on columns that diverged. Balanced default for exploratory diffs. | Column stats + targeted row diff | ## Partitioning large tables For tables beyond ~10M rows, partition the diff into independent batches: ```text Compare orders between postgres and snowflake, partitioned by order_date month. ``` Three partition modes: | Mode | How to trigger | Example | | --------------- | ---------------------------------------------------- | ----------------------------- | | **Date** | Set `partition_column` + `partition_granularity` | `l_shipdate` + `month` | | **Numeric** | Set `partition_column` + `partition_bucket_size` | `l_orderkey` + `100000` | | **Categorical** | Set `partition_column` alone (no granularity/bucket) | `region`, `status`, `country` | Each partition is diffed independently. Results are aggregated with a per-partition breakdown so you can see *which* groups have differences. ## SQL Server and Microsoft Fabric Both `sqlserver` and `fabric` are supported. For Azure AD / Entra ID authentication, altimate-code recognizes all of the major flows through `tedious`: | `authentication` | Config fields | Use case | | --------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------- | | `azure-active-directory-password` | `azure_client_id`, `azure_tenant_id`, `user`, `password` | User credentials | | `azure-active-directory-access-token` (or `access-token`) | `access_token` | Pre-fetched token | | `service-principal-secret` (`service-principal`) | `azure_tenant_id`, `azure_client_id`, `azure_client_secret` | Service principals | | `azure-active-directory-msi-vm` (`msi`) | `azure_client_id` (optional) | Azure VM managed identity | | `azure-active-directory-msi-app-service` | `azure_client_id` (optional) | App Service managed identity | | `azure-active-directory-default` (`default` / `CLI`) | — | DefaultAzureCredential chain (CLI, env, MSI) | All Azure AD connections force TLS encryption. ## Compliance and sensitive data PII / PHI / PCI data `data_diff` prints up to 5 sample diff rows in tool output. Those rows become part of the conversation and are sent to your LLM provider. When comparing tables that might contain regulated data: - Start with `algorithm: "profile"` — column-level statistics only, no row values leave the database. - If a row-level diff is genuinely required, scope it with a `where_clause` that excludes sensitive customers / accounts. - The `data-parity` skill asks for confirmation before sending sample rows to the LLM when the table name matches common regulated patterns (`customers`, `patients`, `orders`, `payments`, `accounts`, `users`). ## Column auto-discovery and audit exclusion When you omit `extra_columns` and the source is a plain table name, altimate-code: 1. Queries `information_schema` (or the dialect-specific equivalent) on both sides. 1. Excludes audit/timestamp columns by name pattern (`updated_at`, `created_at`, `_fivetran_synced`, `_airbyte_emitted_at`, etc.). 1. Queries column defaults and excludes anything with an auto-generating timestamp default (`NOW()`, `CURRENT_TIMESTAMP`, `GETDATE()`, `SYSDATE`, `SYSTIMESTAMP`). 1. Reports excluded columns so you can override if the timestamps are part of what you're validating. When the source is a SQL query, only the key columns are compared unless you explicitly list `extra_columns`. Always provide `extra_columns` for query-mode comparisons. ## The `data_diff` tool Direct tool invocation (if you prefer not to use the skill): ```text data_diff( source = "orders", target = "orders", source_warehouse = "postgres_prod", target_warehouse = "snowflake_dw", key_columns = ["id"], algorithm = "auto", ) ``` See the [tool reference](https://help.altimate.ai/code/data-engineering/tools/warehouse-tools/index.md) for the full parameter list. # Migration Guide Use altimate to translate SQL across warehouse dialects while preserving lineage and correctness. ## Start a migration ```bash altimate --agent builder ``` ## Translation workflow ### 1. Identify source dialect and target ```text You: Migrate our Snowflake models to BigQuery Builder: I'll translate each model and verify lineage is preserved. Let me start by listing your models. > dbt_manifest ./target/manifest.json 47 models found ``` ### 2. Translate with verification For each model, the agent: 1. **Reads** the source SQL 1. **Translates** to target dialect 1. **Checks lineage** on both versions to ensure they match 1. **Validates** the translated SQL against target schema ```text > sql_translate --source snowflake --target bigquery [model SQL] Snowflake → BigQuery translations applied: DATEADD(day, -7, x) → DATE_SUB(x, INTERVAL 7 DAY) IFF(cond, a, b) → IF(cond, a, b) TRY_TO_NUMBER(x) → SAFE_CAST(x AS NUMERIC) FLATTEN(array_col) → UNNEST(array_col) table_name → `table_name` (backtick quoting) QUALIFY clause → QUALIFY clause (supported in BQ) > lineage_check [source SQL] > lineage_check [translated SQL] ✓ Lineage preserved — 4 source columns → 4 target columns ``` ### 3. Handle dialect-specific features Some features don't have direct equivalents: | Snowflake | BigQuery | Notes | | --------------------- | ------------------- | ---------------------------------- | | `VARIANT` type | `JSON` or `STRUCT` | Manual mapping may be needed | | `LATERAL FLATTEN` | `UNNEST` | Different syntax, same result | | `$1, $2` (positional) | Named columns | Requires column naming | | `MERGE` | `MERGE` | Syntax differences in WHEN clauses | | `COPY INTO` | `LOAD DATA` | Different bulk load approach | | `STREAMS` | Change Data Capture | Architectural difference | | `TASKS` | Scheduled queries | Different scheduling model | ### 4. Validate at scale ```text You: Run all translations and report issues Builder: ✓ 38/47 models translated cleanly ⚠ 6 models need manual review (VARIANT columns) ✗ 3 models use Snowflake-specific features (STREAMS, TASKS) Manual review needed: models/staging/stg_events.sql — VARIANT column parsing models/staging/stg_api_logs.sql — PARSE_JSON usage ... ``` ## Common translation patterns ### Snowflake → BigQuery ```sql -- Snowflake SELECT DATEADD(month, -3, CURRENT_TIMESTAMP()) AS three_months_ago, IFF(amount > 100, 'high', 'low') AS tier, LISTAGG(tag, ', ') WITHIN GROUP (ORDER BY tag) AS tags, TRY_TO_DECIMAL(raw_price, 10, 2) AS price, OBJECT_CONSTRUCT('key', value) AS json_obj FROM my_schema.my_table QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY ts DESC) = 1; -- BigQuery (translated) SELECT DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 3 MONTH) AS three_months_ago, IF(amount > 100, 'high', 'low') AS tier, STRING_AGG(tag, ', ' ORDER BY tag) AS tags, SAFE_CAST(raw_price AS DECIMAL) AS price, STRUCT(value AS key) AS json_obj FROM `my_schema.my_table` QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY ts DESC) = 1; ``` ### Snowflake → Databricks ```sql -- Snowflake SELECT DATEADD(day, -7, CURRENT_TIMESTAMP()), DATEDIFF(hour, start_ts, end_ts), TRY_CAST(x AS INTEGER), ARRAY_AGG(DISTINCT val) WITHIN GROUP (ORDER BY val) FROM table WHERE RLIKE(email, '^[a-z]+@.*$'); -- Databricks (translated) SELECT DATEADD(DAY, -7, CURRENT_TIMESTAMP()), DATEDIFF(HOUR, start_ts, end_ts), TRY_CAST(x AS INT), ARRAY_AGG(DISTINCT val) FROM table WHERE RLIKE(email, '^[a-z]+@.*$'); ``` ## Best practices 1. **Translate in batches.** Start with staging models, then intermediate, then marts. 1. **Verify lineage.** Always check that column lineage is preserved after translation. 1. **Test with LIMIT.** Run translated queries with `LIMIT 10` on the target warehouse first. 1. **Check data types.** Type mappings may lose precision (e.g., `NUMBER(38,0)` to `INT64`). 1. **Handle NULL semantics.** Some warehouses handle NULLs differently in comparisons. # Using altimate with Claude Code altimate can work alongside Claude Code. While Claude Code handles general coding tasks, altimate provides specialized data engineering capabilities that Claude Code doesn't have. ## How it works Claude Code can invoke altimate as a tool when working on data projects. The `/altimate` command routes data engineering tasks to altimate's specialized tools. ```text # In Claude Code /altimate analyze the cost of our Snowflake warehouse ``` This gives Claude Code access to: - SQL analysis and anti-pattern detection - Column-level lineage - Cost prediction and FinOps analysis - Schema inspection and PII detection - dbt manifest parsing and model scaffolding - Cross-dialect SQL translation ## Example workflows ### Code review with cost analysis When Claude Code reviews a PR that includes SQL changes: ```text Claude Code: I see changes to models/marts/fct_revenue.sql. Let me check for data engineering concerns. > /altimate analyze fct_revenue.sql for anti-patterns and estimate cost altimate: sql_analyze: No anti-patterns detected ✓ lineage_check: Sources stg_orders.amount, dim_products.category schema_diff: Added column revenue_category (low severity) ``` ### dbt project setup ```text You (in Claude Code): Set up a new dbt model for our customer metrics Claude Code: I'll create the model structure. Let me use altimate to inspect the source tables first. > /altimate inspect the raw.customers and raw.orders tables altimate: schema_inspect raw.customers → 12 columns schema_inspect raw.orders → 8 columns lineage_check [draft SQL] → verified column mappings Claude Code: Here's the staging model based on the actual schema... ``` ### FinOps during development ```text You (in Claude Code): This query is slow, can you optimize it? Claude Code: Let me analyze it with altimate's SQL tools. > /altimate analyze and optimize: SELECT * FROM events WHERE YEAR(event_date) = 2026 altimate: sql_analyze: ⚠ SELECT_STAR: Use explicit columns ⚠ FUNCTION_IN_FILTER: YEAR() prevents partition pruning sql_optimize: Optimized: explicit columns + range predicate Estimated improvement: 70-80% fewer bytes scanned ``` ## Setup 1. Install altimate globally: `npm install -g altimate-code` 1. Configure warehouse connections in your project 1. Run `/configure-claude` inside altimate to set up the integration: ```bash altimate # then in the TUI: /configure-claude ``` This creates `~/.claude/commands/altimate.md`. You can now use `/altimate` in any Claude Code session. ## When to use which | Task | Use Claude Code | Use altimate | | -------------------------- | --------------- | --------------------------- | | Writing Python/JS code | Yes | No | | SQL anti-pattern detection | No | Yes | | Column-level lineage | No | Yes | | Cost prediction | No | Yes | | FinOps analysis | No | Yes | | Schema inspection | No | Yes | | dbt model scaffolding | Partially | Yes (better) | | Cross-dialect translation | No | Yes | | PII detection | No | Yes | | General code review | Yes | Supplement with data checks | | File editing | Yes | Yes (in builder mode) | # Using altimate with Codex altimate integrates with Codex in two ways: as an **LLM provider** (use your ChatGPT subscription to power altimate) and as a **Codex skill** (invoke altimate from within Codex CLI). ## Using altimate as a Codex CLI skill You can delegate data engineering tasks from Codex CLI to altimate. Run `/configure-codex` inside altimate to set up the integration: ```text /configure-codex ``` This creates `~/.codex/skills/altimate/SKILL.md`. Restart Codex to pick up the new skill. Codex will then automatically invoke altimate when you ask about data engineering tasks like SQL analysis, lineage, dbt, or FinOps. ## Using Codex as an LLM provider If you have a ChatGPT Plus or Pro subscription, you can use Codex as your LLM backend in altimate at no additional API cost. Your subscription covers all usage. ## Setup ### 1. Launch altimate ```bash altimate ``` ### 2. Run /connect In the TUI, type `/connect` and select **Codex** as your provider. ### 3. Authenticate A browser window opens for OAuth authentication with your ChatGPT account. Sign in and authorize altimate. For headless environments (SSH, containers), a device code flow is available: ```text Visit: https://chatgpt.com/device Enter code: ABCD-1234 ``` ### 4. Start using Once authenticated, all altimate tools work with Codex as the LLM backend. No API keys needed. ## Available models | Model | Best for | | -------------------- | ------------------------------- | | `gpt-5.2-codex` | General data engineering tasks | | `gpt-5.1-codex-max` | Complex analysis, large context | | `gpt-5.1-codex-mini` | Fast, lightweight tasks | | `gpt-5.3-codex` | Latest capabilities | ## How it works - altimate authenticates via PKCE OAuth flow with ChatGPT - Requests route through `chatgpt.com/backend-api/codex/responses` - Your subscription covers all token usage, so there is no per-token billing - Token is stored locally at `~/.altimate/data/auth.json` ## Cost With Codex subscription: - **LLM cost**: $0 (covered by subscription) - **Warehouse cost**: Normal warehouse credits apply for SQL execution - altimate helps minimize warehouse costs through cost prediction and optimization ## Comparison with API keys | Aspect | Codex Subscription | API Key (Anthropic/OpenAI) | | --------------- | ------------------------- | -------------------------- | | Monthly cost | $20-200/mo (subscription) | Pay per token | | Setup | OAuth (browser login) | Copy-paste API key | | Rate limits | Subscription limits | API limits | | Model selection | Codex models only | Full model catalog | | Best for | Individual developers | Teams, CI/CD | ## Troubleshooting **"OAuth token expired"** - Run `/connect` again to re-authenticate **"Rate limit exceeded"** - Codex subscription has usage limits. Wait a few minutes or upgrade your plan. **"Codex not available"** - Ensure you have an active ChatGPT Plus or Pro subscription - Check that Codex is available in your region # Tools Reference altimate has 100+ specialized tools organized by function. | Category | Tools | Purpose | | ------------------------------------------------------------------------------------------------ | ------------------ | ---------------------------------------------------------------------------------- | | [SQL Tools](https://help.altimate.ai/code/data-engineering/tools/sql-tools/index.md) | 12 tools | Analysis, optimization, translation, formatting, cost prediction | | [Schema Tools](https://help.altimate.ai/code/data-engineering/tools/schema-tools/index.md) | 7 tools | Inspection, search, PII detection, tagging, diffing | | [FinOps Tools](https://help.altimate.ai/code/data-engineering/tools/finops-tools/index.md) | 8 tools | Cost analysis, warehouse sizing, unused resources, RBAC | | [Lineage Tools](https://help.altimate.ai/code/data-engineering/tools/lineage-tools/index.md) | 1 tool | Column-level lineage tracing with confidence scoring | | [dbt Tools](https://help.altimate.ai/code/data-engineering/tools/dbt-tools/index.md) | 3 tools + 6 skills | Run, manifest parsing, unit test generation, scaffolding, `altimate-dbt` CLI | | [Warehouse Tools](https://help.altimate.ai/code/data-engineering/tools/warehouse-tools/index.md) | 6 tools | Environment scanning, connection management, discovery, testing | | [Altimate Memory](https://help.altimate.ai/code/data-engineering/tools/memory-tools/index.md) | 3 tools | Persistent cross-session memory for warehouse config, conventions, and preferences | | [Training](https://help.altimate.ai/code/data-engineering/training/index.md) | 3 tools + 3 skills | Correct the agent once, it remembers forever, your team inherits it | | `tool_lookup` | 1 tool | Runtime introspection that discovers tool schemas and parameters dynamically | All tools are available in the interactive TUI. The agent automatically selects the right tools based on your request. # dbt Tools ## dbt_run Execute dbt commands from within the agent. ```text > dbt_run --command run --select stg_orders Running: dbt run --select stg_orders ✓ stg_orders .................. [OK in 2.3s] 1 model completed successfully. ``` **Parameters:** - `command` (optional, default: "run"): dbt command: `run`, `test`, `build`, `compile`, `seed`, `snapshot` - `select` (optional): Model selection syntax (`stg_orders`, `+fct_revenue`, `tag:daily`) - `args` (optional): Additional CLI arguments - `project_dir` (optional): Path to dbt project root ### Examples ```text > dbt_run --command test --select stg_orders ✓ not_null_stg_orders_order_id ........ [PASS in 1.1s] ✓ unique_stg_orders_order_id .......... [PASS in 0.8s] ✓ relationships_stg_orders_customer_id [PASS in 1.3s] 3 tests passed. ``` ```text > dbt_run --command compile --select fct_revenue Compiled SQL written to target/compiled/models/marts/fct_revenue.sql ``` ```text > dbt_run --command build --select +fct_revenue Running upstream models, tests, and fct_revenue... ✓ stg_orders ............... [OK in 2.1s] ✓ stg_payments ............. [OK in 1.8s] ✓ fct_revenue .............. [OK in 3.4s] ✓ 5 tests .................. [PASS] ``` ______________________________________________________________________ ## dbt_manifest Parse a dbt manifest.json to understand project structure. ```text > dbt_manifest ./target/manifest.json Project Summary: Models: 47 (12 staging, 8 intermediate, 15 marts, 12 other) Sources: 12 (across 3 databases) Tests: 89 Seeds: 3 Snapshots: 2 Model Dependencies: fct_revenue depends on: stg_orders, stg_payments, dim_products fct_orders depends on: stg_orders, stg_customers, dim_dates Source Freshness: raw.orders — loaded hourly raw.customers — loaded daily raw.products — loaded weekly ``` ______________________________________________________________________ ## dbt_unit_test_gen Generate dbt unit tests (v1.8+) from a compiled manifest. Analyzes model SQL for testable logic (CASE/WHEN, JOINs, NULLs, window functions, division, incremental), generates type-correct mock inputs, and assembles complete YAML. ```text > dbt_unit_test_gen --manifest_path target/manifest.json --model fct_orders --max_scenarios 5 Unit Test Gen: 4 test(s) for fct_orders === Unit Test Generation Summary === Model: fct_orders Description: "Daily order totals by order ID" Materialization: table Upstream dependencies: 2 Tests generated: 4 === Upstream Dependencies === ref('stg_orders') Staged orders from raw source Columns: order_id (INTEGER) — Primary key for orders quantity (INTEGER) — Number of items ordered unit_price (NUMERIC) — Price per unit in USD === Column Lineage (output ← inputs) === order_total ← stg_orders.quantity, stg_orders.unit_price === YAML (paste into schema.yml) === unit_tests: - name: test_fct_orders_happy_path description: Verify correct output for standard input data model: fct_orders given: - input: ref('stg_orders') rows: - { order_id: 1, quantity: 3, unit_price: 100 } - { order_id: 2, quantity: 1, unit_price: 50 } expect: rows: - { order_id: 1, order_total: 300 } - { order_id: 2, order_total: 50 } # ... null_handling, edge_case, incremental tests ``` **Parameters:** - `manifest_path` (required): Path to compiled `manifest.json` (run `dbt compile` first) - `model` (required): Model name or unique_id (e.g. `fct_orders` or `model.project.fct_orders`) - `dialect` (optional): SQL dialect override (auto-detected from manifest adapter_type) - `max_scenarios` (optional, default 3): Maximum number of test scenarios to generate **What it generates:** - **Scenarios:** `happy_path`, `null_handling` (for CASE/COALESCE), `edge_case` (for JOINs, window functions, division), `incremental` (for incremental models with `input: this` mock) - **Mock data:** Type-correct values from dialect-aware type mapping (Snowflake, BigQuery, Postgres, Redshift, Databricks, DuckDB, MySQL) - **Dependencies:** Handles `ref()` for models/seeds/snapshots, `source()` for raw tables, `format: sql` for ephemeral models - **Context:** Returns model/column descriptions, column lineage, and compiled SQL for the LLM to refine test values **Skill:** `/dbt-unit-tests` — 5-phase workflow (Analyze → Generate → Refine → Validate → Write) with reference guides for YAML spec, edge-case patterns, and incremental testing. **Important:** The tool generates scaffold tests with type-correct placeholder values. The LLM skill layer refines expected outputs by running SQL against mock data — always review and verify before committing. ______________________________________________________________________ ## altimate-dbt CLI `altimate-dbt` is a standalone CLI for dbt workflows. It auto-detects your dbt project directory, Python environment, and adapter type (Snowflake, BigQuery, Databricks, Redshift, etc.). ```bash # Initialize dbt integration altimate-dbt init # Diagnose issues altimate-dbt doctor # Run dbt commands altimate-dbt compile altimate-dbt build altimate-dbt run altimate-dbt test # Utilities altimate-dbt execute "SELECT 1" # Run a query via dbt adapter altimate-dbt columns my_model # List model columns altimate-dbt graph # View lineage/DAG altimate-dbt deps # Manage dependencies ``` All commands provide friendly error diagnostics with actionable fix suggestions when something goes wrong. > **Tip:** In builder mode, the agent prefers `altimate-dbt` over the raw `dbt_run` tool for better error handling and auto-detection. ______________________________________________________________________ ## dbt Skills ### /dbt-unit-tests Automated dbt unit test generation (v1.8+). Uses `dbt_unit_test_gen` to produce scaffold YAML, then refines expected outputs by reading the compiled SQL and running it against the mock data. ```text You: /dbt-unit-tests fct_orders > dbt_unit_test_gen --manifest_path target/manifest.json --model fct_orders > altimate-dbt test --select fct_orders Generated 4 unit tests for fct_orders: ✓ test_fct_orders_happy_path ✓ test_fct_orders_null_handling ✓ test_fct_orders_edge_case_1 (division) ✓ test_fct_orders_incremental All tests passing. YAML written to models/marts/_unit_tests.yml. ``` Workflow: Analyze → Generate → Refine → Validate → Write. See [reference guides](https://github.com/AltimateAI/altimate-code/tree/main/.opencode/skills/dbt-unit-tests/references) for edge-case patterns and incremental testing. ### /generate-tests Auto-generate dbt test definitions from table metadata. ```text You: /generate-tests models/staging/stg_orders.sql > schema_inspect stg_orders > lineage_check [stg_orders SQL] Generated tests for schema.yml: models: - name: stg_orders columns: - name: order_id tests: - not_null - unique - name: customer_id tests: - not_null - relationships: to: ref('stg_customers') field: customer_id - name: order_amount tests: - not_null - dbt_utils.accepted_range: min_value: 0 - name: order_status tests: - accepted_values: values: ['pending', 'shipped', 'delivered', 'cancelled'] ``` ### /model-scaffold Scaffold dbt models following medallion architecture. ```text You: /model-scaffold orders from raw.raw_orders Generated files: models/staging/stg_orders.sql models/staging/stg_orders.yml models/intermediate/int_orders_enriched.sql models/marts/fct_orders.sql models/marts/fct_orders.yml ``` ### /yaml-config Generate sources.yml from warehouse schema. ```text You: /yaml-config for raw schema tables > schema_search --schema RAW Generated models/staging/sources.yml: sources: - name: raw database: ANALYTICS schema: RAW tables: - name: raw_orders loaded_at_field: _loaded_at freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} - name: raw_customers loaded_at_field: _loaded_at - name: raw_products ``` ### /dbt-docs Generate model and column descriptions. ```text You: /dbt-docs models/marts/fct_revenue.sql > lineage_check [fct_revenue SQL] > schema_inspect [source tables] Generated description: models: - name: fct_revenue description: > Monthly revenue fact table aggregating order amounts by product category. Grain: one row per product category per month. Sources: stg_orders, dim_products columns: - name: revenue_month description: "First day of the month (truncated from order_date)" - name: product_category description: "Product category from dim_products" - name: total_revenue description: "Sum of order_amount for the category/month" - name: order_count description: "Count of distinct orders" ``` ### /incremental-logic Generate incremental materialization strategies. ```text You: /incremental-logic for fct_orders Recommended strategy: merge (upsert) {{ config( materialized='incremental', unique_key='order_id', incremental_strategy='merge', on_schema_change='append_new_columns' ) }} SELECT order_id, customer_id, order_amount, order_status, updated_at FROM {{ ref('stg_orders') }} {% if is_incremental() %} WHERE updated_at > (SELECT MAX(updated_at) FROM {{ this }}) {% endif %} ``` ______________________________________________________________________ ## Completion-gate validators Beyond the agent-facing tools above, altimate-code ships **harness-side validators** that fire automatically after the agent declares done. They run `altimate-dbt test` and `altimate-dbt schema-verify` against every model modified during the session and block "done" if anything failed. This is **opt-in** today via either `ALTIMATE_VALIDATORS_ENABLED=1` (enforcement mode — failing validators block "done" with synthetic retries) or `ALTIMATE_VALIDATORS_SHADOW=1` (telemetry-only mode — runs without blocking, useful for measuring "would have caught" rates). When neither flag is set the dispatch path is completely skipped and there is zero overhead. See the [Validators page](https://help.altimate.ai/code/data-engineering/validators/index.md) for the full reference, env var catalogue, performance characteristics, and the phased rollout plan. # FinOps Tools Cost optimization and warehouse governance. These tools help you find where money is being wasted and fix it. v0.7.3+ — warehouse parameter is now optional Every `finops_*` tool used to require an explicit `warehouse=` argument. As of v0.7.3, the parameter is optional — if omitted, the tool auto-picks the first configured warehouse whose driver type supports the operation. Pass `warehouse=` explicitly when you have multiple compatible connections and want a specific one. The bare form (`finops_query_history --days 7`) works. ## finops_query_history Fetch recent query execution history from your warehouse. ```text > finops_query_history prod-snowflake --days 7 Recent Queries (top 10 by cost): ┌───┬──────────────────────────────────┬──────────┬────────┬───────────┬─────────┐ │ # │ Query (truncated) │ Credits │ Rows │ Duration │ Runs │ ├───┼──────────────────────────────────┼──────────┼────────┼───────────┼─────────┤ │ 1 │ SELECT * FROM events JOIN use... │ 89.3 │ 2.1B │ 4m 12s │ 47 │ │ 2 │ CREATE TABLE AS SELECT DISTIN... │ 45.1 │ 340M │ 12m 33s │ 1 │ │ 3 │ SELECT COUNT(DISTINCT user_id... │ 23.7 │ 890M │ 1m 45s │ 312 │ │ 4 │ INSERT INTO daily_agg SELECT... │ 18.2 │ 45M │ 3m 21s │ 7 │ │ 5 │ SELECT * FROM raw_clickstream...│ 12.8 │ 1.5B │ 2m 08s │ 3 │ └───┴──────────────────────────────────┴──────────┴────────┴───────────┴─────────┘ Summary: Total queries: 4,231 Total credits: 847.2 Avg credits/query: 0.20 ``` **Parameters:** - `warehouse` (optional, since v0.7.3): Connection name. If omitted, the first configured Snowflake / BigQuery / Databricks / PostgreSQL warehouse is auto-picked. - `days` (optional, default: 7): Lookback period - `limit` (optional, default: 100): Max queries returned - `user` (optional): Filter by username - `warehouse_filter` (optional, Snowflake-only): Filter the result rows by the in-warehouse compute name (different from the `warehouse` connection parameter). Use `warehouse` to pick which connection to query; use `warehouse_filter` to narrow which Snowflake virtual warehouse's queries appear in the output. **Data sources by warehouse:** - Snowflake: `QUERY_HISTORY` function - BigQuery: region-qualified `` `region-.INFORMATION_SCHEMA.JOBS` `` — the region is auto-resolved from the BigQuery connection's `location` (e.g. `us`, `eu`, `us-central1`, `asia-northeast1`). If `location` is unset the tool defaults to `us`. Set `location` explicitly for non-US projects or you will query the wrong region. - Databricks: `system.query.history` - PostgreSQL: `pg_stat_statements` ______________________________________________________________________ ## finops_analyze_credits Break down credit consumption by warehouse, time, and user. ```text > finops_analyze_credits --days 30 # equivalent: finops_analyze_credits prod-snowflake --days 30 Credit Analysis (last 30 days): Daily Usage Trend: Feb 1: ████████████░░░░░░░░ 28.4 credits Feb 2: ███████████████░░░░░ 35.1 credits ... Feb 26: ██████████████████░░ 42.7 credits By Warehouse: TRANSFORM_WH (XL): 523.1 credits (62%) ← largest cost driver ANALYTICS_WH (M): 187.3 credits (22%) LOADING_WH (S): 89.4 credits (11%) DEV_WH (XS): 47.4 credits (6%) Recommendations: 1. TRANSFORM_WH runs at 23% utilization, consider downsizing to L 2. 340 queries on ANALYTICS_WH scan >1GB but return <100 rows, add filters 3. DEV_WH has 0 queries between 2am-8am, enable auto-suspend ``` ______________________________________________________________________ ## finops_expensive_queries Find your most expensive queries ranked by cost. ```text > finops_expensive_queries prod-snowflake --days 7 --limit 5 Top 5 Expensive Queries: 1. 89.3 credits | 47 executions | TRANSFORM_WH SELECT * FROM events e JOIN users u ON e.user_id = u.id Anti-patterns: SELECT_STAR, MISSING_LIMIT Fix: Add column list + date filter → estimated 71% savings 2. 45.1 credits | 1 execution | TRANSFORM_WH CREATE TABLE daily_snapshot AS SELECT DISTINCT ... Anti-patterns: None (legitimate full-table operation) Suggestion: Use incremental logic instead of full refresh 3. 23.7 credits | 312 executions | ANALYTICS_WH SELECT COUNT(DISTINCT user_id) FROM events WHERE ... Anti-patterns: None Suggestion: Pre-aggregate in a materialized view, which saves ~23 credits/week 4. 18.2 credits | 7 executions | TRANSFORM_WH INSERT INTO daily_agg SELECT ... FROM raw_events Anti-patterns: SELECT_STAR_IN_SUBQUERY Fix: Explicit columns → estimated 40% savings 5. 12.8 credits | 3 executions | ANALYTICS_WH SELECT * FROM raw_clickstream WHERE event_type = 'page_view' Anti-patterns: SELECT_STAR Fix: Add column list + LIMIT → estimated 80% savings ``` ______________________________________________________________________ ## finops_warehouse_advice Get warehouse sizing recommendations based on actual usage patterns. ```text > finops_warehouse_advice prod-snowflake --days 14 Warehouse Analysis: TRANSFORM_WH (currently: X-Large) Avg utilization: 23% Peak utilization: 67% (Wed 2-4am during batch jobs) Avg queue time: 0.3s Recommendation: ↓ Downsize to LARGE Estimated savings: 210 credits/month ($630/month) ANALYTICS_WH (currently: Medium) Avg utilization: 71% Peak utilization: 95% (Mon-Fri 9am-12pm) Avg queue time: 4.2s during peak Recommendation: → Keep current size, enable auto-scaling (max 2 clusters) Estimated impact: Queue time drops to <1s during peak LOADING_WH (currently: Small) Avg utilization: 45% Peak utilization: 89% (daily at 6am) Recommendation: → Keep current size Auto-suspend: Currently 5min, recommend 1min (saves 12 credits/month) DEV_WH (currently: X-Small) Avg utilization: 8% Active hours: 9am-6pm weekdays only Recommendation: → Keep size, set auto-suspend to 1min Estimated savings: 15 credits/month ``` ______________________________________________________________________ ## finops_unused_resources Find tables and warehouses that are costing money but not being used. ```text > finops_unused_resources prod-snowflake --days 30 Unused Tables (no reads in 30 days): 1. RAW.LEGACY_EVENTS (450GB, last accessed 2025-11-03) 2. STAGING.STG_OLD_USERS (12GB, last accessed 2025-12-15) 3. ANALYTICS.TMP_MIGRATION_2024 (89GB, last accessed 2025-08-22) Total storage: 551GB → ~$23/month in storage costs Idle Warehouses (no queries in 7+ days): 1. MIGRATION_WH (Medium), last query 2026-02-10 2. TEST_WH (Small), last query 2026-01-28 Recommendations: 1. Archive or drop the 3 unused tables → save $23/month 2. Suspend MIGRATION_WH and TEST_WH → save credits on auto-resume ``` ______________________________________________________________________ ## finops_role_grants Analyze role permissions and access patterns (RBAC). ```text > finops_role_grants prod-snowflake --role ANALYST_ROLE Grants for ANALYST_ROLE: ┌──────────────┬───────────┬──────────────────────────┐ │ Privilege │ Type │ Object │ ├──────────────┼───────────┼──────────────────────────┤ │ USAGE │ WAREHOUSE │ ANALYTICS_WH │ │ USAGE │ DATABASE │ ANALYTICS │ │ USAGE │ SCHEMA │ ANALYTICS.MARTS │ │ SELECT │ TABLE │ ANALYTICS.MARTS.* │ │ SELECT │ TABLE │ ANALYTICS.STAGING.* │ │ USAGE │ SCHEMA │ ANALYTICS.RAW │ │ SELECT │ TABLE │ ANALYTICS.RAW.* │ └──────────────┴───────────┴──────────────────────────┘ Privilege Summary: SELECT on 847 tables across 3 schemas No INSERT/UPDATE/DELETE privileges ✓ No DDL privileges ✓ ``` ______________________________________________________________________ ## finops_role_hierarchy Visualize role inheritance. ```text > finops_role_hierarchy prod-snowflake Role Hierarchy: ACCOUNTADMIN ├── SYSADMIN │ ├── TRANSFORM_ROLE │ │ └── DBT_ROLE │ ├── LOADING_ROLE │ └── ADMIN_ROLE ├── SECURITYADMIN │ └── USERADMIN └── PUBLIC ├── ANALYST_ROLE └── VIEWER_ROLE 8 roles total ``` ______________________________________________________________________ ## finops_user_roles List user-to-role assignments. ```text > finops_user_roles prod-snowflake ┌──────────────────┬────────────────┬───────────────┐ │ User │ Role │ Default Role │ ├──────────────────┼────────────────┼───────────────┤ │ alice@company.com│ ANALYST_ROLE │ YES │ │ alice@company.com│ VIEWER_ROLE │ NO │ │ bob@company.com │ TRANSFORM_ROLE │ YES │ │ bob@company.com │ DBT_ROLE │ NO │ │ svc_dbt │ DBT_ROLE │ YES │ │ svc_fivetran │ LOADING_ROLE │ YES │ └──────────────────┴────────────────┴───────────────┘ ``` # Lineage Tools ## lineage_check Trace column-level lineage through SQL transformations. Returns source-to-target mappings for every column. ```text > lineage_check " SELECT o.order_id, c.name AS customer_name, o.amount * t.rate AS amount_usd, DATE_TRUNC('month', o.order_date) AS order_month FROM orders o JOIN customers c ON o.customer_id = c.id JOIN fx_rates t ON o.currency = t.currency AND o.order_date = t.rate_date " Column Lineage: ┌─────────────────┬────────────────────────┬───────────────┐ │ Target Column │ Source │ Transform │ ├─────────────────┼────────────────────────┼───────────────┤ │ order_id │ orders.order_id │ direct │ │ customer_name │ customers.name │ alias │ │ amount_usd │ orders.amount │ arithmetic │ │ │ fx_rates.rate │ arithmetic │ │ order_month │ orders.order_date │ DATE_TRUNC │ └─────────────────┴────────────────────────┴───────────────┘ Confidence: high Confidence factors: schema-qualified tables, no SELECT *, small graph (7 nodes) ``` ### Confidence signals Lineage confidence is affected by 4 factors: | Factor | Impact | Why | | ---------------------------- | ----------------- | ------------------------------------------- | | `SELECT *` | Reduces to medium | Cannot determine which columns flow through | | Jinja templates | Reduces to medium | Dynamic SQL not fully parseable | | Missing schema qualification | Reduces to low | Ambiguous table references | | Large graph (50+ nodes) | Reduces to medium | Complex lineage may miss indirect paths | ### Use cases **Impact analysis before schema changes:** ```text > lineage_check "SELECT * FROM stg_orders" Warning: SELECT * detected — lineage confidence reduced to medium. All columns from stg_orders flow through. Recommendation: Use explicit column list for precise lineage. ``` **Verify lineage preservation during migration:** ```text > lineage_check [original Snowflake SQL] > lineage_check [translated BigQuery SQL] Compare: ✓ Same 4 source columns map to same 4 target columns Lineage preserved across translation. ``` **dbt model dependency tracking:** ```text > dbt_manifest ./target/manifest.json Models: 47 Sources: 12 > lineage_check [fct_revenue.sql] Source columns: stg_orders.order_amount → fct_revenue.revenue stg_orders.order_date → fct_revenue.revenue_date dim_products.category → fct_revenue.product_category Downstream impact: dim_products.category rename would break fct_revenue ``` # Altimate Memory Tools Altimate Memory gives your data engineering agent **persistent, cross-session memory**. Instead of re-explaining your warehouse setup, naming conventions, or team preferences every session, the agent remembers what matters and picks up where you left off. Memory blocks are plain Markdown files stored on disk, making them human-readable, version-controllable, and fully under your control. ## Why memory matters for data engineering General-purpose coding agents treat every session as a blank slate. For data engineering, this is especially painful because: - **Warehouse context is stable.** Your Snowflake warehouse name, default database, and connection details rarely change, but you re-explain them every session. - **Naming conventions are tribal knowledge.** `stg_` for staging, `int_` for intermediate, `fct_`/`dim_` for marts. The agent needs to learn these once, not every time. - **Past analyses inform future work.** If the agent optimized a query or traced lineage for a table last week, recalling that context avoids redundant work. - **User preferences accumulate.** SQL style, preferred dialects, dbt patterns, warehouse sizing decisions. Altimate Memory solves this with three tools that let the agent save, recall, and manage its own persistent knowledge. ## Tools ### altimate_memory_read Read memory blocks from previous sessions. Automatically called at session start to give the agent context. ```text > Read my memory about warehouse configuration Memory: 1 block(s) ### warehouse-config (project) [snowflake, warehouse] ## Warehouse Configuration - **Provider**: Snowflake - **Default warehouse**: ANALYTICS_WH (XS for dev, M for prod) - **Default database**: ANALYTICS_DB - **Naming convention**: stg_ for staging, int_ for intermediate, fct_/dim_ for marts ``` **Parameters:** | Parameter | Type | Default | Description | | --------- | -------------------------------- | ------- | ---------------------------------------------- | | `scope` | `"global" \| "project" \| "all"` | `"all"` | Filter by scope | | `tags` | `string[]` | `[]` | Filter to blocks containing all specified tags | | `id` | `string` | (none) | Read a specific block by ID | ______________________________________________________________________ ### altimate_memory_write Create or update a persistent memory block. ```text > Remember that our Snowflake warehouse is ANALYTICS_WH and we use stg_ prefix for staging models Memory: Created "warehouse-config" ``` The agent automatically calls this when it learns something worth persisting. You can also explicitly ask it to "remember" something. **Parameters:** | Parameter | Type | Required | Description | | --------- | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------ | | `id` | `string` | Yes | Unique identifier (lowercase, hyphens/underscores). Examples: `warehouse-config`, `naming-conventions` | | `scope` | `"global" \| "project"` | Yes | `global` for user-wide preferences, `project` for project-specific knowledge | | `content` | `string` | Yes | Markdown content (max 2,048 characters) | | `tags` | `string[]` | No | Up to 10 tags for categorization (max 64 chars each) | ______________________________________________________________________ ### altimate_memory_delete Remove a memory block that is outdated, incorrect, or no longer relevant. ```text > Forget the old warehouse config, we migrated to BigQuery Memory: Deleted "warehouse-config" ``` **Parameters:** | Parameter | Type | Required | Description | | --------- | ----------------------- | -------- | ---------------------------- | | `id` | `string` | Yes | ID of the block to delete | | `scope` | `"global" \| "project"` | Yes | Scope of the block to delete | ## Scoping Memory blocks live in two scopes: | Scope | Storage location | Use case | | ----------- | ------------------------------------------ | --------------------------------------------------------------------------------------- | | **global** | `~/.local/share/altimate-code/memory/` | User-wide preferences: SQL style, preferred models, general conventions | | **project** | `.altimate-code/memory/` (in project root) | Project-specific: warehouse config, naming conventions, data model notes, past analyses | Project memory travels with your repo. Add `.altimate-code/memory/` to `.gitignore` if it contains sensitive information, or commit it to share team conventions. ## File format Each block is a Markdown file with YAML frontmatter: ```markdown --- id: warehouse-config scope: project created: 2026-03-14T10:00:00.000Z updated: 2026-03-14T10:00:00.000Z tags: ["snowflake", "warehouse"] --- ## Warehouse Configuration - **Provider**: Snowflake - **Default warehouse**: ANALYTICS_WH - **Default database**: ANALYTICS_DB ``` Files are human-readable and editable. You can create, edit, or delete them manually. The agent will pick up changes on the next session. ## Limits and safety | Limit | Value | Rationale | | -------------------- | ---------------- | --------------------------------------------------------- | | Max block size | 2,048 characters | Prevents any single block from consuming too much context | | Max blocks per scope | 50 | Bounds total memory footprint | | Max tags per block | 10 | Keeps metadata manageable | | Max tag length | 64 characters | Prevents tag abuse | | Max ID length | 256 characters | Reasonable filename length | ### Atomic writes Blocks are written to a temporary file first, then atomically renamed. This prevents corruption if the process is interrupted mid-write. ## Disabling memory Set the environment variable to disable all memory functionality, including tools and automatic injection: ```bash ALTIMATE_DISABLE_MEMORY=true ``` This is useful for **benchmarks**, CI pipelines, or any environment where persistent memory should not influence agent behavior. When disabled, memory tools are removed from the tool registry and no memory blocks are injected into the system prompt. ## Context window impact Altimate Memory automatically injects relevant blocks into the system prompt at session start, subject to a configurable token budget (default: 8,000 characters). Blocks are sorted by last-updated timestamp, so the most recently relevant information is loaded first. The agent also has access to memory tools (`altimate_memory_read`, `altimate_memory_write`, `altimate_memory_delete`) to manage blocks on demand during a session. **What this means in practice:** - With a typical block size of 200-500 characters, the default budget comfortably fits 15-40 blocks - Memory injection adds a one-time cost at session start and does not grow during the session - If you notice context pressure, reduce the number of blocks or keep them concise - The agent's own tool calls and responses consume far more context than memory blocks - To disable injection entirely (e.g., for benchmarks), set `ALTIMATE_DISABLE_MEMORY=true` Tip Keep blocks concise and focused. A block titled "warehouse-config" with 5 bullet points is better than a wall of text. The agent can always call `altimate_memory_read` to fetch specific blocks on demand. ## Potential side effects and how to handle them ### Stale or incorrect memory Memory blocks persist indefinitely. If your warehouse configuration changes or a convention is updated, the agent will continue using outdated information until the block is updated or deleted. **How to detect:** If the agent makes assumptions that don't match your current setup (e.g., references an old warehouse name), check what's in memory: ```text > Show me all memory blocks > Delete the warehouse-config block, it's outdated ``` **How to prevent:** - Review memory blocks periodically, since they're plain Markdown files you can inspect directly - Ask the agent to "forget" outdated information when things change - Keep blocks focused on stable facts rather than ephemeral details ### Wrong information getting saved The agent decides what to save based on conversation context. It may occasionally save incorrect inferences or overly specific details that don't generalize well. **How to detect:** - After a session where the agent saved memory, review what was written: ```bash ls .altimate-code/memory/ # project memory cat .altimate-code/memory/*.md # inspect all blocks ``` - The agent always reports when it creates or updates a memory block, so watch for `Memory: Created "..."` or `Memory: Updated "..."` messages in the session output **How to fix:** - Delete the bad block: ask the agent or run `rm .altimate-code/memory/bad-block.md` - Edit the file directly, since it's just Markdown - Ask the agent to rewrite it: "Update the warehouse-config memory with the correct warehouse name" ### Context bloat With 50 blocks at 2KB each, the theoretical maximum injection is ~100KB. In practice, the 8,000-character default budget caps injection at well under 10KB. **Signs of context bloat:** - Frequent auto-compaction (visible in the TUI) - The agent losing track of your current task because memory is crowding out working context **How to mitigate:** - Keep the total block count low (10-20 active blocks is a sweet spot) - Delete blocks you no longer need - Use tags to categorize and let the agent filter to what's relevant - Reduce the injection budget if needed ### Security considerations Memory blocks are stored as plaintext files on disk. Be mindful of what gets saved: - **Do not** save credentials, API keys, or connection strings in memory blocks - **Do** save structural information (warehouse names, naming conventions, schema patterns) - If using project-scoped memory in a shared repo, add `.altimate-code/memory/` to `.gitignore` to avoid committing sensitive context - Memory blocks are scoped per-user (global) and per-project, so there is no cross-user or cross-project leakage Warning Memory blocks are not encrypted. Treat them like any other configuration file on your machine. Do not store secrets or PII in memory blocks. ## Examples ### Data engineering team setup ```text > Remember: we use Snowflake with warehouse COMPUTE_WH for dev and ANALYTICS_WH for prod. Our dbt project uses the staging/intermediate/marts pattern with stg_, int_, fct_, dim_ prefixes. Always use QUALIFY instead of subqueries for deduplication. Memory: Created "team-conventions" in project scope ``` ### Personal SQL preferences ```text > Remember globally: I prefer CTEs over subqueries, always use explicit column lists (no SELECT *), and format SQL with lowercase keywords. Memory: Created "sql-preferences" in global scope ``` ### Recalling past work ```text > What do you remember about our warehouse? Memory: 2 block(s) ### warehouse-config (project) [snowflake] ... ### team-conventions (project) [dbt, conventions] ... ``` # Schema Tools ## schema_inspect Get column details for any table. ```text > schema_inspect orders --warehouse prod-snowflake Table: ANALYTICS.PUBLIC.ORDERS ┌──────────────┬──────────────┬──────────┬─────────────┐ │ Column │ Type │ Nullable │ Primary Key │ ├──────────────┼──────────────┼──────────┼─────────────┤ │ order_id │ NUMBER(38,0) │ NO │ YES │ │ customer_id │ NUMBER(38,0) │ NO │ NO │ │ order_date │ TIMESTAMP_NTZ│ NO │ NO │ │ amount │ DECIMAL(12,2)│ YES │ NO │ │ status │ VARCHAR(50) │ YES │ NO │ │ _loaded_at │ TIMESTAMP_NTZ│ NO │ NO │ └──────────────┴──────────────┴──────────┴─────────────┘ 6 columns ``` **Parameters:** - `table` (required): Table name (schema-qualified: `schema.table` or just `table`) - `schema_name` (optional): Schema to search in - `warehouse` (optional): Connection name ______________________________________________________________________ ## schema_index Index your warehouse metadata into a local SQLite cache for fast searching. ```text > schema_index prod-snowflake Indexing ANALYTICS warehouse... Schemas indexed: 12 Tables indexed: 847 Columns indexed: 15,293 Cache saved to ~/.altimate/cache/prod-snowflake.db ``` Run this once per warehouse (or periodically to refresh). Enables `schema_search` and powers schema-aware autocomplete. ______________________________________________________________________ ## schema_search Search indexed metadata by keyword to find tables, columns, and schemas. ```text > schema_search "revenue" --warehouse prod-snowflake Tables: 1. ANALYTICS.MARTS.FCT_REVENUE (42 columns), "Monthly revenue fact table" 2. ANALYTICS.STAGING.STG_REVENUE_EVENTS (18 columns) Columns: 1. ANALYTICS.MARTS.FCT_ORDERS.total_revenue (DECIMAL) 2. ANALYTICS.MARTS.DIM_PRODUCTS.revenue_category (VARCHAR) 3. ANALYTICS.RAW.STRIPE_CHARGES.revenue_amount (FLOAT) ``` **Parameters:** - `query` (required): Search term - `warehouse` (optional): Limit to one connection - `limit` (optional): Max results ______________________________________________________________________ ## schema_cache_status Check cache freshness across all warehouses. ```text > schema_cache_status ┌─────────────────┬──────────┬────────┬─────────┬─────────────────────┐ │ Warehouse │ Schemas │ Tables │ Columns │ Last Indexed │ ├─────────────────┼──────────┼────────┼─────────┼─────────────────────┤ │ prod-snowflake │ 12 │ 847 │ 15,293 │ 2026-02-26 14:30:00 │ │ dev-duckdb │ 2 │ 23 │ 156 │ 2026-02-25 09:15:00 │ │ bigquery-prod │ n/a │ n/a │ n/a │ Never │ └─────────────────┴──────────┴────────┴─────────┴─────────────────────┘ ``` ______________________________________________________________________ ## schema_detect_pii Scan columns for potential PII (personally identifiable information). ```text > schema_detect_pii --warehouse prod-snowflake --schema PUBLIC PII Findings: ⚠ ANALYTICS.PUBLIC.USERS.email (VARCHAR) Category: EMAIL_ADDRESS Confidence: high Recommendation: Apply masking policy ⚠ ANALYTICS.PUBLIC.USERS.phone_number (VARCHAR) Category: PHONE_NUMBER Confidence: high ⚠ ANALYTICS.PUBLIC.USERS.ip_address (VARCHAR) Category: IP_ADDRESS Confidence: medium ⚠ ANALYTICS.PUBLIC.ORDERS.shipping_address (VARCHAR) Category: PHYSICAL_ADDRESS Confidence: medium 4 potential PII columns found in PUBLIC schema ``` **Detection categories:** email, phone, SSN, credit card, IP address, physical address, date of birth, name patterns ______________________________________________________________________ ## schema_tags Read metadata tags on warehouse objects (Snowflake object tagging, BigQuery labels). ```text > schema_tags --warehouse prod-snowflake --object_name USERS Tags on ANALYTICS.PUBLIC.USERS: data_classification: CONFIDENTIAL pii_level: HIGH owner_team: platform retention_days: 365 ``` ______________________________________________________________________ ## schema_diff Compare schema changes between two SQL versions to understand migration impact. ```text > schema_diff \ --old_sql "CREATE TABLE orders (id INT, amount FLOAT, status TEXT)" \ --new_sql "CREATE TABLE orders (id INT, amount DECIMAL(12,2), status TEXT, created_at TIMESTAMP)" Schema Changes: ~ Modified: amount (FLOAT → DECIMAL(12,2)), severity: medium + Added: created_at (TIMESTAMP), severity: low Impact: Type change on 'amount' may affect downstream consumers expecting FLOAT ``` # SQL Tools ## sql_execute Run SQL queries against your connected warehouse. ```text > sql_execute "SELECT department, COUNT(*) as headcount FROM employees GROUP BY 1 ORDER BY 2 DESC LIMIT 10" --warehouse prod-snowflake ┌────────────┬───────────┐ │ department │ headcount │ ├────────────┼───────────┤ │ Engineering│ 342 │ │ Sales │ 218 │ │ Marketing │ 156 │ └────────────┴───────────┘ 3 rows returned (limit: 100) ``` **Parameters:** - `query` (required): SQL to execute - `warehouse` (optional): Connection name from config. Uses default if omitted - `limit` (optional, default: 100): Max rows returned ______________________________________________________________________ ## sql_analyze Static analysis that detects 19 SQL anti-patterns before you run anything. ```text > sql_analyze "SELECT * FROM events e JOIN users u ON e.user_id = u.id WHERE LOWER(u.email) LIKE '%@gmail.com'" Issues found (3): ⚠ SELECT_STAR (warning, confidence: high) Line 1: Use explicit column list instead of SELECT * → Reduces data scanned and improves lineage tracking ⚠ FUNCTION_IN_FILTER (warning, confidence: high) Line 1: LOWER(u.email) prevents index usage → Pre-compute or use ILIKE: u.email ILIKE '%@gmail.com' ⚠ LIKE_LEADING_WILDCARD (info, confidence: high) Line 1: LIKE '%@gmail.com' cannot use indexes → Consider a computed column or reverse index if this is a hot path ``` ### All 19 rules | Rule | Severity | What it catches | | ---------------------------- | -------- | ---------------------------------------------- | | `SELECT_STAR` | warning | `SELECT *` instead of explicit columns | | `SELECT_STAR_IN_SUBQUERY` | warning | `SELECT *` in subqueries (breaks lineage) | | `CARTESIAN_PRODUCT` | critical | Missing JOIN condition | | `IMPLICIT_CARTESIAN` | critical | Cross join without explicit CROSS JOIN | | `CORRELATED_SUBQUERY` | warning | Subquery referencing outer query (performance) | | `MISSING_LIMIT` | info | No LIMIT on potentially large result sets | | `ORDER_BY_WITHOUT_LIMIT` | warning | ORDER BY without LIMIT (sorts entire result) | | `ORDER_BY_IN_SUBQUERY` | info | Unnecessary ORDER BY in subquery | | `FUNCTION_IN_FILTER` | warning | Functions on columns in WHERE (non-sargable) | | `FUNCTION_IN_JOIN` | warning | Functions on columns in JOIN conditions | | `NON_EQUI_JOIN` | info | Non-equality joins (`<`, `>`, `!=`) | | `OR_IN_JOIN` | warning | OR in JOIN conditions (cross join risk) | | `LIKE_LEADING_WILDCARD` | info | `LIKE '%pattern'` prevents index usage | | `LARGE_IN_LIST` | info | IN clause with many values | | `NOT_IN_WITH_SUBQUERY` | warning | NOT IN with subquery (NULL handling issues) | | `UNION_INSTEAD_OF_UNION_ALL` | info | UNION vs UNION ALL (unnecessary dedup) | | `UNUSED_CTE` | info | CTE defined but never referenced | | `GROUP_BY_PRIMARY_KEY` | info | GROUP BY on primary key (redundant) | | `WINDOW_WITHOUT_PARTITION` | warning | Window function without PARTITION BY | Each rule includes a **confidence score** (high/medium/low) based on AST complexity: - Wildcards, EXISTS clauses, correlated subqueries, multi-joins with OR, and non-equi joins reduce confidence - High confidence = definite anti-pattern. Medium/low = review recommended ______________________________________________________________________ ## sql_optimize Get optimization suggestions with rewritten SQL. ```text > sql_optimize "SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE YEAR(o.order_date) = 2026" Suggestions: 1. Replace SELECT * with explicit columns (saves ~70% scan) 2. Replace YEAR(o.order_date) = 2026 with: o.order_date >= '2026-01-01' AND o.order_date < '2027-01-01' (enables partition pruning) Optimized SQL: SELECT o.order_id, o.amount, o.order_date, c.name, c.email FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.order_date >= '2026-01-01' AND o.order_date < '2027-01-01' Estimated improvement: 70-80% reduction in bytes scanned ``` ______________________________________________________________________ ## sql_translate Translate SQL between warehouse dialects. ```text > sql_translate \ --source snowflake \ --target bigquery \ "SELECT DATEADD(day, -30, CURRENT_TIMESTAMP()) AS thirty_days_ago, IFF(status = 'active', 1, 0) AS is_active, TRY_TO_NUMBER(amount_str) AS amount, ARRAY_AGG(tag) WITHIN GROUP (ORDER BY tag) AS tags FROM my_table QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) = 1" Translated (BigQuery): SELECT DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY) AS thirty_days_ago, IF(status = 'active', 1, 0) AS is_active, SAFE_CAST(amount_str AS NUMERIC) AS amount, ARRAY_AGG(tag ORDER BY tag) AS tags FROM `my_table` QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) = 1 Warnings: - TRY_TO_NUMBER → SAFE_CAST: returns NULL on failure (same behavior) - ARRAY_AGG: WITHIN GROUP syntax removed, ORDER BY moved inline ``` ### Supported dialects `snowflake`, `bigquery`, `databricks`, `redshift`, `postgres`, `mysql`, `sqlserver`, `duckdb` ______________________________________________________________________ ## sql_format Format SQL for readability. ```text > sql_format "select a.id,b.name,count(*) as cnt from table_a a join table_b b on a.id=b.a_id where a.status='active' group by 1,2 order by 3 desc" SELECT a.id, b.name, COUNT(*) AS cnt FROM table_a a JOIN table_b b ON a.id = b.a_id WHERE a.status = 'active' GROUP BY 1, 2 ORDER BY 3 DESC ``` ______________________________________________________________________ ## sql_fix Diagnose and auto-fix SQL errors. ```text > sql_fix \ --error "SQL compilation error: Object 'ANALYTICS.PUBLIC.USERSS' does not exist" \ "SELECT * FROM analytics.public.userss" Diagnosis: Typo in table name. 'userss' should be 'users' Fixed SQL: SELECT * FROM analytics.public.users Additional suggestions: - Use schema_search to find the correct table name - Replace SELECT * with explicit columns ``` ______________________________________________________________________ ## sql_diff Compare two versions of a SQL query. ```text > sql_diff \ --original "SELECT id, name FROM users WHERE active = true" \ --modified "SELECT id, name, email FROM users WHERE active = true AND created_at > '2026-01-01'" Diff: - SELECT id, name FROM users WHERE active = true + SELECT id, name, email FROM users WHERE active = true AND created_at > '2026-01-01' Changes: + Added column: email + Added filter: created_at > '2026-01-01' Additions: 2 | Deletions: 0 | Modifications: 0 ``` ______________________________________________________________________ ## sql_rewrite Apply automatic SQL rewrites for optimization. ```text > sql_rewrite "SELECT * FROM orders WHERE YEAR(order_date) = 2026 AND status IN ('shipped', 'delivered') ORDER BY order_date" Rewrites applied: 1. Predicate pushdown: YEAR(order_date) = 2026 → order_date >= '2026-01-01' AND order_date < '2027-01-01' 2. SELECT pruning: SELECT * → explicit columns (when schema context available) Rewritten SQL: SELECT * FROM orders WHERE order_date >= '2026-01-01' AND order_date < '2027-01-01' AND status IN ('shipped', 'delivered') ORDER BY order_date ``` ### Rewrite strategies 1. **Predicate pushdown.** Move filters closer to data source 1. **SELECT pruning.** Replace `*` with explicit columns 1. **Function elimination.** Replace non-sargable functions with range predicates 1. **JOIN reordering.** Smaller tables first 1. **Subquery flattening.** Convert to JOINs where possible 1. **UNION ALL promotion.** Replace UNION with UNION ALL when safe ______________________________________________________________________ ## sql_explain Generate execution plans. ```text > sql_explain "SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id" --warehouse prod-snowflake EXPLAIN output: GlobalStats: partitionsTotal=1024 partitionsAssigned=1024 bytesAssigned=4.2GB Operations: 1. TableScan: orders (1024 partitions, 4.2GB) 2. TableScan: customers (8 partitions, 12MB) 3. Join: HASH (orders.customer_id = customers.id) 4. Result: 15 columns ``` ______________________________________________________________________ ## sql_autocomplete Schema-aware SQL completion. ```text > sql_autocomplete --prefix "SELECT o.order_id, o.amo" --table_context ["orders"] Suggestions: 1. o.amount (DECIMAL), from orders.amount 2. o.amount_usd (DECIMAL), from orders.amount_usd ``` # Warehouse Tools ## project_scan Scan the entire data engineering environment in one call. Detects dbt projects, warehouse connections, Docker databases, installed tools, and configuration files. Used by the `/discover` command. ```text > /discover # Environment Scan ## Git Repository ✓ Git repo on branch `main` (origin: github.com/org/analytics) ## dbt Project ✓ Project "analytics" (profile: snowflake_prod) Models: 47, Sources: 12, Tests: 89 ✓ packages.yml found ## Warehouse Connections ### Already Configured Name | Type | Database prod-snowflake | snowflake | ANALYTICS ### From dbt profiles.yml Name | Type | Source dbt_snowflake_dev | snowflake | dbt-profile ### From Docker Container | Type | Host:Port local-postgres | postgres | localhost:5432 ### From Environment Variables Name | Type | Signal env_bigquery | bigquery | GOOGLE_APPLICATION_CREDENTIALS ## Installed Data Tools ✓ dbt v1.8.4 ✓ sqlfluff v3.1.0 ✗ airflow (not found) ## Config Files ✓ .altimate-code/altimate-code.json ✓ .sqlfluff ✗ .pre-commit-config.yaml (not found) ``` ### What it detects | Category | Detection method | | ------------------------- | --------------------------------------------------------------------------------------------------- | | **Git** | `git` commands (branch, remote) | | **dbt project** | Walks up directories for `dbt_project.yml`, reads name/profile | | **dbt manifest** | Parses `target/manifest.json` for model/source/test counts | | **dbt profiles** | Searches for `profiles.yml`: `DBT_PROFILES_DIR` env var → project root → `/.dbt/profiles.yml` | | **Docker DBs** | Bridge call to discover running PostgreSQL/MySQL/MariaDB/MSSQL/Oracle/ClickHouse/Trino containers | | **Existing connections** | Bridge call to list already-configured warehouses | | **Environment variables** | Scans `process.env` for warehouse signals (see table below) | | **Schema cache** | Bridge call for indexed warehouse status | | **Data tools** | Spawns `tool --version` for 9 common tools | | **Config files** | Checks for `.altimate-code/`, `.sqlfluff`, `.pre-commit-config.yaml` | ### Environment variable detection | Warehouse | Signal (any one triggers detection) | | ---------- | ------------------------------------------------------------------- | | Snowflake | `SNOWFLAKE_ACCOUNT` | | BigQuery | `GOOGLE_APPLICATION_CREDENTIALS`, `BIGQUERY_PROJECT`, `GCP_PROJECT` | | Databricks | `DATABRICKS_HOST`, `DATABRICKS_SERVER_HOSTNAME` | | PostgreSQL | `PGHOST`, `PGDATABASE`, `DATABASE_URL` | | MySQL | `MYSQL_HOST`, `MYSQL_DATABASE` | | MongoDB | `MONGODB_URI`, `MONGO_URL` | | Redshift | `REDSHIFT_HOST` | | ClickHouse | `CLICKHOUSE_HOST`, `CLICKHOUSE_URL` | | Trino | `TRINO_HOST`, `TRINO_SERVER`, `TRINO_URL`, `DATABASE_URL` | ### Parameters | Parameter | Type | Description | | ------------- | ------- | ---------------------------------------- | | `skip_docker` | boolean | Skip Docker container discovery (faster) | | `skip_tools` | boolean | Skip installed tool detection (faster) | ______________________________________________________________________ ## warehouse_list List all configured warehouse connections. ```text > warehouse_list ┌─────────────────┬───────────┬────────────┬─────────────┐ │ Name │ Type │ Database │ Status │ ├─────────────────┼───────────┼────────────┼─────────────┤ │ prod-snowflake │ snowflake │ ANALYTICS │ configured │ │ dev-duckdb │ duckdb │ dev.duckdb │ configured │ │ bigquery-prod │ bigquery │ my-project │ configured │ │ databricks-prod │ databricks│ main │ configured │ └─────────────────┴───────────┴────────────┴─────────────┘ ``` ______________________________________________________________________ ## warehouse_test Test a warehouse connection. ```text > warehouse_test prod-snowflake Testing connection to prod-snowflake (snowflake)... ✓ Connected successfully Account: xy12345.us-east-1 User: analytics_user Role: ANALYST_ROLE Warehouse: COMPUTE_WH Database: ANALYTICS ``` ```text > warehouse_test bigquery-prod Testing connection to bigquery-prod (bigquery)... ✓ Connected successfully Project: my-gcp-project Dataset: analytics Auth: Service Account (svc-altimate@my-gcp-project.iam.gserviceaccount.com) ``` ### Connection troubleshooting | Error | Cause | Fix | | ----------------------- | ----------------------- | ---------------------------------- | | `Authentication failed` | Wrong credentials | Check password/token in config | | `Connection refused` | Network/firewall | Verify host/port, check VPN | | `Object does not exist` | Wrong database/schema | Verify database name in config | | `Role not authorized` | Insufficient privileges | Use a role with USAGE on warehouse | | `Timeout` | Network latency | Increase connection timeout | ______________________________________________________________________ ## warehouse_add Add a new warehouse connection by providing a name and configuration. ```text > warehouse_add my-postgres {"type": "postgres", "host": "localhost", "port": 5432, "database": "analytics", "user": "analyst", "password": "secret"} ✓ Added warehouse 'my-postgres' (postgres) ``` ______________________________________________________________________ ## warehouse_remove Remove an existing warehouse connection. ```text > warehouse_remove my-postgres ✓ Removed warehouse 'my-postgres' ``` ______________________________________________________________________ ## warehouse_discover Discover database containers running in Docker. Detects PostgreSQL, MySQL/MariaDB, SQL Server, Trino, and ClickHouse containers with their connection details. ```text > warehouse_discover Container | Type | Host:Port | User | Database | Status local-postgres | postgres | localhost:5432 | postgres | postgres | running mysql-dev | mysql | localhost:3306 | root | mydb | running Use warehouse_add to save any of these as a connection. ``` # Training: Corrections That Stick > **Correct the agent once. It remembers forever. Your team inherits it.** ## The Problem AI coding assistants make the same mistakes over and over. You say "use DECIMAL not FLOAT," it fixes it, then does the same thing next session. You write instructions in CLAUDE.md, but nobody updates it after corrections. The knowledge from your day-to-day work never becomes permanent. ## How Training Works When the agent makes a mistake and you correct it, it asks: ```text You: No — never use FLOAT for money. Use DECIMAL(18,2). Builder: Got it. Want me to remember this as a rule? You: Yes Builder: Saved. I'll apply this in every future session. Your team gets it too when they pull. ``` That's it. **2 seconds.** No editing files. No context switching. The correction becomes permanent knowledge that every agent mode (builder, analyst) sees in every future session. Research shows compact, focused context improves AI performance by 17 percentage points, while dumping comprehensive docs actually hurts by 3 points (SkillsBench, 7,308 test runs). Training delivers the right knowledge to the right agent at the right time, not everything to everyone. ## Three Ways to Teach ### 1. Correct as You Go (Most Common) In any mode, corrections become learning moments: ```text You: We use fct_ not fact_ for fact tables Builder: Got it. Want me to remember this? You: Yes ``` Next session, every agent knows. Every teammate inherits it via git. ### 2. Learn from Example Files Point the agent at code that demonstrates a convention: ```text You: /teach @models/staging/stg_orders.sql Agent: I see the pattern: - source CTE → filtered CTE → final - ROW_NUMBER dedup on _loaded_at Save as pattern "staging-cte-structure"? ``` ### 3. Learn from Documentation Point the agent at your style guide: ```text You: /train @docs/sql-style-guide.md Agent: I found 8 actionable rules: 1. SQL keywords in lowercase 2. Never use SELECT * 3. CTEs named as verb_noun ... Save these? ``` ______________________________________________________________________ ## What You Can Teach | Kind | Purpose | Example | | ------------ | ---------------------- | --------------------------------------------------------------------- | | **rule** | Hard constraint | "Never use FLOAT for money. Use DECIMAL(18,2)." | | **pattern** | How code should look | "Staging models: source CTE → filtered → final" | | **standard** | Team convention | "Every PR needs tests + schema YAML" | | **glossary** | Business term | "ARR = Annual Recurring Revenue = MRR * 12" | | **context** | Background knowledge | "We chose Snowflake because of RBAC support" | | **playbook** | Step-by-step procedure | "Cost spike: check query history → identify warehouse → kill runaway" | ## How Training Reaches Your Team 1. You correct the agent → training saved to `.altimate-code/memory/` 1. You commit and push (training files are in git) 1. Teammates pull → they inherit your corrections automatically 1. Next session, every agent applies the correction No meetings. No Slack messages. No "hey everyone, remember to..." ## Systematic Teaching For systematic teaching (not just corrections), use the `/teach` and `/train` skills in any agent mode: - `/teach @file` to learn patterns from example files - `/train @file` to learn standards from documentation - `/training-status` to see all learned knowledge ### When to Teach | Scenario | Why | | ------------------- | ----------------------------------------------- | | New project setup | Teach conventions before anyone starts building | | New hire onboarding | Walk through what the team has taught | | After an incident | Save the lesson as a permanent rule | | Quarterly review | Remove stale entries, consolidate, fill gaps | ## Agent-Aware Delivery Training doesn't dump everything into every session. It delivers what's relevant: - **Builder** gets rules and patterns first (naming conventions, SQL constraints) - **Analyst** gets glossary and context first (business terms, background knowledge) Research shows 2-3 focused modules per task is optimal. The scoring system ensures each agent gets its most relevant knowledge first. ## Training vs CLAUDE.md Training doesn't replace CLAUDE.md. They complement each other: | | CLAUDE.md | Training | | --------------------- | -------------------------- | ---------------------------------- | | **Best for** | Broad project instructions | Corrections and domain knowledge | | **How it's written** | You edit a file | Agent captures from conversation | | **When it's updated** | When you remember | When you correct the agent (2 sec) | | **What it knows** | What you wrote down | What emerged from working together | | **Delivery** | Everything, every session | Most relevant per agent | **Use CLAUDE.md for**: Project-wide setup, broad instructions, architecture docs. **Use training for**: The corrections, patterns, and domain knowledge that emerge from actually using the agent. ______________________________________________________________________ ## Limitations - **Advisory, not enforced.** Training guides the agent, but it's not a hard gate. For critical rules, also add dbt tests or sqlfluff rules that block CI. - **No approval workflow.** Anyone with repo access can save training to project scope. Use code review on `.altimate-code/memory/` changes for governance. - **No audit trail** beyond git history. Training doesn't track who saved what, so use `git blame` on the training files. - **Context budget.** Training competes for context space. Under pressure, least-relevant entries are excluded. Run `/training-status` to see what's included. - **20 entries per kind.** Hard limit. Consolidate related rules into one entry rather than saving many small ones. - **SQL-focused file analysis.** The `/teach` skill works best with SQL/dbt files. Python, PySpark, and other patterns must be taught manually via conversation. - **Team sync requires git discipline.** Training saves to disk but doesn't auto-commit. Commit `.altimate-code/memory/` changes to share with your team. ## Quick Reference ### Tools | Tool | Purpose | Available In | | ----------------- | ----------------------------- | ------------ | | `training_save` | Save or update an entry | All modes | | `training_list` | List entries with usage stats | All modes | | `training_remove` | Remove an entry | All modes | ### Skills | Skill | Purpose | | ------------------ | ------------------------------------ | | `/teach` | Learn a pattern from an example file | | `/train` | Extract rules from a document | | `/training-status` | View training dashboard | ### Limits | Limit | Value | | --------------------- | ------------------------------------- | | Max entries per kind | 20 | | Max content per entry | 1,800 characters | | Training kinds | 6 | | Scopes | 2 (global = personal, project = team) | ### Feature Flag ```bash export ALTIMATE_DISABLE_TRAINING=true # Disables all training ``` # Deploying Team Training Get every teammate's AI automatically applying the same SQL conventions, naming standards, and anti-pattern rules. Achieved by committing `.altimate-code/memory/` to git so that teammates inherit your training on `git pull`. ______________________________________________________________________ ## Step 1: Create Your First Team Training Entries Use the `/teach` or `/train` skills to save project-specific conventions: ```text /teach always use QUALIFY instead of nested window function subqueries in Snowflake SQL ``` ```text /teach our staging models follow the pattern: stg___.sql ``` Verify the training was saved: ```bash /training-status ``` This shows all active training entries, their scope (global vs project), and when they were added. ______________________________________________________________________ ## Step 2: Locate the Training Files Training is stored in `.altimate-code/memory/` in your project root. Each entry is a markdown file with YAML frontmatter: ```text .altimate-code/ memory/ sql-conventions.md naming-standards.md project-patterns.md ``` **Global vs. project scope:** - **Project scope** (`.altimate-code/memory/`): Applies when working in this project. Commit to git to share with team. - **Global scope** (`~/.altimate-code/memory/`): Applies across all projects. Do not commit, as this is personal. ______________________________________________________________________ ## Step 3: Commit to Git ```bash git add .altimate-code/memory/ git commit -m "Add team SQL conventions and naming standards" git push ``` Teammates who `git pull` automatically inherit all training entries. No additional setup is required because the tool reads from `.altimate-code/memory/` on startup. ______________________________________________________________________ ## Step 4: Verify a Teammate Got the Training After a teammate pulls, they can run: ```bash /training-status ``` They should see the same entries you created. If they don't, check that `.altimate-code/memory/` is not in `.gitignore`. ______________________________________________________________________ ## Best Practices **What to teach first:** 1. Your team's most common SQL mistakes (the things that keep coming up in code review) 1. Naming conventions for models, tables, and columns 1. Project-specific patterns: your medallion layer names, your warehouse, your dbt project structure **Handling conflicting corrections:** Later corrections override earlier ones for the same topic. Use `/training-status` to audit and delete stale entries with `/forget `. **Global vs. project scope:** Use project scope for team standards. Use global scope only for personal preferences that apply to all your projects (e.g., preferred SQL style). ______________________________________________________________________ ## Limitations Training is as good as the corrections you save. The system doesn't infer conventions from your existing codebase; you teach it explicitly. For the full description of how training works, see [Training Overview](https://help.altimate.ai/code/data-engineering/training/index.md). # Ecosystem altimate has a growing ecosystem of plugins, tools, and integrations. ## Official Packages | Package | Description | | ---------------------------------- | ---------------------- | | `@altimateai/altimate-code` | CLI and TUI | | `@altimateai/altimate-code-sdk` | TypeScript SDK | | `@altimateai/altimate-code-plugin` | Plugin development kit | ## Integrations - **GitHub Actions**: Automated PR review and issue triage - **GitLab CI**: Merge request analysis - **VS Code / Cursor / Windsurf**: [IDE integration](https://help.altimate.ai/code/usage/ide/index.md) via the Datamates extension (branded **Altimate MCP** in-editor) - **[Altimate MCP](/datamates/)**: AI teammates platform with MCP integrations, Knowledge Hub, Memory, and Guardrails - **MCP**: Model Context Protocol servers - **ACP**: Agent Communication Protocol for editors ## Community - [GitHub Repository](https://github.com/AltimateAI/altimate-code): Source code, issues, discussions - Share your plugins and tools with the community ## Contributing Contributions are welcome. See the repository for guidelines on: - Bug reports and feature requests - Plugin development - Documentation improvements - Tool contributions # Plugins Plugins extend altimate with custom tools, hooks, and behaviors. Use plugins to add domain-specific rules, integrate with internal APIs, log telemetry, enforce governance policies, or customize how the agent interacts with your data stack. ## Creating a Plugin ```bash mkdir my-plugin && cd my-plugin npm init -y npm install @altimateai/altimate-code-plugin zod ``` ```typescript // index.ts import { definePlugin } from "@altimateai/altimate-code-plugin" import { z } from "zod" export default definePlugin({ name: "my-plugin", tools: [ { name: "my_tool", description: "A custom tool", parameters: z.object({ query: z.string(), }), async execute({ query }) { return { result: query.toUpperCase() } }, }, ], hooks: { onSessionStart(session) { console.log("Session started:", session.id) }, onToolCall(call) { console.log("Tool called:", call.name) }, }, }) ``` ## Registering Plugins Add plugins to your `altimate-code.json` config file: ```json { "plugin": [ "@altimateai/altimate-code-plugin-example", "./path/to/local-plugin", "npm-published-plugin" ] } ``` Plugins can be specified as: - **npm package name**: installed from the registry (e.g., `"npm-published-plugin"`) - **Relative path**: a local directory (e.g., `"./path/to/local-plugin"`) - **Scoped package**: with an org prefix (e.g., `"@altimateai/altimate-code-plugin-example"`) ## Plugin Hooks Plugins can listen to lifecycle events. Each hook receives a context object with data relevant to the event. | Hook | When It Fires | Data Available | | ---------------- | ------------------------------------- | --------------------------------------------------------------------------- | | `onSessionStart` | A new session is created | `session.id`, `session.agent`, `session.metadata` | | `onSessionEnd` | A session is closed or expires | `session.id`, `session.duration`, `session.messageCount` | | `onMessage` | User sends a message to the agent | `message.content`, `message.sessionId`, `message.agent` | | `onResponse` | Agent generates a response | `response.content`, `response.sessionId`, `response.toolCalls` | | `onToolCall` | Before a tool is executed | `call.name`, `call.parameters`, `call.sessionId` (return `false` to cancel) | | `onToolResult` | After a tool finishes executing | `result.toolName`, `result.output`, `result.duration`, `result.error` | | `onFileEdit` | A file is modified via the agent | `edit.filePath`, `edit.oldContent`, `edit.newContent`, `edit.sessionId` | | `onFileWrite` | A new file is created via the agent | `write.filePath`, `write.content`, `write.sessionId` | | `onError` | An error occurs during processing | `error.message`, `error.code`, `error.stack`, `error.sessionId` | | `onConfigChange` | Configuration is reloaded or modified | `config.previous`, `config.current`, `config.changedKeys` | ### Hook Execution Order Hooks fire in this order during a typical interaction: 1. `onSessionStart` (once per session) 1. `onMessage` (each user message) 1. `onToolCall` (before each tool runs) 1. `onToolResult` (after each tool completes) 1. `onFileEdit` / `onFileWrite` (if the tool modifies files) 1. `onResponse` (when the agent produces a response) 1. `onError` (if something fails, at any point) 1. `onSessionEnd` (when the session closes) ## Example: SQL Anti-Pattern Plugin This example creates a data-engineering-specific plugin that checks for `CROSS JOIN` without a `WHERE` clause in Snowflake SQL. This is a common anti-pattern that can cause massive result sets and runaway costs. ### Plugin File ```typescript // plugins/sql-antipattern-cross-join/index.ts import { definePlugin, defineTool } from "@altimateai/altimate-code-plugin" import { z } from "zod" /** * Detects CROSS JOIN usage without a WHERE clause in Snowflake SQL. * This anti-pattern can produce cartesian products and consume * excessive credits. */ const crossJoinChecker = defineTool({ name: "check_cross_join_antipattern", description: "Checks SQL for CROSS JOIN without a WHERE clause, which can cause cartesian products in Snowflake", parameters: z.object({ sql: z.string().describe("The SQL query to analyze"), severity: z .enum(["warning", "error"]) .default("error") .describe("Severity level for detected anti-patterns"), }), async execute({ sql, severity }) { const findings: Array<{ line: number message: string severity: string suggestion: string }> = [] const lines = sql.split("\n") const upperSql = sql.toUpperCase() // Check for CROSS JOIN const crossJoinRegex = /\bCROSS\s+JOIN\b/gi let match: RegExpExecArray | null while ((match = crossJoinRegex.exec(sql)) !== null) { const lineNumber = sql.substring(0, match.index).split("\n").length // Check if there's a WHERE clause after this CROSS JOIN const afterJoin = upperSql.substring(match.index) const hasWhere = /\bWHERE\b/.test(afterJoin) const hasLimit = /\bLIMIT\b/.test(afterJoin) if (!hasWhere) { findings.push({ line: lineNumber, message: `CROSS JOIN without a WHERE clause at line ${lineNumber}`, severity, suggestion: hasLimit ? "Add a WHERE clause to filter the cartesian product. LIMIT alone does not prevent full computation in Snowflake." : "Add a WHERE clause or replace with an INNER JOIN on a specific condition. Without filtering, this produces a full cartesian product.", }) } } // Also detect implicit cross joins (comma-separated FROM without WHERE) const implicitCrossRegex = /\bFROM\s+(\w+\s*,\s*\w+(?:\s*,\s*\w+)*)\b/gi while ((match = implicitCrossRegex.exec(sql)) !== null) { const afterFrom = upperSql.substring(match.index) const hasWhere = /\bWHERE\b/.test(afterFrom) if (!hasWhere) { const lineNumber = sql.substring(0, match.index).split("\n").length findings.push({ line: lineNumber, message: `Implicit CROSS JOIN (comma-separated tables) without WHERE at line ${lineNumber}`, severity: "warning", suggestion: "Use explicit JOIN syntax with ON conditions instead of comma-separated tables in FROM.", }) } } return { passed: findings.length === 0, findingCount: findings.length, findings, summary: findings.length === 0 ? "No CROSS JOIN anti-patterns detected." : `Found ${findings.length} potential CROSS JOIN anti-pattern(s).`, } }, }) export default definePlugin({ name: "sql-antipattern-cross-join", description: "Detects CROSS JOIN anti-patterns in Snowflake SQL", tools: [crossJoinChecker], hooks: { onToolCall(call) { // Automatically check SQL when query tools are used if ( call.name === "warehouse_query" && typeof call.parameters?.sql === "string" ) { console.log( `[cross-join-checker] Scanning query for anti-patterns...` ) } }, onToolResult(result) { if (result.toolName === "check_cross_join_antipattern") { const output = result.output as { passed: boolean; summary: string } if (!output.passed) { console.warn(`[cross-join-checker] ${output.summary}`) } } }, }, }) ``` ### Register It Add the plugin path to your `altimate-code.json`: ```json { "plugin": [ "./plugins/sql-antipattern-cross-join" ] } ``` Or place it directly in your project's `.altimate-code/plugins/` directory, where it will be loaded automatically. ### Use It Once registered, the tool is available in any session: ```text > check_cross_join_antipattern sql:"SELECT * FROM orders CROSS JOIN customers" Found 1 potential CROSS JOIN anti-pattern(s). - Line 1: CROSS JOIN without a WHERE clause Suggestion: Add a WHERE clause or replace with an INNER JOIN on a specific condition. ``` ## Testing Your Plugin ### Development Mode Run your plugin tests using `bun test`: ```bash cd plugins/sql-antipattern-cross-join bun test ``` ### Writing Unit Tests Create a test file alongside your plugin: ```typescript // plugins/sql-antipattern-cross-join/index.test.ts import { describe, it, expect } from "bun:test" import plugin from "./index" describe("cross-join-antipattern", () => { const tool = plugin.tools[0] it("detects CROSS JOIN without WHERE", async () => { const result = await tool.execute({ sql: "SELECT * FROM orders CROSS JOIN customers", severity: "error", }) expect(result.passed).toBe(false) expect(result.findingCount).toBe(1) expect(result.findings[0].message).toContain("CROSS JOIN without a WHERE") }) it("passes CROSS JOIN with WHERE", async () => { const result = await tool.execute({ sql: "SELECT * FROM orders CROSS JOIN customers WHERE orders.id = customers.order_id", severity: "error", }) expect(result.passed).toBe(true) expect(result.findingCount).toBe(0) }) it("detects implicit cross join", async () => { const result = await tool.execute({ sql: "SELECT * FROM orders, customers", severity: "warning", }) expect(result.passed).toBe(false) expect(result.findings[0].message).toContain("Implicit CROSS JOIN") }) it("handles clean SQL", async () => { const result = await tool.execute({ sql: "SELECT o.id, c.name FROM orders o INNER JOIN customers c ON o.customer_id = c.id", severity: "error", }) expect(result.passed).toBe(true) }) }) ``` Run the tests: ```bash bun test plugins/sql-antipattern-cross-join/index.test.ts ``` ## Distributing Your Plugin ### Option 1: Local Directory Place your plugin in the `.altimate-code/plugins/` directory of your project. Plugins in this directory are loaded automatically without explicit registration. ```text my-dbt-project/ .altimate-code/ plugins/ sql-antipattern-cross-join/ index.ts package.json ``` ### Option 2: Git Repository Publish your plugin as a git repository and reference it by URL: ```json { "plugin": [ "git+https://github.com/your-org/altimate-cross-join-checker.git" ] } ``` ### Option 3: npm Package Publish your plugin to npm for the widest distribution: ```bash # In your plugin directory npm publish ``` Your `package.json` should include: ```json { "name": "@your-org/altimate-plugin-cross-join", "version": "1.0.0", "main": "index.ts", "keywords": ["altimate-code-plugin"], "peerDependencies": { "@altimateai/altimate-code-plugin": ">=0.4.0" } } ``` Then consumers install and register it: ```bash npm install @your-org/altimate-plugin-cross-join ``` ```json { "plugin": ["@your-org/altimate-plugin-cross-join"] } ``` ## Plugin API ```typescript import { definePlugin, defineTool } from "@altimateai/altimate-code-plugin" ``` | Export | Description | | -------------- | ------------------------------------ | | `definePlugin` | Define a plugin with tools and hooks | | `defineTool` | Define a standalone tool | ## Disabling Default Plugins ```bash export ALTIMATE_CLI_DISABLE_DEFAULT_PLUGINS=true ``` # SDK The altimate SDK (`@altimateai/altimate-code-sdk`) provides a TypeScript client for programmatic access to altimate functionality. Use it to automate SQL analysis, manage sessions, and integrate altimate into your CI/CD pipelines or internal tools. ## Installation ```bash npm install @altimateai/altimate-code-sdk ``` ## Starting the Server Before using the SDK, you need a running altimate server. Start it with: ```bash # Start the server on the default port (3000) altimate serve # Start on a custom port altimate serve --port 8080 # Start with a specific config file altimate serve --config ./altimate-code.json ``` Verify the server is running by hitting the health check endpoint: ```bash curl http://localhost:3000/health # => {"status":"ok"} ``` ## Client Usage ```typescript import { createClient } from "@altimateai/altimate-code-sdk/client" const client = createClient({ baseURL: "http://localhost:3000", username: "admin", password: "secret", }) // Send a message const response = await client.send({ message: "analyze my top 10 most expensive queries", agent: "analyst", }) // List sessions const sessions = await client.sessions.list() ``` ## Complete Integration Example The following example demonstrates a full workflow: starting a session, running a SQL analysis task, reading the structured result, and handling errors. ```typescript import { createClient } from "@altimateai/altimate-code-sdk/client" async function analyzeExpensiveQueries() { const client = createClient({ baseURL: "http://localhost:3000", username: "admin", password: "secret", }) // Step 1: Create a new session const session = await client.sessions.create({ agent: "analyst", metadata: { project: "analytics-pipeline" }, }) try { // Step 2: Send an analysis request within the session const response = await client.send({ sessionId: session.id, message: "Find the top 10 most expensive queries by credit consumption in the last 30 days", agent: "analyst", }) // Step 3: Read the structured result console.log("Analysis complete:") console.log("Response:", response.content) if (response.toolResults) { for (const result of response.toolResults) { console.log(`Tool: ${result.toolName}`) console.log(`Output:`, JSON.stringify(result.output, null, 2)) } } // Step 4: Ask a follow-up question in the same session const followUp = await client.send({ sessionId: session.id, message: "Which of those queries could benefit from clustering keys?", agent: "analyst", }) console.log("Follow-up:", followUp.content) return { response, followUp } } finally { // Step 5: Always close the session when done await client.sessions.close(session.id) } } analyzeExpensiveQueries().catch(console.error) ``` ## Session Management Sessions maintain conversation context, which is important for multi-turn interactions and batch workflows. ```typescript // Create a session with metadata for tracking const session = await client.sessions.create({ agent: "analyst", metadata: { pipeline: "nightly-audit", runId: "2025-01-15" }, }) // Reuse the session for multiple related messages await client.send({ sessionId: session.id, message: "List all tables in ANALYTICS.PUBLIC" }) await client.send({ sessionId: session.id, message: "Which tables have no primary key?" }) // List all active sessions const activeSessions = await client.sessions.list() console.log(`Active sessions: ${activeSessions.length}`) // Close the session to release resources await client.sessions.close(session.id) ``` **Batch workflow tip:** When processing many projects or warehouses, create one session per unit of work and close each when done. This keeps memory usage predictable and ensures context does not leak between unrelated analyses. ## Error Handling The SDK throws typed errors that you can catch and handle: ```typescript import { createClient } from "@altimateai/altimate-code-sdk/client" import { ConnectionError, AuthenticationError, SessionNotFoundError, RateLimitError, ServerError, } from "@altimateai/altimate-code-sdk" const client = createClient({ baseURL: "http://localhost:3000", username: "admin", password: "secret", }) try { const response = await client.send({ message: "analyze warehouse costs", agent: "analyst", }) } catch (error) { if (error instanceof ConnectionError) { // Server is not running or unreachable console.error("Cannot reach altimate server. Is it running?", error.message) } else if (error instanceof AuthenticationError) { // Invalid credentials console.error("Invalid username or password") } else if (error instanceof SessionNotFoundError) { // Session expired or does not exist console.error("Session not found — it may have expired", error.sessionId) } else if (error instanceof RateLimitError) { // Too many requests — back off and retry console.error(`Rate limited. Retry after ${error.retryAfterMs}ms`) await new Promise((r) => setTimeout(r, error.retryAfterMs)) } else if (error instanceof ServerError) { // Internal server error console.error("Server error:", error.statusCode, error.message) } else { throw error // Re-throw unexpected errors } } ``` ## Exports | Import | Description | | ----------------------------------------- | ---------------------------------------------------------- | | `@altimateai/altimate-code-sdk` | Core SDK: error types, constants, utilities | | `@altimateai/altimate-code-sdk/client` | HTTP client: `createClient()` | | `@altimateai/altimate-code-sdk/server` | Server utilities for embedding altimate in your own server | | `@altimateai/altimate-code-sdk/v2` | v2 API types: TypeScript type definitions | | `@altimateai/altimate-code-sdk/v2/client` | v2 client: auto-generated typed client | ## OpenAPI The SDK is generated from an OpenAPI specification. The v2 client is auto-generated using `@hey-api/openapi-ts`. When the server is running, you can access the live OpenAPI spec at: ```text http://localhost:PORT/openapi.json ``` This is useful for exploring available endpoints, generating clients in other languages, or importing into tools like Postman or Insomnia. > **For contributors:** If you make changes to the API (e.g., `packages/opencode/src/server/server.ts`), run `./script/generate.ts` to regenerate the SDK and related files. See [CONTRIBUTING.md](https://github.com/AltimateAI/altimate-code/blob/main/CONTRIBUTING.md) for details. # Server altimate includes an HTTP API server for remote access and integrations. ## Starting the Server ```bash altimate serve ``` Or use the web UI (which includes the API): ```bash altimate web ``` ## Configuration ```json { "server": { "port": 3000, "hostname": "localhost", "cors": ["https://myapp.example.com"], "mdns": true, "mdnsDomain": "altimate-code.local" } } ``` ## Authentication Set credentials via environment variables: ```bash export ALTIMATE_CLI_SERVER_USERNAME=admin export ALTIMATE_CLI_SERVER_PASSWORD=secret altimate serve ``` The server uses HTTP Basic Authentication when credentials are set. ## API Endpoints The server exposes REST endpoints for: - **Sessions**: Create, list, delete sessions - **Messages**: Send messages, stream responses - **Models**: List available models - **Agents**: List and switch agents - **Tools**: Execute tools programmatically - **Export/Import**: Session data management Use the [SDK](https://help.altimate.ai/code/develop/sdk/index.md) for a typed client, or call the API directly. ## mDNS Discovery Enable mDNS to discover altimate servers on your local network: ```json { "server": { "mdns": true, "mdnsDomain": "altimate-code.local" } } ``` # Showcase Real-world examples showing what altimate can do across data engineering workflows. Each example demonstrates end-to-end automation — from discovery to implementation. ______________________________________________________________________ ## Onboarding a Junior Data Engineer — Automated Peer Review `dbt` `SQL Quality` `A-F Grading` A junior engineer always gets senior-level peer review — altimate grades the mart layer, flags every anti-pattern, fixes the offending SQL, and re-grades to prove the improvement. **Prompt:** > Run quality checks and grading on the mart layer queries of my dbt project to find out the SQL anti patterns. Also fix those issues, validate and re-grade them. *Click on the image to watch the demo.* ______________________________________________________________________ ## An Upstream Schema Changed. What Just Broke? `dbt` `Lineage` `Incident Response` A staging model renames a column and the dbt run fails. altimate reads the error log, traces lineage, pinpoints every broken downstream model, and fixes the references — no hunting through dozens of files. **Prompt:** > Switch to the `bug/column-rename` branch. A staging model was updated to rename a column, but downstream models weren't updated. Check the error log at `logs/dbt_run_error.log` and identify all the downstream models that broke. Fix them. *Click on the image to watch the demo.* ______________________________________________________________________ ## Column-Level Lineage Diff for PR Reviews `dbt` `Column-Level Lineage` `PR Review` Before approving a risky refactor PR, get a precise column-level lineage diff between the two branches — new dependencies, removed ones, source changes — so you know the blast radius before you merge. **Prompt:** > I am reviewing a PR that refactors `mart_patient_360` — the PR claims to fix a cartesian explosion, hash SSN for HIPAA, and add financial metrics. Before I approve, I need to understand exactly what changed at the column-level data flow. Run a column-level lineage diff between the old version (on `main`) and the new version (on `refactor/mart-patient-360-fix-cartesian-and-pii`) of `models/marts/mart_patient_360.sql`. Show me which column dependencies were added, removed, or changed source — I want to know the blast radius before merging. *Click on the image to watch the demo.* ______________________________________________________________________ ## From Idea to Production dbt Model in One Terminal Session `dbt` `Model Scaffolding` `Tests & Docs` A plain-English analytics request becomes a production-ready dbt asset — SQL, documentation, schema tests, validation — all in a single session. **Prompt:** > I need a new dbt model called `mart_monthly_revenue`. It should show monthly revenue broken down by merchant risk tier. Include total revenue, transaction count, unique merchants, and average transaction value. Use `stg_transactions` and `stg_merchants` as the upstream models. *Click on the image to watch the demo.* ______________________________________________________________________ ## Refactoring dbt Models Without Breaking Everything `dbt` `Refactor` `Impact Analysis` Plan a schema refactor with a complete blast-radius report before merging — every downstream model that needs a change, and exactly what change it needs. **Prompt:** > Switch to the `feat/refactor-stg-transactions` branch. The `stg_transactions` model renames `created_at` to `transaction_at` and drops `card_last_four` and `ip_address`. Before I merge this, tell me every downstream model that will break and what changes each one needs. *Click on the image to watch the demo.* ______________________________________________________________________ ## Migrating From MS SQL Server to MS Fabric via dbt `MS SQL Server` `MS Fabric` `dbt` `Migration` `data-diff` End-to-end warehouse migration: review the stored procedures, generate dbt models targeting Fabric, run cross-database data-diff validation, schema-difference checks, build the project, and produce an interactive migration validation dashboard. **Prompt:** > We need to perform MS SQL Server to MS Fabric migration via dbt. We have SQL Server code present at `sql_server_objects/stored_procedures` — review it and create dbt models for the same with Fabric as the target, following `migration_best_practices`. Raw layer tables are already populated in Fabric. Once done, perform compilation, cross-database `data_diff` validation between existing and new code, a schema-difference check, and then build the project in Fabric. Finally, produce an interactive migration validation dashboard with migration status, validation results, lineage, etc. *Click on the image to watch the demo.* ______________________________________________________________________ ## A Platform Admin's First Day With Microsoft Fabric `MS Fabric` `Governance` `Lineage` `PII Audit` Drop altimate into an unfamiliar Fabric instance and get an immediate picture — lineage, code quality, active roles, users, PII exposures — in one prompt. **Prompt:** > I am new to the Microsoft Fabric instance. Show me the lineage, code quality, active roles, users, PII exposures etc. *Click on the image to watch the demo.* ______________________________________________________________________ ## NYC Taxi Coverage Dashboard `DuckDB` `dbt` `Airflow` `Python` **Prompt:** > Take the New York City taxi cab public dataset, bring up a DuckDB instance, and build a dashboard showing areas of maximum coverage and lowest coverage. Set up a complete dbt project with staging, intermediate, and mart layers, and create an Airflow DAG to orchestrate the pipeline. ______________________________________________________________________ ## Olist E-Commerce Analytics Pipeline `Snowflake` `Azure Data Factory` `Azure Blob Storage` `dbt` **Prompt:** > Build an end-to-end e-commerce analytics pipeline using the Olist Brazilian E-Commerce dataset. Use Azure Data Factory to ingest CSV files from Blob Storage into Snowflake raw tables, then orchestrate Snowflake stored procedures to transform data through raw → staging → mart layers (star schema with customer, product, seller dimensions and orders fact table). Create mart views for customer lifetime value, seller performance scores, and delivery SLA compliance. ______________________________________________________________________ ## Global CO2 & Climate Explorer `DuckDB-WASM` `SQL` `Browser` **Prompt:** > Build me an interactive Global CO2 & Climate Explorer dashboard using DuckDB-WASM running entirely in the browser, sourcing data from Our World in Data's CO2 dataset. Give me surprising insights about who emits the most, how that's changing, the equity angle of per-capita emissions, and which countries bear the most historical responsibility. Include an interactive SQL console with example queries showing off CTEs, window functions (LAG, RANK, SUM OVER), and make it a single index.html with a dark theme. ______________________________________________________________________ ## Spotify Analytics Pipeline Migration `PySpark` `dbt` `Databricks` `Airflow` **Prompt:** > Modernize my Spotify analytics pipeline: use the Kaggle Spotify Tracks public dataset, migrate all PySpark transformations in /spotify-analytics/ to dbt on Databricks/Spark, preserve the ML feature engineering logic (popularity tiers, mood classification, audio profile scores), add schema tests and unit tests, generate an Airflow DAG with SLAs and alerting, and validate semantic equivalence of the outputs. ______________________________________________________________________ ## US Home Sales Data Science Dashboard `Data Science` `K-Means` `OLS Regression` `R/ggplot2 Aesthetic` **Prompt:** > Download all available public US home sales data sets. Process and merge them into a unified format. Perform advanced data science on it to bring to the surface interesting insights. K-means, OLS regressions, and more. Build a single interactive dashboard with data science style charts, think violin plots, Q-Q plots and lollipop charts. Use a R/ggplot2 aesthetic. No BI style charts. ______________________________________________________________________ ## Snowflake vs Databricks Deployment Benchmark `Snowflake` `Databricks` `Benchmarking` `Cost Analysis` **Prompt:** > The NovaMart e-commerce analytics platform in the current directory is ready for deployment. Deploy to both Snowflake and Databricks, testing multiple warehouse sizes on each platform (Snowflake: X-Small, Small, Medium; Databricks: 2X-Small, Small, Medium SQL Warehouses) to find the optimal price-performance configuration. Run the full data pipeline and benchmark queries (CLV calculation, daily incremental, executive dashboard) on each warehouse size, capturing execution time, credits/DBUs consumed, and bytes scanned. Generate a cost analysis document with a recommendation matrix showing cost-per-run for each platform/size combination, and recommend the single best platform + warehouse size for production based on cost efficiency and performance. Open-source data engineering harness. 100+ specialized data engineering tools for building, validating, optimizing, and shipping data products. Use in your terminal, CI pipeline, orchestration DAGs, or as the harness for your data agents. Evaluate across platforms, independent of any single warehouse provider. [Get Started](/code/getting-started/quickstart/) [See Examples](/code/examples/) [View on GitHub](https://github.com/AltimateAI/altimate-code) ```bash npm install -g altimate-code ``` ______________________________________________________________________ ## Why Altimate Code? Every major data platform is building AI agents, but they're all locked to one ecosystem. Your data stack isn't. Altimate Code connects to your **entire** stack and lets you bring **any LLM**. No vendor lock-in, no platform tax. ### [Bring Your Own LLM](/code/configure/providers/) Works with Anthropic, OpenAI, Google, AWS Bedrock, Azure, Ollama, and 10+ more providers. Swap models without swapping your harness. No vendor lock-in. ### [Cross-Platform](/code/usage/tui/) Claude Code, Cursor, Windsurf, VS Code, and any MCP-compatible client. Terminal, IDE, CI, or web. One install, everywhere. ### [100+ Deterministic Tools](/code/configure/tools/) SQL analysis, column-level lineage, dbt integration, FinOps, warehouse connectivity. Purpose-built for data work, not hallucinated by a model. ### [Validation Layer](/code/data-engineering/validators/) SQL, lineage, and equivalence checks run in compiled Rust, not the model. 100% F1 across 1,077 anti-pattern queries, ~2 ms each, zero tokens. ### [Token Efficiency](/code/configure/context-management/) Context compaction trims the schema payload per task. The model gateway routes each call to the cheapest model that clears your accuracy bar. ### [Data Governance](/code/configure/governance/) Built-in PII detection, policy enforcement, and compliance validation across your data stack. Three agent modes — Builder, Analyst, Plan — with tool-level permissions. [**Open source & auditable**Every tool, prompt and rule is inspectable on GitHub. A requirement for regulated industries, not a nice-to-have.](https://github.com/AltimateAI/altimate-code) [**Customizable to your workflow**Bring your own rules, agents, skills and tools. Match your company's data conventions and testing patterns.](/code/configure/agents/) ______________________________________________________________________ ## 100+ specialized tools Unlike general-purpose coding agents, every tool is purpose-built for data engineering workflows. ### [SQL Anti-Pattern Detection](/code/data-engineering/tools/sql-tools/) 19 rules with confidence scoring. Catches SELECT \*, missing filters, cartesian joins, non-sargable predicates, and more. 100% accuracy across 1,077 benchmark queries. ### [Live Column-Level Lineage](/code/data-engineering/tools/lineage-tools/) Real-time lineage extraction from SQL. Trace any column back through joins, CTEs, and subqueries to its source. Not a cached graph — a living lineage that updates with every change. ### [FinOps & Cost Analysis](/code/data-engineering/tools/finops-tools/) Credit analysis, expensive query detection, warehouse right-sizing, and unused resource cleanup. Specific optimization recommendations with estimated savings. ### [Cross-Dialect Translation](/code/data-engineering/tools/sql-tools/) Deterministic engine translating SQL between Snowflake, BigQuery, Databricks, Redshift, PostgreSQL, MySQL, SQL Server, and DuckDB with lineage verification. ### [PII Detection & Safety](/code/configure/governance/) Automatic column scanning across 15+ PII categories. Safety checks and policy enforcement before every query touches production. ### [dbt Native](/code/data-engineering/tools/dbt-tools/) Manifest parsing, test generation, model scaffolding, incremental model detection, and lineage-aware refactoring. Builds models that fit your project conventions. ______________________________________________________________________ ## See it in action Build dbt models from Jira tickets, find broken Snowflake views, optimize warehouse costs, migrate PySpark to dbt, debug Airflow DAGs, and more — all from your terminal. ```bash # Analyze a query for anti-patterns and optimization opportunities > Analyze this query for issues: or # Translate SQL across dialects > /sql-translate this Snowflake query to BigQuery: # Get a cost report for your Snowflake or Databricks account > /cost-report # Scaffold a new dbt model following your project patterns > /model-scaffold fct_revenue from stg_orders and stg_payments # Generate column level lineage report for sensitive columns # from a particular table and identify owners > Trace the lineage for email_id and name columns from customer_data.customer_info table and generate a report of where sensitive data is replicated with table owners info # Migrate PySpark jobs to dbt models > Migrate this PySpark ETL to a dbt model: # Debug a failing Airflow DAG > Debug this Airflow DAG failure: ``` [Browse more examples](/code/examples/) ______________________________________________________________________ ## Benchmarks Precision matters. Here's where we stand. | Benchmark | Result | | ---------------------------------------- | ------------------------------------------------------------------------------ | | **ADE-Bench (DuckDB Local)** | **74.4%** pass rate (32/43 tasks) — 15.4 points ahead of dbt Fusion+MCP (59%). | | **SQL Anti-Pattern Detection** | 100% accuracy across 1,077 queries, 19 categories. Zero false positives. | | **Column-Level Lineage** | 100% edge match across 500 queries with complex joins, CTEs, and subqueries. | | **Snowflake Query Optimization (TPC-H)** | 16.8% average execution speedup (3.6x vs baseline). | [Full benchmark details](https://altimate.ai/benchmarks/?utm_source=altimate-code&utm_medium=docs) ______________________________________________________________________ **Learn More** — [Quickstart](/code/getting-started/quickstart/) | [Examples](/code/examples/) | [Use](/code/data-engineering/agent-modes/) | [Configure](/code/configure/) | [Interfaces](/code/usage/tui/) | [Reference](/code/reference/security-faq/) # Quickstart ______________________________________________________________________ ## Step 1: Install ```bash npm install -g altimate-code ``` ______________________________________________________________________ ## Step 2: Sign in ```bash altimate # Launch the TUI ``` On a fresh install, a welcome panel appears with a curated 6-provider picker: - **Altimate LLM Gateway** *(recommended)* — 10M tokens free, no API keys. Routes to the best model per task across Sonnet, Opus, GPT-5, and more. Sign-in opens a browser tab; complete Google or email signup and you're back in the TUI. If your terminal can't open a browser (SSH / tmux / WSL), the CLI prints the URL — paste it into a browser on your desktop. - **Anthropic** / **OpenAI** / **Google** — paste an API key or OAuth in. - **Altimate Base** — a hosted open model, free and rate limited, with no signup or API key. Requests and responses may be logged and used to improve Altimate's products, so do not send secrets or confidential code. Registration happens only after an explicit confirmation that defaults to **No**. - **Search all providers…** — full picker if you need Bedrock, Databricks AI Gateway, Cloudflare AI Gateway, Snowflake Cortex, DigitalOcean Inference, etc. Or set an environment variable and skip the picker: ```bash export ANTHROPIC_API_KEY=sk-ant-... altimate ``` Don't want to manage API keys? Choose **Altimate Base** for the no-signup, rate-limited model. Choose the [Altimate LLM Gateway](/datamates/user-guide/components/llm-gateway/) for 10M free tokens and automatic model routing. Gateway sign-in uses a loopback OAuth on `127.0.0.1:7317-7325` (falls back if the preferred port is taken). ______________________________________________________________________ ## Step 2.5: First-run scan (optional) Immediately after model setup, a **"Scan your environment?"** Yes/No dialog appears. Say **Yes** and altimate-code reads local config files (`.dbt/profiles.yml`, `dbt_project.yml`, `.git/config`) — no credentials are read or sent, and no schema, model contents, or queries leave your computer. An anonymous environment summary (e.g. "dbt project detected, no warehouse configured") may be included in the standard telemetry stream if telemetry is enabled; disable via `ALTIMATE_TELEMETRY_DISABLED=true` or the [telemetry docs](https://help.altimate.ai/code/reference/telemetry/index.md) if you want a strictly-offline scan. The scan then routes you into one of four branches: - **Found a warehouse** → offers to add + verify each connection, then index its schema. - **Found dbt project, no warehouse** → asks which warehouse it runs against and walks you through `warehouse_add`. - **In a git repo, no dbt** → suggests you `cd` into the right project and re-run. - **Nothing yet** → offers to try Altimate on a sample dbt project (bundled jaffle-shop DuckDB, no warehouse needed) or another exploratory job. Every branch ends on a numbered "**What would you like to do?**" menu in the chat — pick a job by typing the number, or free-text if none fit. **The menu is chat text, not an arrow-key picker; type your answer and press Enter.** Say **No** to the scan gate and you land on the same activation menu without the scan detail — good for users who already know what they want to run. ______________________________________________________________________ ## Step 3: Connect Your Warehouse ### Option A: Auto-detect from dbt profiles If you have a `profiles.yml` — either in your home directory's `.dbt/` folder, in your project repo, or pointed to by `DBT_PROFILES_DIR`: ```bash /discover ``` Altimate searches for `profiles.yml` in this order: `DBT_PROFILES_DIR` env var → project root (next to `dbt_project.yml`) → `/.dbt/profiles.yml`. It reads your dbt profiles and creates warehouse connections automatically. You'll see output like: ```text Found dbt project: jaffle_shop (dbt-snowflake) Found profile: snowflake_prod → Added connection 'snowflake_prod' Indexing schema... 142 tables, 1,847 columns indexed ``` ### Option B: Manual configuration Add to `.altimate-code/connections.json` in your project root: ```json { "snowflake": { "type": "snowflake", "account": "xy12345.us-east-1", "user": "dbt_user", "password": "{env:SNOWFLAKE_PASSWORD}", "warehouse": "TRANSFORM_WH", "database": "ANALYTICS", "schema": "PUBLIC", "role": "TRANSFORMER" } } ``` ```json { "bigquery": { "type": "bigquery", "project": "my-project-id", "credentials_path": "~/.config/gcloud/application_default_credentials.json" } } ``` ```json { "postgres": { "type": "postgres", "host": "localhost", "port": 5432, "database": "analytics", "user": "postgres", "password": "{env:POSTGRES_PASSWORD}" } } ``` ```json { "local": { "type": "duckdb", "path": "./data/analytics.duckdb" } } ``` All warehouse types support SSH tunneling for bastion hosts. See the [Warehouses reference](https://help.altimate.ai/code/configure/warehouses/index.md) for full options including key-pair auth, IAM roles, and ADC. Verify your connection: ```text > warehouse_test snowflake ✓ Connected successfully ``` ______________________________________________________________________ ## Step 4: Choose an Agent Mode altimate ships with specialized agent modes, each with its own tool permissions: | Mode | Access | Use when you want to... | | ----------- | ---------- | ------------------------------------------------------------------------------------------------------------- | | **Builder** | Read/Write | Create and modify SQL, dbt models, pipelines. SQL writes prompt for approval. | | **Analyst** | Read-only | Ask questions about your data, explore production data safely, run cost analysis. SQL writes denied entirely. | | **Plan** | Minimal | Plan an approach before switching to builder to execute it | Switch modes in the TUI: ```text /agent analyst ``` Or from the CLI: ```bash altimate --agent analyst ``` The **Analyst** mode is production-safe — it blocks INSERT, UPDATE, DELETE, and DROP statements at the harness level. The **Builder** mode has full read/write access for creating and editing SQL and dbt files. ______________________________________________________________________ ## Step 5: Select Skills Skills are reusable prompt templates for common workflows. Type `/` in the TUI to browse all available skills: | Skill | Purpose | | ------------------- | ------------------------------------------------- | | `/query-optimize` | Optimize slow queries with anti-pattern detection | | `/sql-review` | SQL quality gate with grading | | `/sql-translate` | Cross-dialect SQL translation | | `/cost-report` | Snowflake/Databricks cost analysis | | `/pii-audit` | Scan for PII exposure | | `/dbt-develop` | Scaffold new dbt models | | `/dbt-test` | Generate dbt tests | | `/dbt-docs` | Generate dbt documentation | | `/dbt-analyze` | Column-level lineage and impact analysis | | `/dbt-troubleshoot` | Debug dbt errors | | `/data-viz` | Interactive dashboards and visualizations | | `/teach` | Teach patterns from example files | | `/train` | Load standards from documents | You don't need to memorize these — describe what you want in plain English and the agent routes to the right skill automatically. ### Custom skills Add your own skills as Markdown files in `.altimate-code/skill/`: ```markdown --- name: cost-review description: "Review SQL queries for cost optimization" --- Analyze the SQL query for cost optimization opportunities. Focus on: $ARGUMENTS ``` Skills are loaded from these paths (highest priority first): 1. `.altimate-code/skill/` (project) 1. `~/.altimate-code/skills/` (global) 1. Custom paths via config: ```json { "skills": { "paths": ["./my-skills", "~/shared-skills"] } } ``` ______________________________________________________________________ ## Step 6: Configure Permissions Governance is enforced at the harness level, not via prompts. Every tool has a permission level: `allow`, `ask`, or `deny`. ### Per-agent permissions Set tool permissions for each agent mode in `altimate-code.json`: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "bash": { "dbt docs generate": "allow", "*": "deny" } } }, "builder": { "permission": { "write": "allow", "edit": "allow", "bash": { "dbt *": "allow", "rm -rf *": "deny" } } } } } ``` ### Project rules with AGENTS.md Define project-wide conventions in an `AGENTS.md` file at your project root. These rules are automatically loaded into every agent's system prompt: ```markdown # Project Rules - All staging models must be prefixed with `stg_` - Never run queries without a WHERE clause on production tables - Use `ref()` instead of hardcoded table names in dbt models - All new models require at least one unique test and one not_null test ``` ### Default permissions by agent mode | Agent | File writes | SQL writes | Bash | Training | | ------- | ----------- | -------------------------- | --------------------------------- | -------- | | Builder | allow | ask (prompts for approval) | ask | allow | | Analyst | deny | deny (blocked entirely) | deny (safe commands auto-allowed) | allow | | Plan | deny | deny | deny | deny | ______________________________________________________________________ ## Step 7: Build Your First Artifact In the TUI, paste this prompt: ```text Build a NYC taxi analytics dashboard using BigQuery public data and dbt for transformations. Include geographic demand analysis with pickup/dropoff hotspots, top routes, airport traffic, and borough comparisons. Add revenue analytics with fare breakdowns, fare distribution, tip analysis, payment trends, and revenue-per-mile by route. ``` ______________________________________________________________________ ## What's Next - [Agent Modes](https://help.altimate.ai/code/data-engineering/agent-modes/index.md): Deep dive into each mode's capabilities - [Warehouses Reference](https://help.altimate.ai/code/configure/warehouses/index.md): All warehouse types, auth methods, SSH tunneling - [Config Reference](https://help.altimate.ai/code/configure/config/index.md): Full config file schema - [CI & Automation](https://help.altimate.ai/code/usage/ci-headless/index.md): Run altimate in automated pipelines # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## How to check your version ```bash altimate --version ``` ## How to upgrade ```bash npm update -g altimate-code ``` After upgrading, the TUI welcome banner shows what changed since your previous version. ______________________________________________________________________ ## [0.5.6] - 2026-03-21 ### Added - Snowflake Cortex as a built-in AI provider with PAT authentication (#349) - 26 models: Claude, OpenAI, Llama, Mistral, DeepSeek - Tool calling support for Claude and OpenAI models - Zero token cost — billing via Snowflake credits - Cortex-specific request transforms (`max_completion_tokens`, tool stripping, synthetic stop) ## [0.5.0] - 2026-03-18 ### Added - Smooth streaming mode for TUI response rendering (#281) - Ship builtin skills to customers via postinstall (#279) - `/configure-claude` and `/configure-codex` built-in commands (#235) ### Fixed - Brew formula stuck at v0.3.1, version normalization in publish pipeline (#286) - Harden auth field handling for all warehouse drivers (#271) - Suppress console logging that corrupts TUI display (#269) ## [0.4.9] - 2026-03-18 ### Added - Script to build and run compiled binary locally (#262) ### Fixed - Snowflake auth — support all auth methods (`password`, `keypair`, `externalbrowser`, `oauth`), fix field name mismatches (#268) - dbt tool regression — schema format mismatch, silent failures, wrong results (#263) - `altimate-dbt compile`, `execute`, and children commands fail with runtime errors (#255) - `Cannot find module @altimateai/altimate-core` on `npm install` (#259) - Dispatcher tests fail in CI due to shared module state (#257) ### Changed - CI: parallel per-target builds — 12 jobs, ~5 min wall clock instead of ~20 min (#254) - CI: faster release — build parallel with test, lower compression, tighter timeouts (#251) - Docker E2E tests skip in CI unless explicitly opted in (#253) ## [0.4.2] - 2026-03-18 ### Breaking Changes - **Python engine eliminated** — all 73 tool methods now run natively in TypeScript. No Python, pip, venv, or `altimate-engine` installation required. Fixes #210. ### Added - `@altimateai/drivers` shared workspace package with 10 database drivers (Snowflake, BigQuery, PostgreSQL, Databricks, Redshift, MySQL, SQL Server, Oracle, DuckDB, SQLite) - Direct `@altimateai/altimate-core` napi-rs bindings — SQL analysis calls go straight to Rust (no Python intermediary) - dbt-first SQL execution — automatically uses `profiles.yml` connection when in a dbt project - Warehouse telemetry (5 event types: connect, query, introspection, discovery, census) - 340+ new tests including E2E tests against live Snowflake, BigQuery, and Databricks accounts - Encrypted key-pair auth support for Snowflake (PKCS8 PEM with passphrase) - Comprehensive driver documentation at `docs/docs/drivers.md` ### Fixed - Python bridge connection failures for UV, conda, and non-standard venv setups (#210) - SQL injection in finops/schema queries (parameterized queries + escape utility) - Credential store no longer saves plaintext passwords - SSH tunnel cleanup on SIGINT/SIGTERM - Race condition in connection registry for concurrent access - Databricks DATE_SUB syntax - Redshift describeTable column name - SQL Server describeTable includes views - Dispatcher telemetry wrapped in try/catch - Flaky test timeouts ### Removed - `packages/altimate-engine/` — entire Python package (~17,000 lines) - `packages/opencode/src/altimate/bridge/` — JSON-RPC bridge - `.github/workflows/publish-engine.yml` — PyPI publish workflow ## [0.4.1] - 2026-03-16 ### Added - Local-first tracing system replacing Langfuse (#183) ### Fixed - Engine not found when user's project has `.venv` in cwd — managed venv now takes priority (#199) - Missing `[warehouses]` pip extra causing FinOps tools to fail with "snowflake-connector-python not installed" (#199) - Engine install trusting stale manifest when venv/Python binary was deleted (#199) - Extras changes not detected on upgrade — manifest now tracks installed extras (#199) - Windows path handling for dev/cwd venv resolution (#199) - Concurrent bridge startup race condition — added `pendingStart` mutex (#199) - Unhandled spawn `error` event crashing host process on invalid Python path (#199) - Bridge hung permanently after ping failure — child process now cleaned up (#199) - `restartCount` incorrectly incremented on signal kills, prematurely disabling bridge (#199) - TUI prompt corruption from engine bootstrap messages writing to stderr (#180) - Tracing exporter timeout leaking timers (#191) - Feedback submission failing when repo labels don't exist (#188) - Pre-release security and resource cleanup fixes for tracing (#197) ## [0.4.0] - 2026-03-15 ### Added - Data-viz skill for data storytelling and visualizations (#170) - AI Teammate training system with learn-by-example patterns (#148) ### Fixed - Sidebar shows "OpenCode" instead of "Altimate Code" after upstream merge (#168) - Prevent upstream tags from polluting origin (#165) - Show welcome box on first CLI run, not during postinstall (#163) ### Changed - Engine version bumped to 0.4.0 ## [0.3.1] - 2026-03-15 ### Fixed - Database migration crash when upgrading from v0.2.x — backfill NULL migration names for Drizzle beta.16 compatibility (#161) - Install banner not visible during `npm install` — moved output from stdout to stderr (#161) - Verbose changelog dump removed from CLI startup (#161) - `altimate upgrade` detection broken — `method()` and `latest()` referenced upstream `opencode-ai` package names instead of `@altimateai/altimate-code` (#161) - Brew formula detection and upgrade referencing `opencode` instead of `altimate-code` (#161) - Homebrew tap updated to v0.3.0 (was stuck at 0.1.4 due to expired `HOMEBREW_TAP_TOKEN`) (#161) - `.opencode/memory/` references in docs updated to `.altimate-code/memory/` (#161) - Stale `@opencode-ai/plugin` reference in CONTRIBUTING.md (#161) ### Changed - CI now uses path-based change detection to skip unaffected jobs (saves ~100s on non-TS changes) (#161) - Release workflow gated on test job passing (#157) - Upstream merge restricted to published GitHub releases only (#150) ## [0.3.0] - 2026-03-15 ### Added - AI-powered prompt enhancement (#144) - Altimate Memory — persistent cross-session memory with TTL, namespaces, citations, and audit logging (#136) - Upstream merge with OpenCode v1.2.26 (#142) ### Fixed - Sentry review findings from PR #144 (#147) - OAuth token refresh retry and error handling for idle timeout (#133) - Welcome banner on first CLI run after install/upgrade (#132) - `@altimateai/altimate-code` npm package name restored after upstream rebase - Replace `mock.module()` with `spyOn()` to fix 149 test failures (#153) ### Changed - Rebrand user-facing references to Altimate Code (#134) - Bump `@modelcontextprotocol/sdk` dependency (#139) - Engine version bumped to 0.3.0 ## [0.2.5] - 2026-03-13 ### Added - `/feedback` command and `feedback_submit` tool for in-app user feedback (#89) - Altimate MCP manager — dynamic MCP server management (#99) - Non-interactive mode for `mcp add` command with input validation - `mcp remove` command - Upstream merge with OpenCode v1.2.20 ### Fixed - TUI crash after upstream merge (#98) - `GitlabAuthPlugin` type incompatibility in plugin loader (#92) - All test failures from fork restructure (#91) - CI/CD workflow paths updated from `altimate-code` to `opencode` - Fallback to global config when not in a git repo - PR standards workflow `TEAM_MEMBERS` ref corrected from `dev` to `main` (#101) ### Changed - Removed self-hosted runners from public repo CI (#110) - Migrated CI/release to ARC runners (#93, #94) - Reverted Windows tests to `windows-latest` (#95) - Engine version bumped to 0.2.5 ## [0.2.4] - 2026-03-04 ### Added - E2E tests for npm install pipeline: postinstall script, bin wrapper, and publish output (#50) ## [0.2.3] - 2026-03-04 ### Added - Postinstall welcome banner and changelog display after upgrade (#48) ### Fixed - Security: validate well-known auth command type before execution, add confirmation prompt (#45) - CI/CD: SHA-pin all GitHub Actions, per-job least-privilege permissions (#45) - MCP: fix copy-paste log messages, log init errors, prefix floating promises (#45) - Session compaction: clean up compactionAttempts on abort to prevent memory leak (#45) - Telemetry: retry failed flush events once with buffer-size cap (#45, #46) - Telemetry: flush events before process exit (#46) - TUI: resolve worker startup crash from circular dependency (#47) - CLI: define ALTIMATE_CLI build-time constants for correct version reporting (#41) - Address 4 issues found in post-v0.2.2 commits (#49) - Address remaining code review issues from PR #39 (#43) ### Changed - CI/CD: optimize pipeline with caching and parallel builds (#42) ### Docs - Add security FAQ (#44) ## [0.2.2] - 2026-03-05 ### Fixed - Telemetry init: `Config.get()` failure outside Instance context no longer silently disables telemetry - Telemetry init: called early in CLI middleware and worker thread so MCP/engine/auth events are captured - Telemetry init: promise deduplication prevents concurrent init race conditions - Telemetry: pre-init events are now buffered and flushed (previously silently dropped) - Telemetry: user email is SHA-256 hashed before sending (privacy) - Telemetry: error message truncation standardized to 500 chars across all event types - Telemetry: `ALTIMATE_TELEMETRY_DISABLED` env var now actually checked in init - Telemetry: MCP disconnect reports correct transport type instead of hardcoded `stdio` - Telemetry: `agent_outcome` now correctly reports `"error"` outcome for failed sessions ### Changed - Auth telemetry events use session context when available instead of hardcoded `"cli"` ## [0.2.1] - 2026-03-05 ### Added - Comprehensive telemetry instrumentation: 25 event types across auth, MCP servers, Python engine, provider errors, permissions, upgrades, context utilization, agent outcomes, workflow sequencing, and environment census - Telemetry docs page with event table, privacy policy, opt-out instructions, and contributor guide - AppInsights endpoint added to network firewall documentation - `categorizeToolName()` helper for tool classification (sql, schema, dbt, finops, warehouse, lineage, file, mcp) - `bucketCount()` helper for privacy-safe count bucketing ### Fixed - Command loading made resilient to MCP/Skill initialization failures ### Changed - CLI binary renamed from `altimate-code` to `altimate` ## [0.2.0] - 2026-03-04 ### Added - Context management: auto-compaction with overflow recovery, observation masking, and loop protection - Context management: data-engineering-aware compaction template preserving warehouse, schema, dbt, and lineage context - Context management: content-aware token estimation (code, JSON, SQL, text heuristics) - Context management: observation masking replaces pruned tool outputs with fingerprinted summaries - Context management: provider overflow detection for Azure OpenAI patterns - CLI observability: telemetry module with session, generation, tool call, and error tracking - `/discover` command for data stack setup with project_scan tool - User documentation for context management configuration ### Fixed - ContextOverflowError now triggers automatic compaction instead of a dead-end error - `isOverflow()` correctly reserves headroom for models with separate input/output limits - `NamedError.isInstance()` no longer crashes on null input - Text part duration tracking now preserves original start timestamp - Compaction loop protection: max 3 consecutive attempts per turn, counter resets between turns - Negative usable context guard for models where headroom exceeds base capacity ### Changed - Removed cost estimation and complexity scoring bindings - Docs: redesigned homepage with hero, feature cards, and pill layouts - Docs: reorganized sidebar navigation for better discoverability ## [0.1.10] - 2026-03-03 ### Fixed - Build: resolve @opentui/core parser.worker.js via import.meta.resolve for monorepo hoisting - Build: output binary as `altimate-code` instead of `opencode` - Publish: update Docker/AUR/Homebrew references from anomalyco/opencode to AltimateAI/altimate-code - Publish: make Docker/AUR/Homebrew steps non-fatal - Bin wrapper: look for `@altimateai/altimate-code-*` scoped platform packages - Postinstall: resolve `@altimateai` scoped platform packages - Dockerfile: update binary paths and names ## [0.1.9] - 2026-03-02 ### Fixed - Build: fix solid-plugin import to use bare specifier for monorepo hoisting - CI: install warehouse extras for Python tests (duckdb, boto3, etc.) - CI: restrict pytest collection to tests/ directory - CI: fix all ruff lint errors in Python engine - CI: fix remaining TypeScript test failures (agent rename, config URLs, Pydantic model) - Update theme schema URLs and documentation references to altimate-code.dev ## [0.1.8] - 2026-03-02 ### Changed - Rename npm scope from `@altimate` to `@altimateai` for all packages - Wrapper package is now `@altimateai/altimate-code` (no `-ai` suffix) ### Fixed - CI: test fixture writes config to correct filename (`altimate-code.json`) - CI: add `dev` optional dependency group to Python engine for pytest/ruff ## [0.1.7] - 2026-03-02 ### Changed - Improve TUI logo readability: redesign M, E, T, I letter shapes - Add two-tone logo color: ALTIMATE in peach, CODE in purple ### Fixed - Release: npm publish glob now finds scoped package directories - Release: PyPI publish skips existing versions instead of failing ## [0.1.5] - 2026-03-02 ### Added - Anthropic OAuth plugin ported in-tree - Docs site switched from Jekyll to Material for MkDocs ### Fixed - Build script: restore `.trim()` on models API JSON to prevent syntax error in generated `models-snapshot.ts` - Build script: fix archive path for scoped package names in release tarball/zip creation ## [0.1.0] - 2025-06-01 ### Added - Initial open-source release - SQL analysis and formatting via Python engine - Column-level lineage tracking - dbt integration (profiles, lineage, `+` operator) - Warehouse connectivity (Snowflake, BigQuery, Databricks, Postgres, DuckDB, MySQL) - AI-powered SQL code review - TUI interface with Solid.js - MCP (Model Context Protocol) server support - Auto-bootstrapping Python engine via uv # Network Configure network settings for proxied or restricted environments. ## HTTP Proxy Set the `HTTPS_PROXY` environment variable: ```bash export HTTPS_PROXY=http://proxy.example.com:8080 altimate ``` Also supports `HTTP_PROXY` and `NO_PROXY`: ```bash export HTTPS_PROXY=http://proxy.example.com:8080 export NO_PROXY=localhost,127.0.0.1,.internal.com ``` ## Custom CA Certificates For environments with custom certificate authorities: ```bash export NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.crt altimate ``` This is common in corporate environments with TLS inspection. ## Firewall Requirements altimate needs outbound HTTPS access to: | Destination | Purpose | | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | Your LLM provider API | Model inference (Anthropic, OpenAI, etc.) | | Official Altimate Base gateway (embedded in release), or the host set by `ALTIMATE_BASE_GATEWAY_URL` | Altimate Base registration and inference when you explicitly enable Altimate Base | | `registry.npmjs.org` | Package updates | | `models.dev` | Model catalog (can be disabled) | | Your warehouse endpoints | Database connections | | `eastus-8.in.applicationinsights.azure.com` | Telemetry (Azure Application Insights) | ### Disable Model Fetching If `models.dev` is unreachable: ```bash export ALTIMATE_CLI_DISABLE_MODELS_FETCH=true ``` Or provide a local models file: ```bash export ALTIMATE_CLI_MODELS_PATH=/path/to/models.json ``` # Security FAQ Answers to the most common security questions about running Altimate Code in your environment. ______________________________________________________________________ ## Does Altimate Code send my data to external services? Altimate Code sends prompts and context to the LLM provider you configure (Anthropic, OpenAI, Azure OpenAI, AWS Bedrock, etc.). **You choose the provider.** No data is sent anywhere else except optional [telemetry](#what-telemetry-is-collected), which contains no code, queries, or credentials. Altimate Base is an optional hosted provider. Its confirmation dialog explains that requests and responses are logged and may be used to improve Altimate products and services; do not send secrets or confidential code. The dialog defaults to **No**, and no registration request is made unless you explicitly accept. This request logging is part of the Altimate Base service and is separate from anonymous product telemetry. **What identifies you to Altimate Base.** Registration sends a SHA-256 hash of a locally generated installation secret — the secret itself never leaves your machine. That hash is stable, so logged requests from this installation are linked to one another. This is deliberate: it is how the free allowance is enforced. Running `altimate providers logout altimate-base` disconnects the provider but **keeps** the installation identity, by design, so that logging out and back in cannot mint a fresh allowance. Each inference request also carries a session identifier used for rate limiting and abuse control. Altimate Base is therefore pseudonymous, not anonymous. To reset the local identity completely, delete `altimate-base.json` from the application data directory — `$XDG_DATA_HOME/altimate-code/`, which defaults to `~/.local/share/altimate-code/` on both macOS and Linux — while the app is closed. This is outside the supported flow, and the gateway applies its own network-level rate limits. If you use a self-hosted or VPC-deployed model (e.g., AWS Bedrock, Azure OpenAI), your data never leaves your cloud account. ## Can the AI read my database credentials? Altimate Code needs database credentials to connect to your warehouse. Credentials are stored locally in your project's `altimate-code.json` or passed via environment variables. They are **never** included in telemetry, logged, or sent to any service other than your database. Tip Prefer environment variables or your cloud provider's secret manager over hardcoding credentials in config files. Add `altimate-code.json` to `.gitignore` if it contains connection strings. ## What can the agent actually execute? Altimate Code can read files, write files, and run shell commands, but only with your permission. The [permission system](https://help.altimate.ai/code/configure/permissions/index.md) lets you control every tool: | Level | Behavior | | --------- | --------------------------- | | `"allow"` | Runs without confirmation | | `"ask"` | Prompts you before each use | | `"deny"` | Blocked entirely | By default, destructive operations like `bash`, `write`, and `edit` require confirmation. You can further restrict specific commands: ```json { "permission": { "bash": { "*": "ask", "dbt *": "allow", "git status": "allow", "DROP *": "deny", "rm *": "deny" } } } ``` ## Can I prevent the agent from modifying production databases? Yes. Use pattern-based permissions to deny destructive SQL: ```json { "permission": { "bash": { "*": "ask", "DROP *": "deny", "DELETE *": "deny", "TRUNCATE *": "deny", "ALTER *": "deny" } } } ``` You can also configure per-agent permissions. For example, restrict the `analyst` agent to read-only: ```json { "agent": { "analyst": { "permission": { "write": "deny", "edit": "deny", "bash": { "SELECT *": "allow", "*": "deny" } } } } } ``` ## What network endpoints does Altimate Code contact? | Destination | Purpose | | ------------------------------------------- | ------------------------------------------------------------------------- | | Your configured LLM provider | Model inference | | Altimate Base gateway | Registration and inference only after you explicitly enable Altimate Base | | Your warehouse endpoints | Database queries | | `registry.npmjs.org` | Package updates | | `models.dev` | Model catalog (can be disabled) | | `eastus-8.in.applicationinsights.azure.com` | Telemetry (can be disabled) | No other outbound connections are made. See the [Network reference](https://help.altimate.ai/code/reference/network/index.md) for proxy and firewall configuration. ## Can I run Altimate Code without internet access? Yes, with constraints. You need: 1. **A locally accessible LLM**, either a self-hosted model or a provider reachable from your network 1. **Model catalog disabled** by setting `ALTIMATE_CLI_DISABLE_MODELS_FETCH=true` or providing a local models file 1. **Telemetry disabled** by setting `ALTIMATE_TELEMETRY_DISABLED=true` ```bash export ALTIMATE_CLI_DISABLE_MODELS_FETCH=true export ALTIMATE_TELEMETRY_DISABLED=true export ALTIMATE_CLI_MODELS_PATH=/path/to/models.json ``` ## What telemetry is collected? Anonymous usage telemetry, including event names, token counts, timing, and error types. **Never** code, queries, credentials, file paths, or prompt content. See the full [Telemetry reference](https://help.altimate.ai/code/reference/telemetry/index.md) for the complete event list. Disable telemetry entirely: ```json { "telemetry": { "disabled": true } } ``` Or via environment variable: ```bash export ALTIMATE_TELEMETRY_DISABLED=true ``` ### How does Altimate Code identify users for analytics? - **Logged-in users:** Your email is SHA-256 hashed before sending. We never see your raw email. - **Anonymous users:** A random UUID (`crypto.randomUUID()`) is generated on first run and stored at `~/.altimate/machine-id`. This is NOT tied to your hardware, OS, or identity — it's purely random. - **Both identifiers** are only sent when telemetry is enabled. Disable with `ALTIMATE_TELEMETRY_DISABLED=true` or the `telemetry.disabled` config option. - **No fingerprinting:** We do not use browser fingerprinting, hardware IDs, MAC addresses, or IP-based tracking. - **CLI auth flow:** When you sign in via `altimate auth login`, the anonymous machine ID is included in the authorization URL and associated with your account in product analytics for funnel analysis. This is suppressed when you disable telemetry — via `ALTIMATE_TELEMETRY_DISABLED=true` or the `telemetry.disabled` config option — and the machine ID is omitted from the URL entirely. ### What happens on first launch? A single `first_launch` event is sent containing only: - The installed version (e.g., "0.5.9") - Whether this is a fresh install or upgrade (boolean) - Which installer was used (`curl`, `powershell`, `npm`, `vscode-extension`, `local`, or `unknown` — what every upgrade from a version predating this field reports) - Your anonymous machine ID (random UUID) No code, queries, file paths, or personal information is included. This event helps us understand adoption and is fully opt-out-able. The install scripts (`altimate.sh/install`, `install.ps1`), the npm postinstall, and the VS Code extension's installer send nothing themselves and contact no telemetry endpoint. They only record the version and installer name to a local file that the CLI reads on its next run, so the opt-out above decides whether anything is ever transmitted. One caveat on the config-file opt-out The environment variables (`ALTIMATE_TELEMETRY_DISABLED`, `OPENCODE_DISABLE_TELEMETRY`) are always honoured. The `telemetry.disabled` **config key** is read during telemetry startup, which can run before the CLI's config is resolvable — and in that case startup currently proceeds with telemetry enabled. A user who has opted out via the config key alone may therefore still have this event transmitted. Use an environment variable if you need a guarantee. ## What happens when I authenticate via a well-known URL? When you run `altimate auth login `, the CLI fetches `/.well-known/altimate-code` to discover the server's auth command. Before executing anything: 1. **Validation.** The auth command must be an array of strings. Malformed or unexpected types are rejected. 1. **Confirmation prompt.** You are shown the exact command and must explicitly approve it before it runs. ```text $ altimate auth login https://mcp.example.com ◆ The server requests to run: gcloud auth print-access-token. Allow? │ ● Yes / ○ No ``` This prevents a malicious server from silently executing arbitrary commands on your machine. ## Are MCP servers a security risk? MCP (Model Context Protocol) servers extend Altimate Code with additional tools. They run as local subprocesses or connect via SSE/HTTP. Security considerations: - **Only install MCP servers you trust.** They run with the same permissions as your user account. - **MCP servers can access your filesystem and network.** Review what a server does before adding it. - **MCP tool calls go through the permission system.** You can set MCP tools to `"ask"` or `"deny"` like any other tool. Warning Third-party MCP servers are not reviewed or audited by Altimate. Treat them like any other third-party dependency: review the source, check for updates, and limit their access. ## What is MCP auto-discovery? Altimate Code can automatically discover MCP server definitions from other AI tools installed on your machine. This saves you from manually re-configuring servers you already use elsewhere. Sources include: | Source | Config file | Scope | | -------------- | -------------------------- | -------------- | | VS Code | `.vscode/mcp.json` | Project | | Cursor | `.cursor/mcp.json` | Project | | GitHub Copilot | `.github/copilot/mcp.json` | Project | | Claude Code | `.mcp.json` | Project + Home | | Gemini CLI | `.gemini/settings.json` | Project + Home | | Claude Desktop | `~/.claude.json` | Home | **Security model:** - **Home-directory configs** (your personal machine config) are treated as trusted and auto-enabled, since you installed them. - **Project-scoped configs** (checked into a repo) are discovered but **not auto-connected**. They are loaded with `enabled: false` and shown in a notification. Ask the assistant to enable them, or disable auto-discovery entirely with `experimental.auto_mcp_discovery: false`. - **Sensitive details are redacted** in discovery notifications. Server commands and URLs are only shown when you explicitly inspect them. - **Prototype pollution, command injection, and path traversal** are hardened against with input validation and `Object.create(null)` result objects. **To disable auto-discovery entirely:** ```json { "experimental": { "auto_mcp_discovery": false } } ``` Tip If your project repository contains `.vscode/mcp.json` or similar config files from other contributors, auto-discovery will find them but **will not start them** until you approve. Always review discovered servers before enabling them. ## How does the SQL analysis engine work? As of v0.4.2, all 73 tool methods run natively in TypeScript via `@altimateai/altimate-core` (Rust napi-rs bindings). There is no Python dependency. The engine executes in-process with no subprocess, no network port, and no external service. ## What is `sensitive_write` protection? Altimate Code classifies writes to credential-adjacent files as `sensitive_write` operations. These always trigger a confirmation prompt, even if `write` is set to `"allow"` in your config. Protected patterns include: - **Environment files** such as `.env`, `.env.local`, `.env.production`, `.env.staging` - **Credential files** such as `credentials.json`, `service-account.json`, `.npmrc`, `.pypirc`, `.netrc`, `.pgpass` - **Secret key directories** such as `.ssh/`, `.aws/`, `.gnupg/`, `.gcloud/`, `.kube/`, `.docker/` - **Private key extensions** such as `*.pem`, `*.key`, `*.p12`, `*.pfx` - **Version control** files such as `.git/config`, `.git/hooks/*` You can approve per-file with "Allow always" to reduce prompt fatigue. The approval persists for your current session only. On macOS and Windows, matching is case-insensitive. ## Does Altimate Code store conversation history? Yes. Altimate Code persists session data locally on your machine: - **Session messages** are stored in a local SQLite database so you can resume, review, and revert conversations. - **Prompt history** (your recent inputs) is saved to `~/.state/prompt-history.jsonl` for command-line recall. This data **never** leaves your machine. It is not sent to any service or included in telemetry. You can delete it at any time by removing the local database and history files. Note Your LLM provider may have its own data retention policies. Check your provider's terms to understand how they handle API requests. ## How do I secure Altimate Code in a team environment? 1. **Use project-level config.** Place `altimate-code.json` in your project root with appropriate permission defaults. This ensures consistent security settings across the team. 1. **Restrict dangerous operations.** Deny destructive SQL and shell commands at the project level so individual users can't accidentally bypass them. 1. **Use environment variables for secrets.** Never commit credentials. Use `ALTIMATE_CLI_PYTHON`, warehouse connection env vars, and your cloud provider's secret management. 1. **Review MCP servers.** Maintain a list of approved MCP servers. Don't let individual developers add arbitrary servers to shared configurations. 1. **Lock down agent permissions.** Give each agent only the permissions it needs. The `analyst` agent doesn't need `write` access. The `builder` agent doesn't need `DROP` permissions. ## Can AI-generated SQL damage my database? Altimate Code generates SQL based on your instructions and schema context. Like any generated code, it should be reviewed before execution. The permission system defaults to `"ask"` for shell commands, so you'll see every query before it runs. For additional safety: - Use a **read-only database user** for exploration and analysis - **Deny destructive DDL/DML** via pattern-based permissions - Run against a **staging environment** before production - Use the `analyst` agent with restricted permissions for ad-hoc queries ## What protections does Altimate Code have for file access? Altimate Code includes several layers of protection to keep the agent within your project: - **Project boundary enforcement.** File operations check that paths stay within your project directory (or git worktree for monorepos). Attempts to read or write outside the project trigger an `external_directory` permission prompt. - **Symlink-aware path resolution.** Symlinks inside the project that point outside are detected and blocked. This prevents an agent from reading or writing outside your project through symlinks. - **Path traversal blocking.** Paths containing `../` sequences that would escape the project are rejected with an "Access denied" error. - **Sensitive file protection.** Writing to credential files (`.env`, `.ssh/`, `.aws/`, private keys) triggers a confirmation prompt, even inside the project. See [below](#why-am-i-being-prompted-to-edit-env-files) for details. - **Bash command analysis.** The bash tool parses commands with tree-sitter to detect file operations (`rm`, `cp`, `mv`, etc.) targeting paths outside your project, and prompts for permission. - **Non-git project safety.** For projects outside a git repository, the boundary is strictly the working directory (not the entire filesystem). These protections operate at the application level. For additional isolation, you can run Altimate Code inside a Docker container or VM. ## Why am I being prompted to edit `.env` files? Altimate Code prompts before modifying files that commonly contain credentials or security-sensitive configuration, even when they're inside your project. This includes: | Pattern | Examples | | -------------------------- | ------------------------------------------------------------------------------------ | | **Environment files** | `.env`, `.env.local`, `.env.production`, `.env.staging` | | **Credential files** | `credentials.json`, `service-account.json`, `.npmrc`, `.pypirc`, `.netrc`, `.pgpass` | | **Secret key directories** | `.ssh/`, `.aws/`, `.gnupg/`, `.gcloud/`, `.kube/`, `.docker/` | | **Private keys** | `*.pem`, `*.key`, `*.p12`, `*.pfx` | | **Version control** | `.git/config`, `.git/hooks/*` | When you see this prompt: - **"Allow once"** approves this single edit - **"Allow always"** approves edits to this specific file for the rest of the session (resets on restart) If you frequently edit `.env` files and find the prompts disruptive, click "Allow always" on the first prompt for each file. You won't be asked again for that file during your session. Tip This protection does **not** block reading these files, only writing. The agent can still read your `.env` to understand configuration without prompting. ## What commands are blocked or prompted by default? Altimate Code applies safe defaults so you don't have to configure anything for common protection: | Command | Default | Why | | ---------------------- | ------------ | ----------------------------------------------------------------------- | | `rm -rf *`, `rm -fr *` | **Prompted** | Recursive deletion can be destructive. You'll see what's being deleted. | | `git push --force *` | **Prompted** | Force-push can overwrite shared branch history. | | `git reset --hard *` | **Prompted** | Discards uncommitted changes permanently. | | `git clean -f *` | **Prompted** | Removes untracked files permanently. | | `DROP DATABASE *` | **Blocked** | Almost never intentional in an agent context. | | `DROP SCHEMA *` | **Blocked** | Almost never intentional in an agent context. | | `TRUNCATE *` | **Blocked** | Irreversible data deletion. | | All other commands | **Prompted** | You approve each command before it runs. | **"Prompted"** means you'll see the command and can approve or reject it. **"Blocked"** means the agent cannot run it at all; you must override in config. To override defaults, add rules in `altimate-code.json`. See [Permissions](https://help.altimate.ai/code/configure/permissions/index.md) for the full configuration reference. ## Best practices for staying safe 1. **Review before approving.** The permission prompt shows you exactly what will happen, including diffs for file edits and the full command for bash. Take a moment to read it. 1. **Work on a branch.** Let the agent work on a feature branch so you can review changes before merging. Git gives you a full safety net. This is the single most effective protection. 1. **Use per-agent permissions.** Give each agent only what it needs. The `analyst` agent doesn't need write access. See [Permissions](https://help.altimate.ai/code/configure/permissions/index.md) for examples. 1. **Use read-only database credentials for exploration.** When using the agent for analysis or ad-hoc queries, connect with a read-only database user. 1. **Commit before large operations.** If the agent is about to make sweeping changes, commit your current state first. You can always `git stash` or revert. 1. **Block truly dangerous database operations.** The defaults block `DROP DATABASE`, `DROP SCHEMA`, and `TRUNCATE`. You can extend this: ```json { "permission": { "bash": { "*": "ask", "DROP *": "deny", "DELETE FROM *": "deny", "TRUNCATE *": "deny" } } } ``` 1. **Use Docker for sensitive environments.** If you're working with production systems or sensitive data, running Altimate Code in a container provides OS-level isolation on top of the permission system. ## Where should I report security vulnerabilities? **Do not open public GitHub issues for security vulnerabilities.** Instead, email **security@altimate.ai** with a description, reproduction steps, and your severity assessment. You'll receive acknowledgment within 48 hours. See the full [Security Policy](https://github.com/AltimateAI/altimate-code/blob/main/SECURITY.md) for details. # Telemetry Altimate Code collects anonymous usage data to help us improve the product. This page describes what we collect, why, and how to opt out. ## What We Collect We collect the following categories of events: | Event | Description | | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `session_start` | A new CLI session begins | | `session_end` | A CLI session ends (includes duration) | | `session_forked` | A session is forked from an existing one | | `generation` | An AI model generation (step) completes — model ID, provider ID, agent, finish reason, cost, duration, and token breakdown: input, output, and when available: reasoning tokens (reasoning models only), cache-read tokens (prompt cache hit), cache-write tokens (new cache entry). No prompt content. | | `tool_call` | A tool is invoked (tool name and category — no arguments or output) | | `native_call` | A native engine call completes (method name and duration — no arguments) | | `command` | A CLI command is executed (command name only) | | `error` | An unhandled error occurs (error type and truncated message, but no stack traces) | | `auth_login` | Authentication succeeds or fails (provider and method, but no credentials) | | `auth_logout` | A user logs out (provider only) | | `mcp_server_status` | An MCP server connects, disconnects, or errors (server name and transport) | | `provider_error` | An AI provider returns an error (error type and HTTP status, but no request content) | | `engine_started` | The native tool engine initializes (version and duration) | | `engine_error` | The native tool engine fails to start (phase and truncated error) | | `upgrade_attempted` | A CLI upgrade is attempted (version and method) | | `permission_denied` | A tool permission is denied (tool name and source) | | `doom_loop_detected` | A repeated tool call pattern is detected (tool name and count) | | `compaction_triggered` | Context compaction runs (strategy and token counts) | | `tool_outputs_pruned` | Tool outputs are pruned during compaction (count) | | `environment_census` | Environment snapshot on project scan (warehouse types, dbt presence, dbt materialization distribution, snapshot/seed counts, feature flags, but no hostnames or project names) | | `context_utilization` | Context window usage per generation (token counts, utilization percentage, cache hit ratio) | | `agent_outcome` | Agent session outcome (agent type, tool/generation counts, cost, outcome status). Also includes diagnostic fields populated for non-completed outcomes: `final_tool` (last tool name, including MCP-namespaced like `mcp__atlassian__getJiraIssue`), `error_class` (classified via `classifyError` patterns or `unknown`), and `reason` (PII-masked error message — capped at 500 chars for `error`, 200 chars for `aborted`; `no_tools_invoked` for `abandoned`; `user_cancelled` fallback when no explicit reason). API key prefixes (`sk-`, `sk-ant-`, `Bearer …`) are redacted at extraction. | | `error_recovered` | Successful recovery from a transient error (error type, strategy, attempt count) | | `mcp_server_census` | MCP server capabilities after connect (tool and resource counts, but no tool names) | | `context_overflow_recovered` | Context overflow is handled (strategy) | | `skill_used` | A skill is loaded (skill name, source — `builtin`, `global`, or `project`, and trigger — `user`, `auto`, or `suggestion` — no skill content) | | `plan_revision` | A plan revision occurs in Plan mode (revision_number, action: `refine`, `approve`, `reject`, or `cap_reached`) | | `feature_suggestion` | A post-connection feature suggestion is shown (suggestion_type, suggestions_shown, warehouse_type — no user input) | | `sql_execute_failure` | A SQL execution fails (warehouse type, query type, error message, PII-masked SQL — no raw values) | | `core_failure` | An internal tool error occurs (tool name, category, error class, truncated error message, PII-safe input signature, and optionally masked arguments — no raw values or credentials) | | `first_launch` | Fired once on the first CLI run after an install or upgrade, triggered by a marker file the installer wrote — the installers themselves send nothing and contact no telemetry endpoint. Contains the installed version, `is_upgrade`, and `install_method` (`curl`, `powershell`, `npm`, `vscode-extension`, `local` for `install --binary`, or `unknown` for markers written before the field existed). `vscode-extension` starts appearing only once an extension build containing the marker write ships, so a zero share for it means the extension has not rolled out yet rather than no extension installs. No PII. **Reading `is_upgrade`:** it means "this machine had run altimate-code before", probed as whether `~/.altimate/machine-id` already existed — *not* "a binary was already present". A reinstall onto a machine that ever ran the CLI reports `is_upgrade: true`, and `altimate uninstall` leaves `machine-id` in place, so a metric excluding upgrades counts installs **per previously-unseen machine** and undercounts reinstalls onto known ones. (`is_upgrade` is a boolean in the event schema; it arrives in Application Insights `customDimensions` as a string, so KQL filters read `tostring(customDimensions.is_upgrade) != "true"`.) Delivery is at-most-once: the marker is deleted before the event flushes, so a process that dies first loses that install rather than re-firing it every launch. Local `--binary` installs report `version: "local"`. | | `startup_ready` | Fired once per process when the top-level command can serve its first request or frame (`serve` listening, TUI transport resolved, `run` about to send its first prompt). Contains the command name, `duration_ms` since process start, and `fresh_install` (true when this process also emitted a non-upgrade `first_launch`). No PII. | | `event_loop_stall` | A 250 ms monitor tick fired more than 1 s late, meaning the event loop was blocked for that long (for example an in-process dependency install). Contains the command name, `thread` (`main` or `worker`), `blocked_ms`, and `since_start_ms`. Capped at 20 per thread (the main thread and the TUI server worker each keep their own counter). No PII. | | `altimate_base_registration` | Timing and outcome of each Altimate Base registration after consent (concurrent calls share one result, and a still-valid cached credential reports `success` without a network round trip): `result` (`success`, `network`, `http`, `response`, `cancelled`, `configuration`, or `error`), `duration_ms`, and the HTTP `status` when the result is `http`. Distinct from `altimate_base_register_result`, which records the onboarding-flow outcome. No gateway URL, response body, credential, or error text is included. | | `task_outcome_signal` | Behavioral quality signal at session end — accepted, error, abandoned, or cancelled. Includes tool count, step count, duration, and last tool category. No user content. | | `task_classified` | Intent classification of the first user message using keyword matching — category (e.g. `debug_dbt`, `write_sql`, `optimize_query`), confidence score, and detected warehouse type. No user text is sent — only the classified category. | | `tool_chain_outcome` | Aggregated tool execution sequence at session end — ordered tool names (capped at 50), error count, recovery count, final outcome, duration, and cost. No tool arguments or outputs. | | `error_fingerprint` | Hashed error pattern for anonymous grouping — SHA-256 hash of masked error message, error class, tool name, and whether recovery succeeded. Raw error content is never sent. | | `sql_fingerprint` | SQL structural shape via AST parsing — statement types, table count, function count, subquery/aggregation/window function presence, and AST node count. No table names, column names, or SQL content. | | `schema_complexity` | Warehouse schema structural metrics from introspection — bucketed table, column, and schema counts plus average columns per table. No schema names or content. | | `validator_check` | A completion-gate validator ran on session end — validator name, `ok` boolean, step, retry count, `enforced` flag (false in shadow mode), and structured `details` (model counts, elapsed time, concurrency limit — no SQL or model content). Only emitted when `ALTIMATE_VALIDATORS_ENABLED=1` or `ALTIMATE_VALIDATORS_SHADOW=1`. See [Validators](https://help.altimate.ai/code/data-engineering/validators/index.md). | | `validator_retries_exhausted` | A session terminated with unresolved validator failures after exhausting the synthetic-retry budget — names of the failing validators (no failure body content). | | `onboarding_started` | The first-run setup gate opened (fresh launch with no usable model). | | `model_picker_shown` | The provider picker was displayed. `trigger` distinguishes the first run from `/connect`, from declining Altimate Base, and from the prompt gate. | | `provider_selected` | A provider row was chosen — `altimate_gateway`, `altimate_base`, `anthropic`, `openai`, `google`, `search_all`, or `other` for anything outside the curated five. `provider_id` carries the raw id only for publicly-known providers, so a provider you named yourself in config is reported as `other` with no name attached. `via_search` marks a pick made inside the full catalogue after choosing "Search all providers…". **Choosing search emits this event twice for one user** — once as `search_all`, then again with the provider actually chosen — so count distinct users or filter on `via_search`, not raw event count. Recorded at the moment of choice, so a sign-in that is then cancelled still counts. | | `altimate_base_confirm_shown` / `altimate_base_choice` | The Altimate Base disclosure was shown, and what the user decided (`accept`/`cancel`). `origin` is `welcome`, `model`, or `migration` (returning free-default users offered Altimate Base on launch); required for the disclosure event and optional for the choice event. | | `altimate_base_register_result` | The consented registration outcome: `success`, `rate_limited`, `unavailable`, `network`, or `error`. Optional `origin` is `welcome`, `model`, or `migration` (returning free-default users offered Altimate Base on launch). No credential or gateway response body is included. | | `gateway_device_code_issued` | The Altimate Gateway authorize URL was built and the browser open attempted. **Name note:** the flow is a browser loopback OAuth — there is no device code. The name follows the original event spec. | | `gateway_auth_completed` / `gateway_auth_failed` | Gateway sign-in outcome. `reason` is `timeout`, `denied`, or `error` — never the underlying message, which can contain the instance name. An unrecognised callback state does not reject the pending attempt, so a CSRF mismatch surfaces as `timeout`. | | `instance_connected` | Credentials received and saved. `time_to_connect_ms` runs from the start of the authorize call, so it includes the browser launch. No instance or tenant name is sent. | | `onboarding_completed` | A model is ready and chat is live. | | `scan_gate_shown` / `scan_gate_choice` | The "scan your environment?" gate appeared, and what the user did — `scan`, `skip`, or `dismissed` (esc / click-away). | | `environment_scan_completed` | A `project_scan` finished during onboarding — `has_dbt`, `has_warehouse`, `is_repo`, `connections_found`, and a bounded list of short `degraded` detection keys. No paths, hostnames, or connection details. Emitted only inside an onboarding session, and only once per session, so scans from `/discover` or a model-initiated call are excluded. | | `sample_setup_completed` | The sample dbt project was materialised. `success`, `models`, `tables`, and `reused` — the tool is deliberately re-callable, so this is per invocation. The target path is never sent. | | `activation_menu_shown` | The activation menu was (very likely) rendered. `variant` is `warehouse` or `no_data`. **Derived** — see the note below. | | `activation_job_selected` / `first_job_completed` | Which activation job the user started and, where observable, finished. Completion is reported only for the job that was actually selected, so the two form a coherent pair. **Derived** — see the note below. | | `first_prompt_sent` | The user's first typed message in an onboarding session. Slash commands are excluded, so the hidden `/onboard-connect` submission does not count. | | `onboarding_abandoned` | The CLI exited during a first run without connecting. `last_stage` is the furthest point reached: `started`, `model_picker`, `provider_setup`, `altimate_base_confirm`, or `gateway_auth`. (`connected` is a funnel position but never a `last_stage` — reaching it means the run completed, which is not an abandonment.) Only emitted for a genuine first run — opening `/connect` as an existing user does not enter the funnel, and abandonment after setup completes is out of scope by definition. Emitted on the exit path under a bounded flush, so the measured rate is a lower bound — see [Delivery & Reliability](#delivery--reliability). | | `review_run` | A dbt/SQL review completed or failed — `invocation` (`cli` for `altimate-code review`, `tool` for the `dbt_pr_review` tool), status, duration, and on success the verdict, the pre-gating verdict, mode, risk tier, and finding counts by severity and by category. No file paths, model or column names, finding titles or bodies, SQL, diff content, or repository/branch/PR names. | | `review_post_outcome` | Whether a review was published to GitHub — `not_requested`, `not_attempted`, `target_unresolved`, `full`, `partial`, or `summary_failed`, plus duration. Emitted on the **CLI path only** — the `dbt_pr_review` tool completes reviews but never publishes, so a `review_run` with `invocation: tool` has no post event and that is not a failure. Within the CLI path there is exactly one per **completed** review: a review that failed emits `review_run: failed` and no post event, so absence there means the review failed rather than that an event was lost. `not_attempted` is publication requested but never reached (a bad `--output` path, a stdout write error). No repository, PR, or comment content. | Each event includes a timestamp, anonymous session ID, a per-launch correlation ID (`launch_id` — a random value regenerated every process start, not persisted and not derived from your machine or identity; it exists only to group events from the same run), CLI version, and an anonymous machine ID (a random UUID stored in `~/.altimate/machine-id`, generated once and never tied to any personal information). ### Notes on the review events - `degraded` is a fidelity flag, not a warehouse flag. It is set when a review found no reviewable files, had no usable manifest for the changed models, or surfaced a finding whose analysis was undecidable. It does not mean "no warehouse was connected". - The category breakdown counts findings that were actually surfaced — after de-duplication, rubric exclusion, and the severity threshold. It is not a count of raw rule detections, and it is grouped by category rather than by individual rule. - Reviews run through the `dbt_pr_review` tool also emit the standard `tool_call` event. They are the same review; count `review_run` rather than both. ### A note on the derived activation events `activation_menu_shown`, `activation_job_selected`, and `first_job_completed` are **inferred, not observed**. The activation menu is not a UI element: it is text the model writes from a prompt template, and the user picks a job by replying in free text. Nothing in the CLI can see either moment directly. They are therefore inferred from the closest deterministic signals — the menu from the command dispatch or the completed environment scan, the job from the first matching tool or skill invocation that follows. Treat the counts as **lower bounds**, and note two specific gaps: - The "something else" branch has no tool signature at all and is never counted. - `first_job_completed` only fires for jobs with a real completion signal. Skill-driven jobs (downstream impact, SQL review, cost) load an instruction bundle and then do their work through other tools, so their completion is not observable and they are absent from this event rather than wrongly counted in it. ## Delivery & Reliability Telemetry events are buffered in memory and flushed periodically. If a flush fails (e.g., due to a transient network error), events are re-added to the buffer for one retry. On process exit, the CLI performs a final flush to avoid losing events from the current session. No events are ever written to disk. If the process is killed before the final flush, buffered events are lost. This is by design to minimize on-disk footprint. The final flush is **time-bounded** so that quitting never hangs the shell: 2 seconds on the main thread and 5 seconds in the TUI worker. When that budget expires the in-flight request is aborted and its events are dropped rather than retried — a retry would only re-queue them into a buffer that is cleared moments later, to be shipped under the next launch's correlation id. The practical consequence is a known bias, not a silent one: events emitted **on the exit path** are the most likely to be lost on a slow or unreachable network, and `onboarding_abandoned` is emitted *only* on that path. So a measured abandonment rate is a **lower bound** — under-reporting is the failure mode, never over-reporting, since a dropped event can only remove an abandonment from the count. Read drop-off numbers as a floor, and treat a change in them as meaningful only if network conditions are comparable. ## Why We Collect Telemetry Telemetry helps us: - **Detect errors** by identifying crashes, provider failures, and engine issues before users report them - **Improve reliability** by tracking MCP server stability, engine initialization, and upgrade outcomes - **Understand usage patterns** to know which tools and features are used so we can prioritize development - **Measure performance** by tracking generation latency, tool call duration, and startup time ## Disabling Telemetry To disable all telemetry collection, add this to your configuration file (`~/.config/altimate-code/altimate-code.json`): ```json { "telemetry": { "disabled": true } } ``` You can also set the environment variable: ```bash export ALTIMATE_TELEMETRY_DISABLED=true ``` When telemetry is disabled, no events are sent and no network requests are made to the telemetry endpoint. ### Test runs are excluded Test runners never reach the default telemetry endpoint. Telemetry is suppressed when `NODE_ENV=test`, `BUN_TEST`, `VITEST`, or `JEST_WORKER_ID` is present. This exists because test processes regenerate their machine ID on every run, so without the exclusion they dominate install and active-machine counts. Running in CI is **not** excluded — that is ordinary product usage (for example [altimate-code-actions](https://github.com/AltimateAI/altimate-code-actions) wraps this CLI), so `CI` and `GITHUB_ACTIONS` on their own do not suppress anything. Two escape hatches exist for reporting from a test run deliberately: - Set `APPLICATIONINSIGHTS_CONNECTION_STRING` to your own endpoint — an explicitly-configured sink is always honoured, which is how the project's own telemetry tests work. - Set `ALTIMATE_TELEMETRY_FORCE=true` to use the default endpoint anyway. `ALTIMATE_TELEMETRY_DISABLED` and the config opt-out take precedence over both. ## Privacy We take your privacy seriously. Altimate Code telemetry **never** collects: - SQL queries or query results - Code content, file contents, or file paths - Credentials, API keys, or tokens - Database connection strings or hostnames - Personally identifiable information (your email is SHA-256 hashed before sending and is used only for anonymous user correlation) - Tool arguments or outputs - AI prompt content or responses Error messages are truncated to 500 characters and scrubbed of file paths before sending. ### New User Identification Altimate Code uses two types of anonymous identifiers for analytics, depending on whether you are logged in: - **Anonymous users (not logged in):** A random UUID is generated using `crypto.randomUUID()` on first run and stored at `~/.altimate/machine-id`. This ID is not tied to your hardware, operating system, or identity — it is purely random and serves only to distinguish one machine from another in aggregate analytics. - **Logged-in users (OAuth):** Your email address is SHA-256 hashed before sending. The raw email is never transmitted. Both identifiers are only sent when telemetry is enabled. Disable telemetry entirely with `ALTIMATE_TELEMETRY_DISABLED=true` or the config option above. ### CLI Authentication Flow When you sign in using the CLI browser auth flow (`altimate auth login`), the anonymous machine ID (a random UUID persisted at `~/.altimate/machine-id` — a device/installation identifier, reused across sessions) is included in the authorization URL and associated with your account in product analytics. This is used solely to correlate CLI install events with authenticated accounts in aggregate funnel analytics — it is not used for advertising or cross-site tracking. Your telemetry opt-out suppresses this: when you disable telemetry — via `ALTIMATE_TELEMETRY_DISABLED=true` **or** the `telemetry.disabled` config option — the machine ID is omitted from the authorization URL entirely. The machine ID is associated with your account in PostHog for this funnel analysis, separate from the Azure Application Insights pipeline used for other CLI telemetry events. ### Data Retention Telemetry data is sent to Azure Application Insights and retained according to [Microsoft's data retention policies](https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-retention-configure). Aside from the PostHog auth-attribution described above, we do not maintain a separate data store for event telemetry. To request deletion of your telemetry data, contact privacy@altimate.ai. ## Network Telemetry data is sent to Azure Application Insights: | Endpoint | Purpose | | ------------------------------------------- | ------------------- | | `eastus-8.in.applicationinsights.azure.com` | Telemetry ingestion | For a complete list of network endpoints, see the [Network Reference](https://help.altimate.ai/code/reference/network/index.md). ## For Contributors ### Naming Convention Event type names use **snake_case** with a `domain_action` pattern: - `auth_login`, `auth_logout` for authentication events - `mcp_server_status`, `mcp_server_census` for MCP server lifecycle - `engine_started`, `engine_error` for native engine events - `provider_error` for AI provider errors - `session_forked` for session lifecycle - `environment_census` for environment snapshot events - `context_utilization`, `context_overflow_recovered` for context management events - `agent_outcome` for agent session events - `error_recovered` for error recovery events - `task_outcome_signal`, `task_classified` for session quality signals - `tool_chain_outcome` for tool execution chain aggregation - `error_fingerprint` for anonymous error pattern grouping - `sql_fingerprint` for SQL structural analysis - `schema_complexity` for warehouse schema metrics ### Adding a New Event 1. **Define the type** — Add a new variant to the `Telemetry.Event` union in `packages/opencode/src/altimate/telemetry/index.ts` 1. **Emit the event** — Call `Telemetry.track()` at the appropriate location 1. **Update docs** — Add a row to the event table above ### Privacy Checklist Before adding a new event, verify: - [ ] No SQL, code, or file contents are included - [ ] No credentials or connection strings are included - [ ] Error messages are truncated to 500 characters - [ ] File paths are not included in any field - [ ] Only tool names are sent, never arguments or outputs # Troubleshooting ## Installation ### Standalone binary not found after curl install **Symptoms:** `altimate-code: command not found` after running `curl -fsSL https://www.altimate.sh/install | bash`. As of v0.7.1 the curl-installed binary is named `altimate`, not `altimate-code`. The npm package continues to ship both names. If you scripted against the curl install: ```bash # Before (v0.7.0 and earlier curl install): ~/.altimate-code/bin/altimate-code run "..." # After (v0.7.1+ curl install): ~/.altimate/bin/altimate run "..." ``` Or stay on the `altimate-code` name by installing via npm: `npm install -g altimate-code`. ### `Cannot find module '@altimateai/altimate-code-core'` **Symptoms:** Binary crashes on first run with the above error (curl-installed v0.7.0 and earlier). The v0.7.0 curl install shipped without the NAPI native module. Fixed in v0.7.1 — the native module is now embedded directly into the binary. Re-install with: ```bash curl -fsSL https://www.altimate.sh/install | bash ``` ### Alpine Linux (musl) not supported **Symptoms:** `Alpine Linux (musl) is not currently supported by the standalone install` during curl install, or `altimate-code is not currently supported on Alpine Linux (musl)` during `npm install` postinstall. `@altimateai/altimate-core` has no NAPI prebuild for musl. Workarounds: ```bash # Run the glibc binary under Alpine (recommended): apk add gcompat # Then either: curl -fsSL https://www.altimate.sh/install | bash # standalone binary # or: apk add gcompat && npm install -g altimate-code # npm install ``` Or use a glibc-based base image (`debian`, `ubuntu`, `node:slim`). ### Windows on ARM64 not supported **Symptoms:** `altimate-code is not currently built for Windows on ARM64` during install. Run the x64 build under Windows-on-ARM's x64 emulation layer, or use WSL. ### `altimate` not found after the Windows standalone install **Symptoms:** `altimate` is unrecognized after running the PowerShell installer. The installer adds `%USERPROFILE%\.altimate\bin` to your **user** PATH — open a new terminal so it takes effect. To (re)install or pin a version: ```powershell # Latest powershell -c "irm https://www.altimate.sh/install.ps1 | iex" # Specific version &([scriptblock]::Create((irm https://www.altimate.sh/install.ps1))) -Version 1.0.180 ``` If the binary crashes immediately on an older CPU, the installer normally retries the baseline (non-AVX2) build automatically; force it with `-ForceBaseline`. ## Log Files Logs are stored at: ```text ~/.local/share/altimate-code/log/ ``` Enable verbose logging: ```bash altimate --print-logs --log-level DEBUG ``` ## Common Issues ### Provider Connection Failed **Symptoms:** "Failed to connect to provider" or timeout errors. **Solutions:** 1. Verify your API key is set: ```bash echo $ANTHROPIC_API_KEY ``` 1. Check network connectivity to the provider 1. If behind a proxy, set `HTTPS_PROXY` (see [Network](https://help.altimate.ai/code/reference/network/index.md)) 1. Try a different provider to isolate the issue ### Provider API Errors **Symptoms:** `APIError: : ` shown in chat output. Common forms: - `APIError: Bad Request: The model 'foo' does not exist or you do not have access to it.` - `APIError: Unauthorized: Invalid API key` - `APIError: Rate limit exceeded` As of v0.7.1, altimate-code surfaces the **inner provider message** instead of dumping the raw JSON body. The status prefix (`Bad Request:`, `Unauthorized:`, etc.) comes from the provider's HTTP status code; everything after the colon is the provider's text verbatim. **Solutions by error class:** 1. **Model not found** (`APIError: Bad Request: The model '' does not exist...`) — list the models your provider currently exposes and re-run with one of them: ```bash altimate models ``` `model_not_found` errors no longer auto-retry; the message you see is the first attempt, not the fifth. 1. **Unauthorized / 401** — re-run `altimate auth login ` and re-issue the request. 1. **Rate limited / 429** — altimate-code automatically retries on rate-limit responses (including plain-text 429s from Alibaba/DashScope). If you keep hitting rate limits, lower `parallel_tool_calls` or switch to a less-saturated model. 1. **Context overflow** — switch to a larger-context model or trim earlier turns with `/compact`. Detection covers Anthropic, Bedrock, OpenAI, Gemini, xAI, Groq, OpenRouter, DeepSeek, Copilot, llama.cpp, LM Studio, MiniMax, Kimi, Moonshot, Azure OpenAI, and HTTP 413. 1. **HTML page returned** — usually a gateway/proxy error. The CLI returns a friendly hint pointing at `altimate auth login` rather than dumping the raw HTML. **Privacy note:** error messages flow through the same redaction layer as everything else (`sk-…`, `Bearer …`, email addresses, and `*.local` / `*.internal` / RFC1918 / IPv6 loopback / ULA / link-local / AWS IMDS hostnames are masked before reaching telemetry). Internal-host URLs in `metadata.url` are also redacted before they reach local storage or shared sessions, and basic-auth userinfo (`user:pass@…`) is stripped from every URL regardless of whether the host is internal. ### Tool Execution Errors **Symptoms:** "No native handler" or tool execution failures for data engineering tools. **Solutions:** 1. Ensure `@altimateai/altimate-core` is installed (should be automatic): ```bash npm ls @altimateai/altimate-core ``` 1. For database tools, ensure the required driver is installed: ```bash # Example for Snowflake: bun add snowflake-sdk # Example for PostgreSQL: bun add pg ``` 1. No Python installation is required. All tools run natively in TypeScript. ### Plan mode refuses a benign request, or stops without exploring **Symptoms:** In plan mode (`--agent plan`), the agent replies *"I'm sorry, but I cannot assist with that request"* to an ordinary planning ask, or you see the warning *"the `plan` agent … stopped without calling any tools."* Most common on the hosted `altimate-default` model (and other non-Anthropic models). **Solutions:** 1. **Upgrade to v0.8.3 or later.** This was a known bug: altimate-code's internal plan instructions were delivered in a way that non-Anthropic models (GPT-5.x, Gemini, …) could mistake for a prompt-injection attempt and refuse. v0.8.3 delivers them as proper system-role messages, eliminating the refusal. 1. If you still see the agent stop without exploring, follow the in-product warning's recoveries: reply asking it to investigate first (`read`/`grep`/`glob`/`explore`), rephrase the request more concretely, or — if it keeps refusing — `/model` to a tier more eager to explore (e.g. Claude Sonnet/Opus). ### Warehouse Connection Failed **Symptoms:** "Connection refused", authentication errors, or "No warehouse configured". **Solutions:** 1. **If using dbt:** Run `/discover` — it automatically finds your `profiles.yml` from `DBT_PROFILES_DIR`, your project directory, or `/.dbt/profiles.yml`. If your `profiles.yml` is in a custom location, set `DBT_PROFILES_DIR` to the directory containing it. 1. **If not using dbt:** Add a connection via the `warehouse_add` tool, `~/.altimate-code/connections.json`, or `ALTIMATE_CODE_CONN_*` env vars. 1. Test connectivity: use the `warehouse_test` tool with your connection name. 1. Check that the warehouse hostname and port are reachable 1. Verify the role/user has the required permissions 1. For Snowflake: ensure the warehouse is not suspended 1. For BigQuery: check that the service account has the required IAM roles ### MCP Server Initialization Failures **Symptoms:** MCP tools missing or MCP server not available after startup. **Solutions:** 1. Check the log files. MCP initialization errors are now logged with the server name and error message: ```text WARN failed to initialize MCP server { key: "my-tools", error: "..." } ``` 1. Verify the MCP server command is correct in your config 1. Test the server manually: ```bash altimate mcp test my-tools ``` 1. Check that required environment variables are set (e.g., API keys referenced in the MCP config) ### LSP Server Won't Start **Symptoms:** No diagnostics or completions for a language. **Solutions:** 1. Check if the LSP server is disabled: ```json { "lsp": { "typescript": { "disabled": false } } } ``` 1. Enable LSP auto-download: ```bash unset ALTIMATE_CLI_DISABLE_LSP_DOWNLOAD ``` 1. Check the log files for LSP-specific errors ### Auto-Update Issues Disable auto-update if it causes problems: ```bash export ALTIMATE_CLI_DISABLE_AUTOUPDATE=true ``` Or set to notification only in your config: ```json { "autoupdate": "notify" } ``` Both options still show an upgrade indicator in the footer when a new version is available. To upgrade manually, run: ```bash altimate upgrade ``` Note When an update is available, you'll see `↑ update available · altimate upgrade` in the bottom-right corner of the TUI. ### Context Too Large If conversations hit context limits: ```json { "compaction": { "auto": true, "prune": true } } ``` Or manually compact in the TUI: leader + `Shift+C`. ## Debug Mode Run with full debug output: ```bash altimate --print-logs --log-level DEBUG 2>debug.log ``` Then share `debug.log` when reporting issues. ## Getting Help - [GitHub Issues](https://github.com/AltimateAI/altimate-code/issues): Report bugs and request features - Check [existing issues](https://github.com/AltimateAI/altimate-code/issues) before filing new ones # Windows / WSL altimate runs on Windows both natively (via Node.js on Windows) and through WSL (Windows Subsystem for Linux). WSL 2 is recommended for the best experience, but it is not required. ## Windows Native Install ### Standalone install (no Node) The fastest path installs the self-contained binary — the same Bun-compiled `altimate.exe` we ship on macOS/Linux — straight from GitHub releases. It needs no Node.js or npm: ```powershell powershell -c "irm https://www.altimate.sh/install.ps1 | iex" ``` This downloads `altimate.exe` to `%USERPROFILE%\.altimate\bin` and adds that directory to your user PATH (open a new terminal afterwards). The installer auto-detects AVX2 support and falls back to the baseline build on older CPUs. Options (pass via a script block): ```powershell # Pin a specific version &([scriptblock]::Create((irm https://www.altimate.sh/install.ps1))) -Version 1.0.180 # Skip the PATH edit &([scriptblock]::Create((irm https://www.altimate.sh/install.ps1))) -NoPathUpdate ``` `altimate upgrade` self-updates a standalone install in place using the same script. ### npm install Alternatively, install via npm with Node.js 18+ installed natively on Windows: ```powershell # PowerShell or CMD — install globally npm install -g altimate-code # Launch altimate ``` Both paths support all core features in native mode, including warehouse connections, agent modes, and the TUI. ## WSL Setup (Recommended) For the best experience (especially with file watching, shell tools, and dbt), we recommend WSL 2: 1. Install WSL: ```powershell wsl --install ``` 1. Install Node.js in WSL: ```bash curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt-get install -y nodejs ``` 1. Install altimate: ```bash npm install -g altimate-code ``` 1. Launch: ```bash altimate ``` ## Windows Terminal For the best TUI experience on Windows, use [Windows Terminal](https://aka.ms/terminal) with a Nerd Font installed. Windows Terminal supports true color, Unicode, and the full range of TUI features that altimate uses. To install a Nerd Font: 1. Download a Nerd Font from [nerdfonts.com](https://www.nerdfonts.com/font-downloads) (e.g., "FiraCode Nerd Font") 1. Install the font on your system 1. In Windows Terminal, go to **Settings > Profiles > Defaults > Appearance** and set the font face to the installed Nerd Font > **Note:** The default `cmd.exe` and older PowerShell windows have limited Unicode support, which may cause rendering issues with altimate's TUI elements. ## Git Bash Path If you need to use Git Bash instead of WSL: ```bash export ALTIMATE_CLI_GIT_BASH_PATH="C:\\Program Files\\Git\\bin\\bash.exe" ``` ## Known Limitations - The TUI works best in Windows Terminal or a modern terminal emulator - Some terminal features may not work in older cmd.exe or PowerShell windows - File watching may have delays due to WSL filesystem bridging ## Troubleshooting ### Path separator issues Windows uses backslashes (`\`) in file paths, but altimate config files should always use **forward slashes** (`/`), even on Windows. This applies to all paths in `.altimate-code/connections.json`: ```json { "local-duckdb": { "type": "duckdb", "database": "C:/Users/analyst/projects/dev.duckdb" } } ``` **Wrong** (will cause errors): ```json { "database": "C:\\Users\\analyst\\projects\\dev.duckdb" } ``` **Right:** ```json { "database": "C:/Users/analyst/projects/dev.duckdb" } ``` This also applies to paths like `private_key_path`, `service_account`, and any plugin paths specified in the config. ### Node.js not found after install If you installed Node.js but `npm` or `node` is not recognized: - Restart your terminal after installing Node.js - Ensure the Node.js installation directory is in your system `PATH` - In WSL, make sure you installed Node.js inside WSL, not on the Windows side ## Tips - Use WSL 2 for better performance - Store your projects in the WSL filesystem (`~/projects/`) rather than `/mnt/c/` for faster file operations - Set up your warehouse connections in the WSL environment - If using both WSL and native Windows, keep separate config files because the WSL and Windows file systems have different path conventions # SQL Check (Headless) Run deterministic SQL checks without an LLM. Ideal for CI/CD pipelines, pre-commit hooks, and GitHub Actions. The `check` command analyzes SQL files for anti-patterns, validation errors, safety issues, policy violations, PII exposure, and semantic problems -- all without requiring a model provider or API key. ______________________________________________________________________ ## Quick Start ```bash # Lint all SQL files in current directory altimate-code check # Check specific files altimate-code check models/staging/stg_orders.sql models/marts/fct_revenue.sql # Run all checks with JSON output altimate-code check --checks lint,validate,safety --format json # Use with a schema for DataFusion validation altimate-code check --checks validate --schema schema.yml # Enforce policy guardrails altimate-code check --checks policy --policy policy.json --fail-on error # Only show warnings and errors (hide info) altimate-code check --severity warning # Exit non-zero on any warning or error altimate-code check --fail-on warning ``` ______________________________________________________________________ ## Available Checks | Check | What It Does | Needs Schema? | Default | | ---------- | --------------------------------------------------------- | ------------- | ------- | | `lint` | Anti-pattern detection (SELECT \*, cartesian JOINs, etc.) | Optional | Yes | | `validate` | DataFusion SQL validation (column exists, type matches) | Yes | No | | `safety` | SQL injection and dangerous pattern detection | No | Yes | | `policy` | Custom guardrails (block SELECT \*, require LIMIT, etc.) | Optional | No | | `pii` | PII column detection and query exposure | Optional | No | | `semantic` | Semantic validation (cartesian products, wrong JOINs) | Optional | No | | `grade` | SQL quality grading with recommendations | Optional | No | Findings usually carry a machine-readable `rule` field (e.g. `unbalanced_quote`, `sql_injection`, `L003`) visible in `--format json` output — see the [Finding Object](#finding-object) schema below. `safety` and `policy` findings always include one; `lint` findings may omit both `rule` and `code` if the engine didn't attach them, so switch on presence rather than assuming. By default, `lint` and `safety` are enabled. Override with `--checks`: ```bash # Run everything altimate-code check --checks lint,validate,safety,policy,pii,semantic,grade \ --schema schema.yml --policy policy.json # Just lint altimate-code check --checks lint ``` ______________________________________________________________________ ## Options Reference | Option | Type | Default | Description | | ------------ | -------- | ------------- | --------------------------------------------------------------------- | | `[files..]` | string[] | `**/*.sql` | SQL files or glob patterns to check | | `--format` | string | `text` | Output format: `text` or `json` | | `--checks` | string | `lint,safety` | Comma-separated list of checks to run | | `--schema` | string | - | Path to schema file for validation context | | `--policy` | string | - | Path to policy JSON file (required for `policy` check) | | `--severity` | string | `info` | Minimum severity level to report: `info`, `warning`, `error` | | `--fail-on` | string | `none` | Exit 1 if findings at this level or above: `none`, `warning`, `error` | ______________________________________________________________________ ## JSON Output Format When using `--format json`, the command writes structured JSON to stdout (diagnostic messages go to stderr): ```json { "version": 1, "files_checked": 3, "checks_run": ["lint", "safety"], "schema_resolved": false, "results": { "lint": { "findings": [ { "file": "models/staging/stg_orders.sql", "line": 5, "column": 1, "rule": "L003", "severity": "warning", "message": "SELECT * used -- enumerate columns explicitly", "suggestion": "Replace SELECT * with explicit column list" } ], "error_count": 0, "warning_count": 1 }, "safety": { "findings": [], "error_count": 0, "warning_count": 0 } }, "summary": { "total_findings": 1, "errors": 0, "warnings": 1, "info": 0, "pass": true } } ``` ### Schema | Field | Type | Description | | ------------------------ | ------------------------------- | ------------------------------------------------ | | `version` | `1` | Schema version (always 1) | | `files_checked` | number | Number of SQL files processed | | `checks_run` | string[] | List of check names that were executed | | `schema_resolved` | boolean | Whether a schema file was loaded | | `results` | Record\ | Per-check category results | | `summary.total_findings` | number | Total findings across all checks | | `summary.errors` | number | Total error-severity findings | | `summary.warnings` | number | Total warning-severity findings | | `summary.info` | number | Total info-severity findings | | `summary.pass` | boolean | Whether the run passes the `--fail-on` threshold | ### Finding Object | Field | Type | Description | | ------------ | ----------------- | ----------------------------------------- | | `file` | string | Relative path to the SQL file | | `line` | number (optional) | Line number of the finding | | `column` | number (optional) | Column number of the finding | | `code` | string (optional) | Machine-readable finding code | | `rule` | string (optional) | Rule or check that produced the finding | | `severity` | string | `"error"`, `"warning"`, or `"info"` | | `message` | string | Human-readable description of the finding | | `suggestion` | string (optional) | Suggested fix for the finding | ______________________________________________________________________ ## Text Output Format The default `text` format is designed for human consumption: ```text Checked 3 file(s) with [lint, safety] --- LINT --- WARNING models/staging/stg_orders.sql:5:1 [L003]: SELECT * used -- enumerate columns explicitly suggestion: Replace SELECT * with explicit column list 1 finding(s): 0 error(s), 1 warning(s), 0 info PASS ``` The final line is `PASS` or `FAIL` based on the `--fail-on` setting. ______________________________________________________________________ ## Policy File Format The `--policy` flag accepts a JSON file that defines custom guardrails. Example: ```json { "rules": [ { "name": "no-select-star", "description": "SELECT * is not allowed in production models", "severity": "error", "pattern": "SELECT\\s+\\*" }, { "name": "require-limit", "description": "All ad-hoc queries must include a LIMIT clause", "severity": "warning", "pattern_absent": "LIMIT\\s+\\d+" }, { "name": "no-drop-table", "description": "DROP TABLE is forbidden", "severity": "error", "pattern": "DROP\\s+TABLE" } ] } ``` ### Common Policy Scenarios **Block dangerous operations:** ```json { "rules": [ { "name": "no-truncate", "severity": "error", "pattern": "TRUNCATE\\s+TABLE" }, { "name": "no-drop", "severity": "error", "pattern": "DROP\\s+(TABLE|VIEW|SCHEMA)" }, { "name": "no-delete-all", "severity": "error", "pattern": "DELETE\\s+FROM\\s+\\w+\\s*$" } ] } ``` **Enforce best practices:** ```json { "rules": [ { "name": "require-where", "severity": "warning", "pattern_absent": "WHERE" }, { "name": "no-select-star", "severity": "warning", "pattern": "SELECT\\s+\\*" }, { "name": "require-alias", "severity": "info", "pattern_absent": "\\bAS\\b" } ] } ``` ______________________________________________________________________ ## Schema File Format The `--schema` flag provides table and column metadata for checks that need it (`validate`, `pii`, `semantic`, `grade`). The schema file is typically a YAML file that describes your database structure: ```yaml tables: - name: orders schema: staging columns: - name: order_id type: INTEGER - name: customer_id type: INTEGER - name: order_date type: DATE - name: total_amount type: DECIMAL(10,2) - name: customers schema: staging columns: - name: customer_id type: INTEGER - name: email type: VARCHAR pii: true - name: full_name type: VARCHAR pii: true ``` If you use dbt, you can reference your `schema.yml` files directly. ______________________________________________________________________ ## Severity Levels Findings have three severity levels: | Level | Rank | Meaning | | --------- | ---- | ------------------------------------------- | | `error` | 2 | Must fix -- query will fail or is dangerous | | `warning` | 1 | Should fix -- anti-pattern or risk detected | | `info` | 0 | Informational -- style suggestion or note | The `--severity` flag controls the minimum level to include in output. The `--fail-on` flag controls the exit code: ```bash # Show only errors in output, exit 1 if any errors exist altimate-code check --severity error --fail-on error # Show everything, but only fail on warnings or errors altimate-code check --severity info --fail-on warning ``` ______________________________________________________________________ ## CI/CD Integration ### GitHub Actions ```yaml name: SQL Check on: [pull_request] jobs: sql-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install altimate-code run: npm install -g altimate-code - name: Lint and safety check run: altimate-code check --checks lint,safety --format json --fail-on error - name: Policy check run: altimate-code check --checks policy --policy .sql-policy.json --fail-on error ``` ### GitHub Actions with JSON parsing ```yaml - name: SQL Check id: sql-check run: | altimate-code check --format json --fail-on warning > check-results.json 2>/dev/null || true echo "findings=$(jq '.summary.total_findings' check-results.json)" >> $GITHUB_OUTPUT echo "pass=$(jq '.summary.pass' check-results.json)" >> $GITHUB_OUTPUT - name: Comment on PR if: steps.sql-check.outputs.pass == 'false' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const results = JSON.parse(fs.readFileSync('check-results.json', 'utf8')); const body = `## SQL Check Failed\n\n${results.summary.errors} errors, ${results.summary.warnings} warnings`; github.rest.issues.createComment({ ...context.repo, issue_number: context.issue.number, body }); ``` ### Pre-commit Hook Add to `.pre-commit-config.yaml`: ```yaml repos: - repo: local hooks: - id: altimate-sql-check name: SQL Check entry: altimate-code check --fail-on warning language: system types: [sql] pass_filenames: true ``` Or add a simple git hook in `.git/hooks/pre-commit`: ```bash #!/usr/bin/env bash set -e # Find staged SQL files SQL_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.sql$' || true) if [ -n "$SQL_FILES" ]; then altimate-code check $SQL_FILES --fail-on warning fi ``` ### GitLab CI ```yaml sql-check: stage: test script: - npm install -g altimate-code - altimate-code check --checks lint,safety --format json --fail-on error rules: - changes: - "**/*.sql" ``` ______________________________________________________________________ ## Examples ### 1. Basic lint of all SQL files ```bash altimate-code check ``` Searches for `**/*.sql` in the current directory and runs `lint` + `safety` checks. ### 2. Check specific models before deploying ```bash altimate-code check models/marts/*.sql --checks lint,validate,semantic \ --schema models/schema.yml --fail-on warning ``` ### 3. PII audit across the entire project ```bash altimate-code check --checks pii --schema schema.yml --format json > pii-report.json ``` ### 4. Grade SQL quality and get improvement suggestions ```bash altimate-code check --checks grade --schema schema.yml ``` ### 5. Full check suite in CI ```bash altimate-code check \ --checks lint,validate,safety,policy,pii,semantic \ --schema schema.yml \ --policy .sql-policy.json \ --format json \ --fail-on error ``` ### 6. Check only changed files in a PR ```bash # Get changed SQL files from git CHANGED=$(git diff --name-only origin/main...HEAD -- '*.sql') if [ -n "$CHANGED" ]; then altimate-code check $CHANGED --fail-on warning fi ``` ### 7. Use glob patterns ```bash # Check all staging models altimate-code check "models/staging/**/*.sql" # Check multiple directories altimate-code check "models/staging/*.sql" "models/marts/*.sql" ``` ______________________________________________________________________ ## Exit Codes | Code | Meaning | | ---- | -------------------------------------------------------------- | | `0` | All checks passed (or no findings above `--fail-on` threshold) | | `1` | Findings found above `--fail-on` threshold | When `--fail-on` is `none` (the default), the command always exits `0` regardless of findings. ______________________________________________________________________ ## How It Works The `check` command does not use an LLM. It calls deterministic analysis routines through the `altimate_core` engine: 1. **File resolution** -- resolves file paths and glob patterns, filters to `.sql` files 1. **Batch processing** -- processes files in batches of 10 for performance 1. **Check execution** -- runs each enabled check against each file via the Dispatcher 1. **Severity filtering** -- filters results by the `--severity` threshold 1. **Output formatting** -- formats results as text (stderr) or JSON (stdout) 1. **Exit code** -- returns non-zero if findings exceed the `--fail-on` threshold # CI & Headless Mode Run any altimate prompt non-interactively from scripts, CI pipelines, or scheduled jobs. No TUI. Output is plain text or JSON. ______________________________________________________________________ ## Basic Usage ```bash altimate run "your prompt here" ``` Key flags: | Flag | Description | | --------------------- | -------------------------------------------- | | `--output json` | Structured JSON output instead of plain text | | `--model ` | Override the configured model | | `--connection ` | Select a specific warehouse connection | | `--no-color` | Disable ANSI color codes (for CI logs) | See `altimate run --help` for the full flag list, or [CLI Reference](https://help.altimate.ai/code/usage/cli/index.md). ______________________________________________________________________ ## Environment Variables for CI Configure without committing an `altimate-code.json` file: ```bash # LLM provider ALTIMATE_PROVIDER=anthropic ALTIMATE_ANTHROPIC_API_KEY=your-key-here # Or OpenAI ALTIMATE_PROVIDER=openai ALTIMATE_OPENAI_API_KEY=your-key-here # Warehouse (Snowflake example) SNOWFLAKE_ACCOUNT=myorg-myaccount SNOWFLAKE_USER=ci_user SNOWFLAKE_PASSWORD=${{ secrets.SNOWFLAKE_PASSWORD }} SNOWFLAKE_DATABASE=analytics SNOWFLAKE_SCHEMA=public SNOWFLAKE_WAREHOUSE=compute_wh ``` ______________________________________________________________________ ## Exit Codes | Code | Meaning | | ---- | ---------------------------------------------------------------------- | | `0` | Success (task completed) | | `1` | Task completed but result indicates issues (e.g., anti-patterns found) | | `2` | Configuration error (missing API key, bad connection) | | `3` | Tool execution error (warehouse unreachable, query failed) | Use exit codes to fail CI on actionable findings: ```bash altimate run "validate models in models/staging/ for anti-patterns" || exit 1 ``` ______________________________________________________________________ ## Worked Examples ### Example 1: Nightly Cost Check (GitHub Actions) ```yaml # .github/workflows/cost-check.yml name: Nightly Cost Check on: schedule: - cron: '0 8 * * 1-5' # 8am UTC, weekdays jobs: cost-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install altimate run: npm install -g altimate-code - name: Run cost report env: ALTIMATE_PROVIDER: anthropic ALTIMATE_ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }} SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_CI_USER }} SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_CI_PASSWORD }} SNOWFLAKE_DATABASE: analytics SNOWFLAKE_WAREHOUSE: compute_wh run: | altimate run "/cost-report" --output json > cost-report.json cat cost-report.json - name: Upload cost report uses: actions/upload-artifact@v4 with: name: cost-report path: cost-report.json ``` ### Example 2: Post-Deploy SQL Validation Add to your dbt deployment workflow to catch anti-patterns before they reach production: ```yaml - name: SQL anti-pattern check env: ALTIMATE_PROVIDER: anthropic ALTIMATE_ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | altimate run "validate all SQL files in models/staging/ for anti-patterns and fail if any are found" \ --no-color \ --output json ``` ### Example 3: Automated Test Generation (Pre-commit) ```bash #!/bin/bash # .git/hooks/pre-commit # Generate tests for any staged SQL model files STAGED_MODELS=$(git diff --cached --name-only --diff-filter=A | grep "models/.*\.sql") if [ -n "$STAGED_MODELS" ]; then echo "Generating tests for new models..." altimate run "/generate-tests for: $STAGED_MODELS" --no-color fi ``` ______________________________________________________________________ ## Traces in Headless Mode Tracing works in headless mode. View traces (session recordings) after the run: ```bash altimate trace list altimate trace view ``` See [Trace](https://help.altimate.ai/code/configure/trace/index.md) for the full trace reference. ______________________________________________________________________ ## Security Recommendation Use a **read-only warehouse user** for CI jobs that only need to read data. Reserve write-access credentials for jobs that explicitly need them (e.g., test generation that writes files). See [Security FAQ](https://help.altimate.ai/code/reference/security-faq/index.md) and [Permissions](https://help.altimate.ai/code/configure/permissions/index.md). # CLI altimate provides subcommands for headless operation, automation, and integration. ## Basic Usage ```bash # Launch the TUI (default) altimate # Run a prompt non-interactively altimate run "analyze my most expensive queries" # Start with a specific agent altimate --agent analyst ``` > **Note:** `altimate-code` still works as a backward-compatible alias for all commands. ## Subcommands | Command | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `run` | Run a prompt non-interactively | | `check` | Run deterministic SQL checks (no LLM required) -- see [SQL Check](https://help.altimate.ai/code/usage/check/index.md) | | `serve` | Start the HTTP API server | | `web` | Start the web UI | | `agent` | Agent management | | `auth` | Authentication | | `mcp` | Model Context Protocol tools -- `mcp list` to see configured servers, `mcp status` for each server's real connection state and any drift between discovered and on-disk config | | `acp` | Agent Communication Protocol | | `models` | List available models | | `stats` | Usage statistics | | `export` | Export session data | | `import` | Import session data | | `session` | Session management | | `link` | Link this project to an Altimate workspace (pilot, requires `ALTIMATE_WORKSPACE=1`) | | `trace` | List and view session traces (recordings of agent sessions) | | `github` | GitHub integration | | `pr` | Pull request tools | | `upgrade` | Upgrade to latest version | | `uninstall` | Uninstall altimate | ## Global Flags | Flag | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--model ` | Override the default model | | `--agent ` | Start with a specific agent | | `--yolo` | Auto-approve all permission prompts (explicit `deny` rules still enforced) | | `--dangerously-skip-permissions` | Same as `--yolo` (alias for upstream compatibility); auto-approves prompts that aren't explicitly denied. `run` subcommand only. | | `--integrations ` | Use only local warehouse tools instead of routing them through a bound workspace's engine (pilot). Sets `ALTIMATE_INTEGRATIONS` for the process, so child processes inherit it. | | `--print-logs` | Print logs to stderr | | `--log-level ` | Set log level: `DEBUG`, `INFO`, `WARN`, `ERROR` | | `--help`, `-h` | Show help | | `--version`, `-v` | Show version | ## Environment Variables Configuration can be controlled via environment variables: ### Core Configuration | Variable | Description | | ----------------------------- | ---------------------------- | | `ALTIMATE_CLI_CONFIG` | Path to custom config file | | `ALTIMATE_CLI_CONFIG_DIR` | Custom config directory | | `ALTIMATE_CLI_CONFIG_CONTENT` | Inline config as JSON string | | `ALTIMATE_CLI_GIT_BASH_PATH` | Path to Git Bash (Windows) | ### Feature Toggles | Variable | Description | | -------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `ALTIMATE_CLI_DISABLE_AUTOUPDATE` | Disable automatic updates (still shows upgrade indicator) | | `ALTIMATE_CLI_DISABLE_LSP_DOWNLOAD` | Don't auto-download LSP servers | | `ALTIMATE_CLI_DISABLE_AUTOCOMPACT` | Disable automatic context compaction | | `ALTIMATE_CLI_DISABLE_DEFAULT_PLUGINS` | Skip loading default plugins | | `ALTIMATE_CLI_DISABLE_EXTERNAL_SKILLS` | Disable external skill discovery | | `ALTIMATE_CLI_DISABLE_PROJECT_CONFIG` | Ignore project-level config files | | `ALTIMATE_CLI_DISABLE_TERMINAL_TITLE` | Don't set terminal title | | `ALTIMATE_CLI_DISABLE_PRUNE` | Disable database pruning | | `ALTIMATE_CLI_DISABLE_MODELS_FETCH` | Don't fetch models from models.dev | | `ALTIMATE_WORKSPACE` | Opt into the workspace pilot (`1`). Off by default; nothing about workspaces is active without it | | `ALTIMATE_INTEGRATIONS` | Set to `local` to keep warehouse tools local rather than routing them through a bound workspace's engine | ### Server & Security | Variable | Description | | ------------------------------ | ------------------------------- | | `ALTIMATE_CLI_SERVER_USERNAME` | Server HTTP basic auth username | | `ALTIMATE_CLI_SERVER_PASSWORD` | Server HTTP basic auth password | | `ALTIMATE_CLI_PERMISSION` | Permission config as JSON | ### Permissions & Safety | Variable | Description | | ------------------- | ------------------------------------------------------------------------------------------- | | `ALTIMATE_CLI_YOLO` | Auto-approve all permission prompts (`true`/`false`). Explicit `deny` rules still enforced. | | `OPENCODE_YOLO` | Fallback for `ALTIMATE_CLI_YOLO`. When both are set, `ALTIMATE_CLI_YOLO` takes precedence. | ### Memory & Training | Variable | Description | | ------------------------------ | --------------------------------------- | | `ALTIMATE_DISABLE_MEMORY` | Disable the persistent memory system | | `ALTIMATE_MEMORY_AUTO_EXTRACT` | Auto-extract memories at session end | | `ALTIMATE_DISABLE_TRAINING` | Disable the AI teammate training system | ### Experimental | Variable | Description | | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ALTIMATE_CLI_EXPERIMENTAL` | Enable all experimental features | | `ALTIMATE_CLI_EXPERIMENTAL_FILEWATCHER` | Enable file watcher | | `ALTIMATE_CLI_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | Custom bash timeout (ms) | | `ALTIMATE_CLI_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | Max output tokens | | `ALTIMATE_CLI_EXPERIMENTAL_PLAN_MODE` | Enable plan mode | | `ALTIMATE_CLI_ENABLE_EXA` | Enable Exa web search | | `ALTIMATE_CALM_MODE` | Enables all streaming optimizations: smooth rendering, line-at-a-time buffering, and 100-column width cap. Recommended for a Claude Code-like experience. Equivalent to setting `ALTIMATE_SMOOTH_STREAMING=true ALTIMATE_LINE_STREAMING=true ALTIMATE_CONTENT_MAX_WIDTH=100`. | | `ALTIMATE_SMOOTH_STREAMING` | Uses lightweight `` rendering during LLM streaming, then swaps to rich markdown after completion. Reduces text jumps and scroll jitter. Included in `ALTIMATE_CALM_MODE`. | | `ALTIMATE_LINE_STREAMING` | Buffers LLM output and reveals one complete line at a time (on `\n`). Gives a calm, steady flow. Remaining text flushes on message completion or abort. Included in `ALTIMATE_CALM_MODE`. | | `ALTIMATE_CONTENT_MAX_WIDTH` | Cap text content width in columns (e.g. `100`). Improves readability on wide screens. Automatically disabled on small terminals. Set to `100` by `ALTIMATE_CALM_MODE`. | #### Calm Mode Quick Start For a Claude Code-like streaming experience, add to your shell profile: ```bash export ALTIMATE_CALM_MODE=true ``` Or use individual flags for fine-grained control: ```bash # Smooth rendering only (no line buffering) export ALTIMATE_SMOOTH_STREAMING=true # Line buffering only (no rendering changes) export ALTIMATE_LINE_STREAMING=true # Custom width cap (e.g., 80 columns) export ALTIMATE_CONTENT_MAX_WIDTH=80 ``` ## Non-interactive Usage ```bash # Pipe input echo "explain this SQL" | altimate run # With a specific model altimate run --model anthropic/claude-sonnet-4-6 "optimize my warehouse" # Print logs for debugging altimate --print-logs --log-level DEBUG run "test query" # Disable tracing for a single run altimate run --no-trace "quick question" ``` For CI pipelines and headless automation, see [CI & Automation](https://help.altimate.ai/code/usage/ci-headless/index.md). ## Trace Every `run` command automatically saves a trace file (a recording of the agent session) with the full session details, including generations, tool calls, tokens, cost, and timing. See [Trace](https://help.altimate.ai/code/configure/trace/index.md) for configuration options. ```bash # List recent traces altimate trace list # View a trace in the browser altimate trace view ``` # dbt PR Review — real-world issue corpus A living, **sourced** corpus of real dbt/SQL pitfalls practitioners report (dbt Discourse/Slack, Reddit, StackOverflow, engineering blogs), each turned into a reproducible test. Every entry is a problem someone actually hit — not a synthetic example — and the reviewer is held to catching it **with zero false positives on the correct version**. Reproduce: `bun run --conditions=browser script/review-realworld-eval.ts` (detection + precision) and `script/review-dialect-coverage.ts` (10-dialect coverage). Verified end-to-end on a real third-party repo (`jaffle_shop`, DuckDB). ## Latest measured results - **Caught: 15/15** sourced pitfalls - **False positives on the *correct* version: 0/5** - **Dialect coverage (10 dialects):** function precision 100%, recall 95.7%, structural/type 100% - **Real repo (jaffle_shop PR):** every finding tied to the change; **no noise** about pre-existing code (diff-scoped) ## The corpus | # | Pitfall | Where practitioners report it | What the reviewer emits | | --- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | 1 | **LEFT JOIN silently becomes INNER** — a filter on the right table in `WHERE` drops the unmatched rows | sqlbenjamin.wordpress.com "LEFT JOINs and WHERE clauses", SQLShack, Toad forum | `join_risk` (critical) — move the predicate to the `ON` clause | | 2 | **Fan-out** — one-to-many join inflates `SUM`/`COUNT` | [dbt join-logic docs](https://docs.getdbt.com/docs/build/join-logic), Holistics fan-out docs | `fanout` / `join_risk` — aggregate before joining, or `count(distinct …)` | | 3 | **`NOT IN (subquery)` with NULLs returns no rows** | classic SQL gotcha (StackOverflow) | `sql_correctness` — use `NOT EXISTS` | | 4 | **Incremental model with no `is_incremental()` guard** → full reprocess / dupes | [dbt incremental-models docs](https://docs.getdbt.com/docs/build/incremental-models) | `materialization` | | 5 | **Dedup `row_number()` with no `ORDER BY`** → which row survives flaps between runs | [dbt "remove partial duplicates" blog](https://docs.getdbt.com/blog/how-we-remove-partial-duplicates) | `dedup` (warning) | | 6 | **Clock (`current_timestamp`/`getdate`) baked into a transform** → non-idempotent | dbt Slack / idempotency guidance | `idempotency` | | 7 | **`SELECT *` in a mart** → breaks downstream on upstream schema change; scan cost | dbt style guides | `warehouse_cost` / `sql_quality` | | 8 | **`= NULL` instead of `IS NULL`** → always false | classic SQL gotcha | `sql_correctness` | | 9 | **Division with no zero-guard** → divide-by-zero failures | dbt Slack (`safe_divide`/`nullif`) | `sql_correctness` (core L032) | | 10 | **Non-portable function for the project's dialect** (e.g. `NVL` on BigQuery) | cross-warehouse migration pain (dbt Discourse, SQLGlot) | `sql_quality` (core L033, dialect-aware) | | 11 | **Comma / implicit cross join** | SQL joins tutorials, cartesian-product warnings | `join_risk` | | 12 | **Unguarded `COUNT(DISTINCT)` at scale** → cost | BigQuery/Snowflake cost threads (`approx_count_distinct`) | `warehouse_cost` | | 13 | **`BETWEEN` on a timestamp drops the last day's afternoon** (inclusive upper bound → `00:00:00`) | [SO "Exclude rows with certain time of day"](https://stackoverflow.com/questions/12891232/exclude-rows-with-certain-time-of-day) | `sql_correctness` — use half-open `>= / <` | | 14 | **String `\|\|` concat NULL-propagation** — any NULL operand → whole result NULL | [Baeldung "Concatenate with NULL Values in SQL"](https://www.baeldung.com/sql/concatenate-null) | `sql_correctness` — use `concat_ws`/`coalesce` | | 15 | **Hand-rolled surrogate key over raw concat** — NULL field nulls the key / NULL-vs-`''` collisions | [dbt-utils #488](https://github.com/dbt-labs/dbt-utils/issues/488), [dbt Discourse surrogate-key](https://discourse.getdbt.com/t/surrogate-key-dbt-upgrade/6813) | `sql_correctness` / `dedup` | Plus the **incremental `unique_key` with NULL components → duplicate rows** class ([dbt Discourse #17298](https://discourse.getdbt.com/t/incremental-model-unique-constraint-still-allows-duplicates/17298), [dbt-core #7597](https://github.com/dbt-labs/dbt-core/issues/7597)) is covered by the incremental + surrogate-key detectors. ## Precision — the *correct* versions stay silent The corpus pairs each pitfall with its fix and asserts **no finding**: a LEFT JOIN anti-join (`WHERE right.key IS NULL`), `nullif`-guarded division, `NOT EXISTS`, `row_number()` **with** an `ORDER BY`, and a dialect's **native** function (e.g. `NVL` on Snowflake). Several real false positives were found and removed via this corpus (blanket `SAFE_CAST` nag, `ARRAY_AGG`-without-`WITHIN GROUP` on the wrong dialect, `ORDER BY DESC` without `NULLS LAST`, and OLTP/index rules like correlated-subquery / function-on-filter that don't apply to columnar warehouses). > The bar: a first-time user opening a PR should see findings that map exactly to what they changed, are correct for their warehouse's dialect, and never nag about code they didn't touch. # dbt PR Review [**See live review PRs**](https://github.com/AltimateAI/dbt-pr-review-demo/pulls) · [**Install the GitHub App**](https://github.com/apps/altimate-code-agent/installations/new) The public demo is a zero-secret DuckDB project with open PRs for broken joins, removed tests, PII exposure, `SELECT *`, unsafe incremental models, and a safe refactor. The GitHub App handles interactive repository tasks; the automatic review on every pull request is installed with the Action below. AI code review specialized for dbt/SQL. `dbt-pr-review` produces a single, **signed** verdict on a pull request — `APPROVE`, `COMMENT`, or `REQUEST_CHANGES` — where every **blocking** finding is backed by a deterministic engine call, not a model's opinion: - **column-lineage / DAG blast radius** — which downstream models a change breaks - **query equivalence** — whether a "refactor" provably returns the same rows - **PII classification** — columns that newly expose sensitive data - **A–F grade + anti-patterns** — readability, correctness, warehouse-cost issues The bot posts a COMMENT review — never a formal GitHub *Approve* `APPROVE` is the **semantic** verdict shown in the comment body ("✅ Approved — no findings"). On GitHub the bot always posts a **COMMENT** review event, **never** a formal *Approve*: a review bot must not be able to satisfy branch protection / required reviews and let a PR merge without human sign-off. `REQUEST_CHANGES` posts a blocking review in `gate` mode (softened to a comment in `comment` mode). **To block merges, gate on the verdict *check* (`--mode gate`), not on requiring this bot as a reviewer.** If your branch protection previously *required the altimate bot's review approval*, remove that requirement — the bot no longer issues one, so those merges would otherwise stay blocked. On top of that deterministic core, an **LLM reviewer** adds the contextual judgment a static analyzer cannot — intent vs. the PR description, misleading names, business-logic risk, and test coverage for the change — as **advisory** comments that never block. The verdict is signed into a replayable envelope keyed to your dbt manifest, so it is tamper-evident and reproducible. ## Architecture — three layers The reviewer is three cooperating layers, ordered by trust. Each blocking decision comes from the most authoritative layer that can decide it; the layers below it fill gaps and add context without ever overriding a proof. ```text ┌──────────────────────────────────────────────────────────────────────┐ │ 3. LLM reviewer (advisory) │ │ Reasons over the diff + compiled SQL + the PR description, GROUNDED │ │ in layers 1–2. Catches intent mismatch, misleading names, business- │ │ logic risk, missing tests, cross-model inconsistency. Clamped to │ │ ≤ warning — enriches the review, never blocks. │ ├──────────────────────────────────────────────────────────────────────┤ │ 2. Deterministic catalog (fallback) │ │ A thin self-verifying catalog for the few signals that need the raw │ │ diff/Jinja and aren't yet AST (schema.yml test removal, single-line │ │ added-only heuristics). Most dbt-specific rules — config/Jinja │ │ (DBT0xx), base-vs-head structural (SC0xx), and SQL anti-patterns — │ │ have MOVED into layer 1 as core AST/minijinja rules. Runs offline, │ │ no warehouse; defers to layer 1 for anything the engine proves. │ ├──────────────────────────────────────────────────────────────────────┤ │ 1. Deterministic engine (authoritative — the only layer that BLOCKS) │ │ The Rust core (`altimate-core`) over PARSED SQL ASTs: query │ │ equivalence, column lineage / DAG blast radius, PII classification, │ │ A–F grade, and AST anti-pattern lint (e.g. division-by-column │ │ without a zero-guard, non-portable dialect functions). Robust by │ │ construction — a string literal or alias can't fool an AST. │ └──────────────────────────────────────────────────────────────────────┘ ``` **How the layers compose** - **Blocking is layer-1 only.** A `REQUEST_CHANGES` verdict is always backed by a proven engine fact (broken lineage, proven non-equivalence, new PII, an enforced contract break). Layers 2–3 can inform and comment, but cannot block on their own — so the verdict stays trustworthy and replayable. - **The engine supersedes the catalog.** When the native engine analyzes a file, the catalog's regex twins for checks the engine covers (cartesian/comma join, `SELECT *`, `NOT IN` on nullables, window-without-partition, division-by-column, dialect-function portability, …) are dropped in favor of the AST verdict. The catalog only surfaces what the engine didn't — and is the sole layer when the engine is unavailable (no manifest / offline), where it is hardened to be literal- and structure-safe. - **The LLM is grounded, not freewheeling.** The reviewer is handed layers 1–2 as context and told not to repeat them; it adds only contextual judgment, treats the diff as untrusted input (prompt-injection hardened), and is force-clamped out of `critical`. If no model is configured, the lane is skipped and the review degrades cleanly to deterministic-only. ______________________________________________________________________ ## Quick start (local) Run the reviewer on your working-tree changes against `origin/main`: ```bash altimate review # human-readable summary altimate review --json # the full signed verdict envelope altimate review --mode gate # exit non-zero on REQUEST_CHANGES (for CI gating) ``` Options: | Flag | Description | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--base ` | Base git ref. Defaults to the merge-base with `origin/main`. | | `--head ` | Head git ref. Omit to review the working tree. | | `--manifest ` | Path to the compiled `manifest.json`. When omitted, the reviewer walks up from the current directory to find the nearest `dbt_project.yml` and uses its adjacent `target/manifest.json`; the discovered path is logged to stderr. | | `--mode comment\|gate` | `comment` never blocks; `gate` exits non-zero on `REQUEST_CHANGES`. | | `--severity ` | Minimum severity to surface: `critical`, `warning`, `suggestion`. | | `--post` | Post the verdict to the GitHub PR (uses `GITHUB_TOKEN` + the Actions event). | | `--no-ai` | Disable the advisory LLM reviewer lane (no model calls / cost) — deterministic-only. | | `--explain-tier` | Emit the classifier's tier-reason list on the verdict envelope so you can see why a diff was rated `trivial`, `lite`, or `full`. Reasons already surface in the PR comment for `full`-tier runs — this flag adds them to `trivial`/`lite` for debugging. | | `--force-tier ` | **[EXPERIMENTAL / bench debug]** Bypass the classifier and force `trivial` / `lite` / `full`. The verdict envelope carries `tierForced: true` and the classifier's original decision for audit. | | `--json` / `--output ` | Emit the verdict envelope as JSON. | > **Full vs lint-only.** With a compiled `manifest.json` present, the reviewer proves lineage and equivalence exactly. Without it (or without a warehouse) it runs **lint-only** and conservatively *warns* on changes it cannot prove safe — clearly labeled, never mistaken for a full verdict. Run `dbt compile` first for the full verdict. Stuck in lint-only mode? It is **not** an API-key problem. The deterministic engine (lineage, equivalence, PII, grade) runs fully offline via the bundled native binary — **no altimate API key or account is required** for any part of the verdict. A key is only ever needed for the *optional* advisory LLM lane (see [below](#model--credentials-for-the-advisory-lane)), and that lane can never block a verdict. Lint-only means the **manifest didn't resolve**, not that auth failed. Check: - **Path.** The default is `target/manifest.json` *relative to the project root you run from*. If your manifest lives elsewhere, pass it explicitly: `dbt_pr_review({ manifest_path: "target/manifest.json" })` (or `--manifest` on the CLI), or set `manifestPath:` in `.altimate/review.yml`. - **Freshness.** A stale manifest that predates the changed models can't resolve them. Run `dbt compile` (or `dbt build`) to regenerate it before reviewing. - **Working directory.** Run the review from the dbt project root so the relative manifest path resolves. Current limitations - **BigQuery equivalence** on some compiled SQL (3-part backtick relations) is currently *undecidable* — the reviewer reports a warning ("could not prove equivalent") rather than an `APPROVE`-on-proof. It never reports a false equivalence; it just can't prove some BigQuery refactors yet. - With no manifest, the SQL dialect defaults to `snowflake`. For a non-Snowflake project, pass a compiled `manifest.json` (its `adapter_type` is auto-detected) or set `dialect:` in `.altimate/review.yml`. Reviewer vs validators `dbt-pr-review` reviews a **PR diff** and emits a verdict. The [completion-gate validators](https://help.altimate.ai/code/data-engineering/validators/index.md) are a different surface — they gate the **agent's own build loop** so it can't declare "done" on failing dbt tests or schema drift. ## GitHub Action Add the review to any repo with a workflow that compiles the project, then runs the review action: Run on `pull_request`, not `pull_request_target` The bot derives the target PR from the Actions event payload. Trigger it on `pull_request` so fork PRs run with a **read-only** token. Do **not** use `pull_request_target` with a checkout of the PR head — that hands a write- scoped token to untrusted PR code (and to the PR's dbt Jinja/macros at compile time). ```yaml name: dbt PR Review on: pull_request: paths: ['models/**', 'macros/**', 'snapshots/**', '**/*.sql', '**/*.yml'] permissions: contents: read pull-requests: write # post the summary + inline review checks: write # the verdict check (gate mode) jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } # Produce target/manifest.json for the full verdict (adapter-specific). - run: pip install dbt-core dbt-bigquery && dbt deps && dbt compile - uses: AltimateAI/altimate-code/github/review@v0.8.5 with: mode: comment # `gate` to block merges manifest_path: target/manifest.json severity_threshold: suggestion # Advisory LLM lane (OPTIONAL — see below). Hosted altimate model: altimate_api_key: ${{ secrets.ALTIMATE_API_KEY }} altimate_instance: ${{ secrets.ALTIMATE_INSTANCE }} # …or bring your own: model: anthropic/claude-sonnet-4-6 # model_api_key: ${{ secrets.ANTHROPIC_API_KEY }} ``` ### Model & credentials for the advisory lane The deterministic engine (lineage, equivalence, PII, grade, lint — the only layer that can **block**) runs entirely from the compiled artifacts and needs **no model or credentials**. The optional layer-3 **LLM reviewer** does — supply it one of two ways, or neither (it self-disables, leaving a deterministic-only review): | Route | Action inputs | Result | | ------------------------- | -------------------------------------------------------------------- | -------------------------------------- | | **Hosted altimate model** | `altimate_api_key` + `altimate_instance` (+ optional `altimate_url`) | uses the altimate-hosted default model | | **Bring-your-own** | `model` (e.g. `anthropic/claude-sonnet-4-6`) + `model_api_key` | uses your provider/model | Always pass keys as repo **secrets**. Warehouse credentials are consumed by the `dbt compile` step (via your `profiles.yml`), **not** by the review step. A complete, copy-paste workflow lives at [`github/review/examples/altimate-ingestion.yml`](https://github.com/AltimateAI/altimate-code/blob/main/github/review/examples/altimate-ingestion.yml). Re-pushing commits updates the same summary comment in place; fixed findings are dropped on the next run. `--post` targets **GitHub** PRs (it reads `GITHUB_TOKEN` / `GITHUB_REPOSITORY` and posts via the GitHub API). On other platforms (e.g. GitLab), run with `--json`/`--output` and post the verdict using that platform's own API — native GitLab posting is not yet built in. ## Configuration — `.altimate/review.yml` Per-repo configuration, the analogue of an `AGENTS.md`. Tune the rubric, choose reviewer lanes, and pick comment-vs-gate without forking: ```yaml mode: comment # comment | gate severityThreshold: suggestion manifestPath: target/manifest.json dialect: snowflake reviewers: [] # empty = risk-tier defaults; or pin lanes dataDiff: # OFF by default — see "Data-diff in CI" below enabled: false warehouse: "" # connection name; empty = default connection exclude: - models/legacy/** riskTierPathTokens: # OFF by default — see "Risk-tier path tokens" below finops: [preset:finops] # promote any FinOps-named path to `full` tier pii: [ssn, email, phone] # or supply your own case-insensitive tokens rubric: blockOn: [lineage_breakage, contract_violation, pii_exposure, semantic_change] warningPatternThreshold: 3 thresholds: warehouseCostMinRows: 1000000 exclusions: allowSelectStarInStaging: true skipNonProdModels: true ``` ### Risk-tier path tokens Named categories under `riskTierPathTokens` promote any diff touching a matching path to `full` review tier, so those areas never auto-approve on `trivial` classification. Tokens are matched **case-insensitively at path, word, or digit boundaries** — not as arbitrary substrings. For example, the token `cost` fires on `models/marts/mrt_cost_daily.sql` (bounded by `_` and `_`) but **not** on `models/broadcaster.sql` (the substring lives inside a longer word). The `preset:finops` marker expands to the built-in FinOps keyword list (cost, billing, spend, revenue, etc.). Before v0.9.3 the FinOps list was hardcoded and always on; it is now opt-in via this config. When a category value is invalid the CLI logs a stderr warning AND surfaces the error in the verdict envelope's `tierReasons[]` (and in the PR comment), so a typo can't silently kill your opt-in. ## Data-diff in CI Static equivalence proves a refactor *can't* change results. **Data-diff** goes further: it runs the base and head SQL **against your warehouse** and reports the actual row/value deltas on the model's key — catching value bugs that static analysis can't decide (e.g. a wrong join key that silently over-/under-counts). It's the right tool when "old ≠ new" but you need to know *how much* and *which rows* changed. Data-diff is **opt-in** because it costs warehouse compute and needs credentials. Enable it and point it at a connection: ```yaml # .altimate/review.yml dataDiff: enabled: true warehouse: prod_ci # a configured connection name; empty = default connection ``` ### Configuring credentials The data-diff lane reads warehouse credentials from a **connection**, resolved in this order (later overrides earlier): 1. `~/.altimate-code/connections.json` (global) 1. `./.altimate-code/connections.json` (repo-local) 1. **Environment variables** — `ALTIMATE_CODE_CONN_` holding a JSON config. This is the CI path: store the JSON in a secret and inject it. 1. A dbt `profiles.yml` (the same profile dbt already uses to compile). The `warehouse:` value in `review.yml` selects which connection by name (the `` suffix, lowercased). Leave it empty to use the default/first connection. In GitHub Actions, supply the connection from a secret — both sides of the diff run against the **same** warehouse (base-compiled vs head-compiled SQL): ```yaml - uses: AltimateAI/altimate-code/github/review@v0.8.5 with: mode: comment manifest_path: target/manifest.json env: # JSON for a single connection named "prod_ci" (referenced in review.yml). ALTIMATE_CODE_CONN_PROD_CI: ${{ secrets.ALTIMATE_DBT_CONNECTION }} ``` `secrets.ALTIMATE_DBT_CONNECTION` is a JSON blob, e.g. for Snowflake: ```json {"type":"snowflake","account":"ab12345.us-east-1","user":"CI_SVC", "password":"…","role":"TRANSFORMER","warehouse":"CI_WH", "database":"ANALYTICS","schema":"DBT_CI"} ``` When no connection resolves, the data-diff lane **skips silently** — the review still runs every other lane. Data-diff never blocks on its own; it surfaces a `warning` so a human confirms the data impact is intended. > **Least privilege:** use a read-only CI role scoped to the schemas under review. The lane only issues `SELECT`s against the compiled base/head SQL. ## Topology-aware equivalence (merge refactors) Model-level equivalence compares a model's base vs head 1:1. A **merge refactor** breaks that assumption: when a PR *deletes* several models and *adds* one that supersedes them (e.g. `int_x_{base,direct,modified}` → `int_x_daily`), the new model has no base to compare against, so plain equivalence skips it. The reviewer detects this shape (≥2 deleted models sharing a name stem with one added model), composes the **base** compiled SQL of the replaced set as `UNION ALL`, and asks the engine whether the new model reproduces it. Because the composition is *inferred* (the replaced models may have been combined differently downstream), this lane is **advisory only** — it never blocks. It surfaces "this merge isn't proven equivalent — verify with a data-diff" and stays silent when the merge is proven equivalent. ## How models are rendered (Jinja → analyzable SQL) dbt models are Jinja templates, so the SQL engine needs *rendered* SQL. The reviewer does **not** re-implement Jinja — it consumes dbt's own compiled output (the same render-then-analyze split dbt-Fusion uses, and what Datafold/Recce do): 1. **Deterministic `dbt-patterns` lane** reads the **raw** model + diff — it needs the Jinja (`{{ config(materialized) }}`, `is_incremental()`, `{{ ref }}`) and the unified diff to detect structural anti-patterns. This lane needs no warehouse and catches the majority of real-world failures. 1. **Engine lanes** (equivalence, grade, lint, PII) consume **dbt-compiled SQL** from `target/compiled//…` (HEAD) and `target-base/compiled/…` (BASE), produced by `dbt compile`. To enable full equivalence verdicts, compile both the base and head refs in CI (the base into `target-base/`, the Recce convention). Without compiled SQL the engine lanes fall back to raw and stay *undecidable* (never fabricated) — the `dbt-patterns` lane still runs. ## What it checks — deterministic rule catalog Every blocking signal is an AST/engine fact in the Rust core, not a regex on text. The deterministic rules group into four families: - **SQL anti-pattern lint (AST).** Parsed-SQL rules that a string literal or alias can't fool — e.g. outer-join filter in `WHERE` (silently turns a `LEFT JOIN` into an inner), NULL-propagating concat, `GREATEST`/`LEAST` over nullables, `DISTINCT` + window non-determinism, cast-division integer truncation, clock functions in a filter (non-idempotent), cast in a join key, `FULL OUTER`/ cartesian (`JOIN` without a condition), `NOT IN (… NULL)`, sum-of-a-ratio, non-portable dialect functions, integer-multiplication overflow, PK-aware join fan-out, timezone-in-hash-key. - **dbt config / Jinja (`DBT0xx`).** A core **minijinja** parser reads `{{ config(...) }}` and the model body: incremental model without an `is_incremental()` guard, `merge`/`delete+insert` without a `unique_key`, microbatch lookahead without `lookback`, enforced contract without `on_table_exists`, `var()` without a default, **hardcoded relation** instead of `{{ ref() }}`/`{{ source() }}`, and materialization-change on diff. - **Structural base-vs-head (`SC0xx`).** An AST comparison of the two model versions (no warehouse needed): `SELECT DISTINCT` added/removed, `UNION` ↔ `UNION ALL`, `GROUP BY` grain shift, surrogate-key column-set change, `COALESCE`/`NVL` removed, a `WHERE` filter removed (output broadens), output type narrowed. - **Engine proofs.** Query equivalence, column-lineage / DAG blast radius, PII classification, and the A–F grade — the only family that can `REQUEST_CHANGES`. **Warehouse-dialect coverage.** Equivalence plans both sides through the engine, so a dialect function the planner doesn't know would make the result *undecidable*. Rather than enumerate every warehouse function, the engine **auto-stubs any unknown function** found in the query — scanning the AST and registering a placeholder (classified scalar vs aggregate by call context) so the plan succeeds across Snowflake / BigQuery / Redshift / Databricks / Trino / DuckDB / Postgres / MySQL / Oracle / T-SQL / ClickHouse. On top of that it normalizes dialect-only *syntax* DataFusion rejects: `QUALIFY` (any dialect) → subquery form so window-filtered dedups decide; date-part keyword args (`date_diff(d, d, DAY)`, `dateadd(DAY, …)`); raw `r'…'` strings; `SAFE.` prefix; dialect cast type names; and array `UNNEST(split(…))`. A representative 39-construct battery across 12 dialects all plan; anything still unrecognized stays *undecidable*, never wrong. ## How it works 1. **Risk-tiering (no LLM).** A deterministic pre-pass classifies the change on *data* signals — blast radius, PII/contract/source touch, materialization and incremental-logic changes — into `trivial` / `lite` / `full`. Expensive lanes only fire when the change warrants them. Any PII, source, contract, snapshot, or migration touch is always `full`. 1. **Engine-backed lanes (layer 1).** For each changed model the relevant lanes run against the Rust core over the parsed AST: lineage/impact, equivalence on before/after SQL, PII via the composite check, SQL grade, and AST anti-pattern lint (`altimate_core.check` → `lint.findings`). The catalog's regex twins (layer 2) for checks the engine covers are then dropped. 1. **AI reviewer lane (layer 3).** When a model is configured, the LLM reviewer runs **after** the deterministic lanes, grounded in their findings, and adds advisory contextual comments (intent, naming, business logic, test coverage). Findings are clamped to ≤ warning and never block. Skipped (clean degrade) if no model is available. 1. **Rubric → verdict.** Findings map to a verdict by a versioned rubric (data, not prompt): any blocking-category `critical` → `REQUEST_CHANGES`; ≥3 warnings → risk pattern → `REQUEST_CHANGES`; only suggestions → `COMMENT`; nothing → `APPROVE`. Only layer-1 findings reach `critical`, so only the engine can block. In `comment` mode, `REQUEST_CHANGES` is posted as comments rather than blocking. 1. **Signed envelope.** The verdict is HMAC-signed (`ALTIMATE_REVIEW_SIGNING_KEY`) and includes the manifest hash, so it is replayable and tamper-evident. ## The safety invariant Query equivalence is undecidable in general. An **undecidable** equivalence result is always a `warning` with `confidence: unknown` — **never** a block. The reviewer never claims a refactor is unsafe when it could not prove it; it asks you to verify with a data-diff instead. A false "this is safe" is worse than a noisy warning, so the rubric clamps unknown/low-confidence findings out of `critical`. ## Agent & skill - Agent: `reviewer` (read-only) — `altimate --agent reviewer`. - Skill: `/dbt-pr-review` — runs the verdict engine and presents the findings. - Tool: `dbt_pr_review` — callable from any agent. # GitHub altimate integrates with GitHub for automated code review and issue handling. ## GitHub Actions Run altimate as a GitHub Actions bot that responds to PRs and issues. ### Setup ```yaml # .github/workflows/altimate.yml name: altimate on: issues: types: [opened, labeled] pull_request: types: [opened, synchronize] issue_comment: types: [created] pull_request_review_comment: types: [created] jobs: agent: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" - name: Install altimate run: npm install -g altimate-code - name: Run agent run: altimate github env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ``` LLM provider required The workflow `GITHUB_TOKEN` is for repository access only — it cannot be used for LLM inference. You must provide a separate API key (e.g., `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`) as a repository secret. GitHub Copilot and GitHub Models providers are automatically disabled in Actions environments. ### Triggers | Event | Behavior | | ------------- | ----------------------------------- | | PR opened | Reviews code, suggests improvements | | PR comment | Responds to review comments | | Issue opened | Analyzes and suggests solutions | | Issue labeled | Triggers specific agent modes | ### PR Commands Comment on a PR to interact with altimate: ```text @altimate review this PR @altimate check for SQL anti-patterns @altimate estimate query costs ``` ## CLI Usage ```bash # Run GitHub integration locally altimate github # Work with PRs altimate pr ``` # GitLab altimate integrates with GitLab for automated merge request review. ## Quick Start Review a merge request from the command line: ```bash export GITLAB_PERSONAL_ACCESS_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx" altimate gitlab review https://gitlab.com/org/repo/-/merge_requests/123 ``` The review is posted as a note on the MR. To print to stdout instead: ```bash altimate gitlab review https://gitlab.com/org/repo/-/merge_requests/123 --no-post-comment ``` ## Authentication Set one of these environment variables: | Variable | Description | | ------------------------------ | --------------------------------------- | | `GITLAB_PERSONAL_ACCESS_TOKEN` | Preferred. GitLab PAT with `api` scope. | | `GITLAB_TOKEN` | Fallback (same scope). | Create a token at: `/-/user_settings/personal_access_tokens` with **api** scope. ## Self-Hosted Instances The instance URL is extracted from the MR URL automatically. To override (e.g., for internal proxies): ```bash export GITLAB_INSTANCE_URL=https://gitlab.internal.example.com ``` ## GitLab CI ### Setup ```yaml # .gitlab-ci.yml altimate-review: image: node:22 stage: review script: - npm install -g altimate-code - altimate gitlab review "$CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID" variables: GITLAB_PERSONAL_ACCESS_TOKEN: $GITLAB_TOKEN ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" ``` ### Model Selection Override the default model with the `--model` flag or `MODEL` / `ALTIMATE_MODEL` env vars: ```yaml - altimate gitlab review "$MR_URL" --model openai/gpt-4o ``` ## Features - AI-powered merge request review - Comment deduplication — re-running updates the existing review note instead of posting duplicates - SQL analysis on data pipeline changes - Supports nested GitLab groups and subgroups - Large MR handling — diffs are automatically truncated when they exceed context limits ## Known Limitations - Reviews are posted as MR-level notes, not inline per-line comments (inline comments planned for a future release). - Large MRs (more than 50 files or exceeding 200 KB of diffs) are automatically truncated. The review will note which files were omitted. # IDE Integration altimate-code integrates with your IDE via the [Datamates extension](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) — listed as **Datamates** in the Marketplace, its in-editor commands and docs are branded **Altimate MCP** — giving you AI-powered chat with 100+ data engineering tools directly in your editor. ______________________________________________________________________ ## Prerequisites Install the altimate-code CLI globally: ```bash npm install -g altimate-code ``` The Datamates extension requires this to be installed for the chat and tools to function. ## Install the Extension Install the Datamates extension for your IDE: - **VS Code** — [Microsoft Marketplace](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) - **Cursor / other VS Code-compatible editors** — [Open VSX Registry](https://open-vsx.org/extension/altimateai/vscode-altimate-mcp-server) - **Windsurf** — Install via the built-in extension marketplace (search "Datamates") ## Open Altimate Code Chat After installing the extension: 1. Press `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux) to open the command palette 1. Type `Altimate MCP` 1. Select **Altimate MCP: Open Altimate Code Chat** This opens the Altimate Code chat panel where you can interact with altimate agents and use all 100+ data engineering tools. ## Features - **Inline chat** with altimate agents — ask questions, run tools, and get results directly in your editor - **File context awareness** — the agent sees your open files and project structure - **Tool call results inline** — SQL analysis, lineage, dbt operations, and more displayed in the chat - **Agent mode switching** — switch between Builder (full read/write), Analyst (read-only), and Plan (minimal access) modes from the command palette - **100+ data engineering tools** — SQL validation, query optimization, column lineage, dbt model generation, FinOps analysis, schema exploration, and more - **Session tracing** — every chat session is recorded as a trace file (the IDE panel runs `altimate-code serve` under the hood, which now writes traces just like the terminal). Inspect them with `altimate-code trace list` / `altimate-code trace view `. See [Traces](https://help.altimate.ai/code/configure/trace/index.md). ## Configuration The extension uses your existing `altimate-code.json` config. No additional IDE-specific configuration is required. Warehouse connections, LLM providers, permissions, and agent settings all carry over. ### Extension settings The extension contributes these VS Code settings (Settings → search "altimate"): | Setting | Default | Description | | ------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `altimate.altimateCodeRequireConsent` | `false` | Ask before downloading and installing the altimate-code CLI. By default the extension installs the CLI automatically the first time chat is opened. When enabled, chat shows an install prompt instead — nothing is downloaded until you confirm, and declining shows manual install instructions. | | `altimate.codeAutoUpdate` | `true` | Keep the CLI up to date automatically in the background. Checked at most once a day, and only runs when the CLI is already installed. | The extension installs the CLI natively: the release archive is fetched over HTTPS from [GitHub releases](https://github.com/AltimateAI/altimate-code/releases), verified against the release's `checksums.txt` (SHA-256), and placed in `~/.altimate/bin` — no shell scripts are executed and nothing outside your home directory is modified. Environments that prefer full control can enable `altimate.altimateCodeRequireConsent` via managed settings, or pre-install the CLI themselves (the extension uses any `altimate` found on `PATH` or in `~/.altimate/bin`). ## LLM Access You need an LLM to power the chat. Two options: - **BYOK (Bring Your Own Key)** — Free and unlimited. Configure any of the [35+ supported providers](https://help.altimate.ai/code/configure/providers/index.md) (Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, etc.) - **[Altimate LLM Gateway](/datamates/user-guide/components/llm-gateway/)** — Managed LLM access with dynamic model routing. 10M tokens free to get started — no API keys to manage ## Full Altimate MCP Documentation The Datamates extension offers additional capabilities beyond Altimate Code Chat, including MCP server integrations, Knowledge Hub, Memory Hub, and Guardrails. See the [Altimate MCP documentation](/datamates/) for full setup guides, integration configuration, and feature details. # TUI altimate launches a terminal-based user interface (TUI) by default. ```bash altimate ``` ## Interface Layout The TUI has three main areas: - **Message area**: shows the conversation with the AI assistant - **Input area**: where you type messages and commands - **Sidebar**: shows session info, tool calls, and file changes (toggle with leader key + `s`) ## Input Shortcuts | Prefix | Action | Example | | ------ | ------------------- | ----------------------------------------------------------------- | | `@` | Reference a file | `@src/models/user.sql explain this model` | | `!` | Run a shell command | `!dbt run --select my_model` | | `/` | Slash command | `/discover`, `/connect`, `/review`, `/models`, `/theme`, `/trace` | ## Leader Key The leader key (default: `Ctrl+X`) gives access to all TUI keybindings. Press leader, then the action key: | Key | Action | | --- | -------------------------------------------- | | `n` | New session | | `l` | List sessions | | `e` | Open editor | | `s` | Toggle sidebar | | `t` | List themes | | `m` | List models | | `i` | Enhance prompt (rewrite with AI for clarity) | | `a` | List agents | | `k` | List keybinds | | `q` | Quit | ## Scrolling - **Page up/down**: scroll messages - **Home/End**: jump to first/last message - **Mouse scroll**: scroll with mouse wheel Configure scroll speed: ```json { "tui": { "scroll_speed": 3, "scroll_acceleration": { "enabled": true } } } ``` ## Agent Switching Switch between agents during a conversation: - Press leader key + `a` to see all agents - Use `/agent ` to switch directly - Built-in agents: `general`, `plan`, `build`, `explore` - Data engineering agents: `builder`, `analyst`, `plan` ## Diff Display Configure how file diffs are displayed: ```json { "tui": { "diff_style": "stacked" } } ``` Options: `"auto"` (default) or `"stacked"`. ## Session Management | Leader + Key | Action | | ------------ | --------------- | | `n` | New session | | `l` | Session list | | `Shift+D` | Delete session | | `Shift+R` | Rename session | | `Shift+F` | Fork session | | `Shift+E` | Export session | | `Shift+C` | Compact session | ## Editor Integration Press leader + `e` to open the current message in your `$EDITOR`. This is useful for composing long prompts or pasting multi-line SQL. # Web UI Altimate Web is a browser-based interface for interacting with altimate's data engineering tools without the terminal. It provides the same conversational agent experience as the TUI, accessible from any browser. - Full chat interface with streaming responses - Agent switching between builder, analyst, and plan modes - File references and tool call results - Session management and history Coming Soon The web UI is currently under development. For now, use the [TUI](https://help.altimate.ai/code/usage/tui/index.md) or [CLI](https://help.altimate.ai/code/usage/cli/index.md) to interact with altimate. # Power User for dbt Only use the following steps for "dbt Cloud" environments. If you have a dbt Core environment, use the [required config instructions for "dbt Core" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfig/index.md). If you have a dbt Fusion environment, use the [required config instructions for "dbt Fusion" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfigFusion/index.md). dbt Cloud integration is available as beta functionality ## Enable dbt Cloud Integration by adding an API key dbt Cloud integration in Power User VSCode extension requires an API key. There are also multiple preview features in the extension including [generate dbt documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md), [column lineage](https://help.altimate.ai/dbt-power-user/test/lineage/index.md), [query explanation](https://help.altimate.ai/dbt-power-user/develop/explanation/index.md), [generate dbt model from SQL](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) that are also enabled with an API key. You can get an API key for free by signing up at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You need to add the API key from "Settings->API key" in your Altimate instance to the VSCode extension settings. You also need to add "Instance name" in the extension settings. Please get your instance name from your Altimate AI URL. If your URL for Altimate instance is - "companyx.app.myaltimate.com", then instance name is "companyx". Go to the VSCode extension settings, and then add an API key and instance name. Here's a demo of how to add an instance name and an API Key to the extension settings ## Use the setup wizard for configuration (recommended) Need to setup environment variables? Refer to this [section](/dbt-power-user/setup/optConfig/#environment-variables-setup) This method will save a bunch of time for you, and you can also validate your configuration. Setup wizard will help you in associating sql files with jinja-sql, selecting the right Python interpreter, make sure dbt dependencies are correctly installed etc. In the end, it will also validate your configuration. You can start the setup wizard by clicking on dbt status icon in the bottom status bar, and performing the following necessary steps as shown in the recorded demo below: **Here are the steps covered in the setup wizard** **Select Python Interpreter** Click on the action button - "Select Python Interpreter" and choose your preferred python interpreter. Usually, choosing an interpreter that's recommended or mapped to your virtual environment software (e.g. venv) as per the list is a good idea. If you know the path of your Python environment, you can choose it from the list, or if the path is not present, you can enter it manually. If needed, please run 'where python' command on terminal to see if it shows path to Python interpreter that you are using. **Install dbt** If dbt is not installed in your environment (dbt status icon on bottom status bar will show it), Click on "Install dbt Cloud" button in the next step. This will install latest version of dbt Cloud CLI in your environment. **Validate Project** Last step is clicking on button - "Validate Project" It will run a bunch of checks to make sure your dbt environment and project are setup correctly. If there are some issues, it will tell you exactly what's wrong as well. If you still can't get the extension setup correctly, please check the [troubleshooting page](https://help.altimate.ai/dbt-power-user/troubleshooting/index.md) ## Recorded Demo ## Questions and Answers #### Is dbt Cloud or dbt Fusion integration free? Answer: Yes, integration with dbt Cloud or dbt Fusion is free and treated the same as integration with dbt Core. It will not count towards the usage quota. #### Why do I need to add the Altimate API key? The API key is necessary for authentication with our backend. VSCode supports login-based authentication, but it often logs out between sessions, which can disrupt the workflow. The API key provides a more stable and streamlined experience. This is particularly beneficial for large teams, allowing them to integrate the key into their deployment secrets when setting up VSCode as a remote environment. In the future, integration with [Cloud Service token](https://docs.getdbt.com/docs/dbt-cloud-apis/authentication)s might be necessary for deeper cloud interactions, thus having the Altimate integration in place from the start makes sense. #### What benefits does registering an API key provide? A direct line of communication with our users is established with the authentication in place. This is essential for efficiently communicating hotfixes, new releases, and deprecation warnings. It helps to minimize operational challenges and ensures that users are not left with outdated versions or unaware of updates due to the limitations of VSCode or lack of IDE restarts. Our main goal is to prevent any disruption in your development environment and to support our users proactively. #### What if I don't want to use preview features or accidentally send data to Altimate? We understand the concern about using preview features and the risk of accidental data transmission. To address this, we have implemented stringent data security practices, which you can review in our [security FAQ](/dbt-power-user/arch/faq/). Our solutions have passed security reviews by several large organizations in the US, and we are open to undergoing similar reviews for your organization. Additionally, we are working on making some preview features available offline through our [open-source Python CLI package](https://github.com/AltimateAI/datapilot-cli). #### How are you addressing concerns about data transmission in preview features? To directly address concerns about data transmission, we have added a "local-mode-only" setting in VSCode. If enabled, this setting prevents backend calls for any feature except authentication. This setting can be reviewed by your security team since our [client code](https://github.com/AltimateAI/vscode-dbt-power-user/blob/master/src/altimate.ts) is open-source. Add the following setting in vscode settings.json ```json { dbt.isLocalMode: True } ``` The Power User for dbt extension is developed and maintained by [Altimate AI](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). We are a software company based in the San Francisco Bay Area and have many large enterprise companies as customers. We have done many security/governance reviews for these companies and we are SOC 2 Type 2 certified. Here is our [Privacy Policy](https://www.altimate.ai/privacy?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) and [Terms of Use](https://www.altimate.ai/terms?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). If you need us to do a security review with your IT / security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ### **Security Measures & Protocols** ### 1. **Is my data encrypted during transmission?** Yes, all data transmitted to and from our service is encrypted using Transport Layer Security (TLS). This ensures that your data remains confidential and cannot be intercepted or tampered with during transmission. ### 2. **How do you prevent unauthorized access to your systems?** Our systems are designed with multiple layers of security: - **Transmission**: We use Transport Layer Security (TLS) to encrypt data during transmission. - **Infrastructure Security**: Our service is hosted on AWS, operating within a Private Virtual Private Cloud (VPC). This provides a secluded environment, significantly reducing intrusion risks. - **Internal Access Controls**: Only authorized developers have access to our servers. Access rights are managed and restricted using AWS's Role-Based Access Control (RBAC) mechanism. ### 3. **Do you comply with industry security standards (e.g., ISO 27001, SOC 2)?** We take security and compliance very seriously at Altimate AI, and we have SOC 2 TYPE 2 certification already. ### 4. **Where are your data centers located, and what security measures are in place there?** Our data centers are managed through Amazon Web Services (AWS), which has facilities in multiple geographic regions around the world. By leveraging AWS, we ensure our users benefit from the rigorous security standards that this leading cloud provider upholds. ### 5. **How are users authenticated and managed?** Users are authenticated with email and password combinations in the SaaS UI. In the VSCode extension, Python package, users use the API key associated with their account. In the enterprise edition, we provide OAuth authentication as well. ### 6. **Do you have a disaster recovery and business continuity plan?** Yes, at Altimate AI, we have a robust disaster recovery plan in place. Our data is backed up frequently to ensure minimal data loss. In the event of any system failure, our recovery processes are designed to restore services within an hour. This quick recovery time minimizes disruptions and ensures the continuity of our services for our users. If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ______________________________________________________________________ ### **Data Privacy & Retention** ### 1. **What data do you collect and for what purposes?** The only data we collect is any feedback you may choose to provide us. This feedback is stored for a brief period of 30 days. Its sole purpose is to assist us in quality improvement efforts, allowing us to identify areas where our models can be further refined and enhanced. We also collect telemetry data as per VSCode guidelines using telemetry framework offered by VSCode. Telemetry is used for error and usage reporting in order to make the extension better. You can disable telemetry if needed, as per instructions [here](https://code.visualstudio.com/docs/getstarted/telemetry#_disable-telemetry-reporting). ### 2. **How do you ensure my data privacy?** At Altimate AI, ensuring the privacy of your data is a top priority. Here's how we uphold it: - **Data Isolation**: We employ a multi-tenant architecture that inherently isolates data on a per-tenant basis. - **Strict Access Controls**: Only a select group of authorized developers can access the collected metadata. We employ Amazon Web Services' Identity and Access Management (IAM) policies to meticulously restrict and control access to our various data stores. ### 3. **How long do you retain my data?** At Altimate AI, we maintain a strict policy of not retaining data related to the requests you make while using our service. The only data we retain is any feedback you may choose to provide us. This feedback is stored for a brief period of 30 days. Its sole purpose is to assist us in quality improvement efforts, allowing us to identify areas where our models can be further refined and enhanced. ### 4. **What's your stance on GDPR?** We do not store any actual customer data, we only store aggregate statistics and metadata. As a result, GDPR data deletion requests do not need to be propagated to us because we do not store such data. Our customers typically do not request or require DPAs. However, we're happy to provide a DPA or review a vendor DPA if your organization needs it. If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ### 5. **What is your cookie policy?** We store only essential cookies, but not to track user data but only to keep few features working as expected. We use only following first party cookies - **Intercom**: Used for support requests. Cookies stored by Intercom and their cookies policy is defined [here](https://www.intercom.com/help/en/articles/2361922-intercom-messenger-cookies) - **Supertokens**: Used for SSO authentication and these cookies will be stored only for tenants with SSO. More details on Supertokens cookies policy can be viewed [here](https://supertokens.com/docs/passwordless/common-customizations/sessions/cookie-consent) ______________________________________________________________________ ### **Use of Data for AI Model Training** ### 1. **Do you use my data to train your AI models?** At Altimate AI, our primary objective is to provide accurate and efficient documentation using our AI models. However, we do not use any specific client data to train our models. Our models are designed to be tenant-agnostic, meaning they do not learn or differentiate based on individual client data. Any data processed by our service is not repurposed for model training or enhancement. ### 2. **How do you ensure my data isn't unintentionally used for model improvement?** We employ strict data isolation and access controls. The multi-tenant architecture isolates data on a per-tenant basis, and our internal access controls ensure that only a select group of authorized developers can access the metadata. Coupled with our tenant-agnostic model approach, our infrastructure is designed to prevent any unintentional usage of your data outside its primary purpose. ### 3. **Can I opt-in or opt-out of allowing my data to be used for model training in the future?** Currently, we do not use client data for model training, so there's no opt-in or opt-out mechanism. If our policy were to change in the future, we would provide users with clear communication and choices regarding the use of their data. If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ______________________________________________________________________ ### **LLM & AI Security** ### 1. **How does Altimate handle LLM access?** Altimate gives you two options for LLM access: - **BYOK (Bring Your Own Key)** — Always free and unlimited. Use your own API keys from any of 35+ supported providers (Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, Ollama, and more). With BYOK, your data goes directly to your chosen provider — **Altimate never sees it**. - **[Altimate LLM Gateway](https://help.altimate.ai/dbt-power-user/arch/llm-gateway/index.md)** — A managed option for users who don't want to manage API keys. The gateway dynamically routes to the best model for each task. See below for its security details. ### 2. **Does the Altimate LLM Gateway store my prompts or responses?** Your full prompts and responses are not retained after processing. Your data is not used to train, fine-tune, or improve any models. The gateway does store limited **metadata** for each request: - Number of prompt and completion tokens - Latency - Model used This metadata is used for billing, performance monitoring, and routing optimization. Additionally, a small number of prompts are sampled for **anonymous categorization** to power routing and model ranking. This categorization is stored completely anonymously and is never associated with your account or user ID. No code, SQL, credentials, or PII are retained. You can opt out of all telemetry by reaching out to us via the Intercom chat built into the [Altimate dashboard](https://app.myaltimate.com). ### 3. **What metadata does the Altimate LLM Gateway collect?** | Metadata | Purpose | | ----------------------------------------- | -------------------------- | | Number of prompt tokens | Usage tracking and billing | | Number of completion tokens | Usage tracking and billing | | Latency | Performance monitoring | | Model used | Routing optimization | | Anonymous prompt categorization (sampled) | Model ranking and routing | Prompt categorization is stored completely anonymously — never linked to your account or user ID. You can opt out via the Intercom chat in the [Altimate dashboard](https://app.myaltimate.com). If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ______________________________________________________________________ ## **What data get sent to the SaaS backend for the preview features?** ### Model Definition - **Model Name:** The name of the model. - **Model Schema:** Schema details of the model. - **Model SQL:** SQL queries related to the model. - **Adapter Type:** Type of adapter used. The above model attributes will be referenced in the following feature descriptions ### 1. Documentation Generations - **Model Attributes:** Refer to the Model Definition. - **Existing Documentation:** Any existing documentation for the model. - **Parent Models:** Corresponding parent models associated with the current model. ### 2. SQL to Model - **SQL:** SQL queries used. - **Adapter Type:** Type of adapter used (Refer to Model Definition for adapter type details). - **All Models Present:** List of all models present. - **All Sources Present:** List of all sources present. ### 3. SQL Explanation - **SQL:** SQL queries used for explanation. - **Adapter Type:** Type of adapter used (Refer to Model Definition for adapter type details). ### 4. Column Lineage - **SQL:** SQL queries related to column lineage. - **Adapter Type:** Type of adapter used (Refer to Model Definition for adapter type details). - **Model Attributes:** Refer to the Model Definition. - **Upstream and Downstream Models Attributes:** Information about all upstream and downstream models. Includes models open in the LINEAGE panel in the extension and additional ones necessary for generating the lineage. (Refer to the model Definition for details about model attributes). ### 5. Defer-to-prod (with saas mode - "DataPilot dbt integration" option) - **dbt manifest file** In the SaaS mode - when you configure "DataPilot dbt integration", manifest files are uploaded to the SaaS instance. If you would like to connect your on-premise storage for manifest file uploads, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. All of the details can be found in the code [here](https://github.com/AltimateAI/vscode-dbt-power-user/blob/master/src/altimate.ts). Please note that we only send meta-data, such as model schema and queries to the backend. We never send actual data to the backend and we do not store any of the meta-data. If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. # Altimate LLM Gateway The Altimate LLM Gateway is a managed LLM service that gives you access to the best AI models — **60-80% cheaper** than buying tokens directly from providers. No API keys to manage, no billing across multiple providers, no rate limits to worry about. ## How It Works The gateway dynamically routes each request to the best model for the task across **Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, and GPT-5.4-mini**. You pay a flat token price regardless of which model handles your request — no surprise bills from expensive model routing. ## Pricing | Plan | Price | Tokens/mo | $/M tokens | Overage (per 1M tokens) | | -------------- | ------ | -------------- | ---------- | ----------------------- | | **Community** | $0/mo | 10M (one-time) | Free | BYOK only | | **Pro Tier 1** | $29/mo | 20M | $1.45 | $5/M tokens | | **Pro Tier 2** | $89/mo | 70M | $1.27 | $3/M tokens | | **Enterprise** | Custom | Custom | Custom | Negotiated | Tokens are counted as input + output combined. All tiers get access to all models — the upgrade incentive is volume, not capability. ## What Would This Cost You Directly? Buying 20M tokens directly from providers: | Model | Direct Cost (20M tokens) | With Altimate Pro Tier 1 | Savings | | ----------------------- | ------------------------ | ------------------------ | ------- | | Sonnet 4.6 | ~$84 | **$29** | ~65% | | Opus 4.6 | ~$140 | **$29** | ~79% | | GPT-5.4 (short context) | ~$75 | **$29** | ~61% | | GPT-5.4 (long context) | ~$135 | **$29** | ~79% | With Altimate, you pay $29 flat regardless of which model handles your task. Buying the same 20M tokens directly from providers would cost $75-140 depending on the model — and you'd have to manage API keys, billing, and rate limits across multiple providers yourself. ## BYOK vs. Gateway | | BYOK (Bring Your Own Key) | Altimate LLM Gateway | | ------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | | **Cost** | Free and unlimited | Token-based pricing (10M tokens free) | | **API Keys** | You manage your own keys | No keys needed | | **Models** | Any model from your provider | Dynamic routing across best-in-class models | | **Data Path** | Direct to your provider — Altimate never sees it | Through Altimate — see [Security FAQ](https://help.altimate.ai/dbt-power-user/arch/faq/#llm-ai-security) for data handling details | | **Best For** | Users with existing API keys or strict data residency requirements | Users who want simplicity and cost savings | Both options are always available. You can use BYOK and the gateway side by side. ## Models Available The gateway routes across the following models based on task complexity, context length, and quality requirements: | Model | Provider | Strengths | | --------------------- | --------- | ----------------------------------------------------------- | | **Claude Sonnet 4.6** | Anthropic | Excellent price/performance for most data engineering tasks | | **Claude Opus 4.6** | Anthropic | Highest quality for complex reasoning and analysis | | **GPT-5.4** | OpenAI | Strong general-purpose capabilities | | **GPT-5.3** | OpenAI | Cost-effective for simpler tasks | | **GPT-5.4-mini** | OpenAI | Fast, lightweight tasks | You don't choose the model — the gateway selects the optimal one for each request automatically. ## Security The Altimate LLM Gateway is designed with enterprise security requirements in mind: ### Data Handling - **Your data is not used to train, fine-tune, or improve any models.** - The gateway stores limited metadata (token counts, latency, model used) for billing and routing. - A small number of prompts are sampled for anonymous categorization to improve routing. See [Security FAQ](https://help.altimate.ai/dbt-power-user/arch/faq/#llm-ai-security) for full details. ### Compliance - **SOC 2 Type II** certified - **TLS 1.3** encryption for all data in transit - AWS infrastructure in private VPC with network isolation - IAM-based RBAC with MFA enforcement for developer access If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ## Getting Started 1. Install the [Datamates extension](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) in your IDE 1. Open the command palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and select **Altimate MCP: Open Altimate Code Chat** 1. The Community plan with 10M free tokens is available immediately — no credit card required To upgrade or manage your plan, visit the [Altimate pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). The Power User for dbt extension is developed and maintained by [Altimate AI](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). We are a software company based in the San Francisco Bay Area, and have many large enterprise companies as customers. ### **Info about pricing plans is available on the [Pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link)** ### 1. **Are you going to charge for current free features in the "power user for dbt" extension?** No. We have no plans to convert previously available free features into paid features. Newly developed features may be released with a credit quota for the free community plan. Please check the [pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) for more details. ### 2. **What exactly is credit for the feature?** You can find the definition of credit for different features in the table below. | Feature | Definition of credit | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Docs Generation | Each generated description = 1 credit. For bulk generation, 3 generated descriptions = 1 credit. If you bulk generate descriptions for more than 300 columns, only first 100 credits are counted | | Column Lineage | Each column lineage generation = 1 credit. Once the lineage for a particular column in a model is generated, no additional credits are counted for that particular column lineage unless VSCode is restarted | | Query Explanation | Each query explanation= 1 credit, Follow-up question = 1 credit | | Model Generation | Each dbt model generation = 2 credits | | Model Updates | Each model change generation = 1 credit | | Tests Generation | Each test generation = 1 credit. No credit count for adding default tests without code generation. | | Defer to Prod | Each dbt command executed with defer flag (saas mode) = 1 credit | | Query Translation | Each query translation = 3 credits | | Project Governance | Each scan = 5 credits. Same project scan is not counted again unless VSCode is restarted. | | Collaboration | One share = 5 credits. It doesn't matter how many comments are added, only first time share operation is counted. | | SQL Visualizer | Each DAG Generation = 1 credit. No additional credits are counted for creating that particular DAB unless VSCode is restarted | | AI agent in UI | Each agent execution = 1 credit | Features that are not listed here, have unlimited free usage. Their usage is not counted towards the no. of credits ### 3. **What is considered an upgrade or downgrade of the subscription?** Upgrade or downgrade of the subscription is determined based on the price of the subscription plan. If the price of the original subscription plan is higher than the price of the newer subscription plan, it's considered a downgrade. If the price of the original subscription plan is lower than the price of the new subscription plan, it's considered an upgrade. ### 4. **What happens during an upgrade of the subscription?** As soon as you upgrade the subscription, changes will be made to your instance for the new subscription. You will be charged the difference between a new subscription price and the prorated current subscription price based on the no. of credits remaining. ### 5. **What happens during a downgrade of the subscription?** Your current subscription will be downgraded at the end of the current billing cycle. There is no refund when you downgrade your subscription, as the subscription is downgraded at the end of the billing cycle. ### 6. **What happens if I change from a yearly subscription to a monthly subscription?** If the price of the monthly subscription is lower than the yearly subscription, it's considered a downgrade. So, the change in the subscription will be made only after the current billing period is over. If you would like to make an immediate change to your subscription, make the change at a yearly plan level. It will be considered an upgrade and will be effective immediately. ### 7. **Do free plan credits refresh every month?** No. Credits on the free community plan are a one-time allowance that lets you try out these features, they do not renew monthly. Any unused credits in your account remain available until used. Once your free credits are used, you can: - Upgrade to a paid subscription for a higher credit allowance, see the [pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) for details, or - Continue using all non-credit features for free, features not listed in the table above remain free. Note: Free plan credits previously refreshed each month. As of July 2026, the free plan includes a one-time credit allowance instead. If you can't find your question here, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via Slack. dbt-power user extension auto-completes model, macro, column names in the VSCode ## Models a) Autocomplete model b) Go to model definition ## Macros a) Autocomplete macro b) Go to macro definition ## Sources a) Autocomplete source b) Go to source definition ## Doc blocks a) Autocomplete doc block b) Go to doc block definition ## Hover actions Hover tooltips expose **Altimate Code** action links so you can ask AI questions about whatever symbol you're inspecting without leaving the file. Clicking an action opens the Altimate Code chat beside the editor with a pre-filled prompt. ### Model hover — `ref('model_name')` - ✨ **Explain transformation** — walks through selects, filters, joins, and aggregations step by step. ### Macro hover — `{{ macro_name(...) }}` - ✨ **Explain what this macro does** — explains purpose, parameters, and usage. - ⚠️ **Find risky usages** — analyzes missing args, wrong types, edge cases, and anti-patterns. Looking for column-level hover actions? When you hover a column's `name:` value in `schema.yml`, two more Altimate Code actions appear — ✏️ **Suggest description** and 🧪 **Suggest tests**. Those live with the doc-generation flow on the [Generate documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/#single-column-hover-shortcut) page. Hover actions delegate to the Datamates extension Like all Altimate Code surfaces, hover actions open the chat panel provided by the **Datamates** extension (`altimateai.vscode-altimate-mcp-server`), which is installed as a dependency of Power User for dbt. The bundled chat handles BYOK or [Altimate LLM Gateway](https://help.altimate.ai/dbt-power-user/arch/llm-gateway/index.md) routing. There are two methods to do it. You can either do it from the top right corner toolbar or from the extension side pane ### Method 1: Build and run models from the toolbar The toolbar action to build models is present on the top right corner of the VSCode as shown in the image below: ### Method 2: Run models from the side panel You cannot build models from the side panel ## When a build fails When `dbt build`, `dbt run`, or `dbt test` fails, the extension surfaces a **Fix with Altimate Code** button so you can jump straight into AI-assisted debugging without copying error text by hand. There are three places the button appears: | Failure point | Where you see it | Prompt sent to Altimate Code | | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------ | | Model fails at runtime (`run_results.json` contains an error) | Notification: *dbt: `my_model` failed* | Run command + failed resource names/types + error messages | | dbt exits **before** generating `run_results.json` (broken `ref()`, missing node, config error) | Notification: *dbt command failed: `dbt run --select my_model`* | Exact dbt CLI command (machine paths stripped) + full stderr | | Failed model / seed / snapshot in the **Run History** panel | Inline 💡 **Fix with Altimate Code** action on the failed row | Run command first, error in a fenced code block | ## Preview compiled code (SQL) The toolbar action to preview compiled code is present on the top right corner of the VSCode as shown in the image below: Query explanation is invaluable to understanding a complex piece of dbt or SQL code (especially written by others!). Requires the Datamates extension Altimate Code features (Explain, Optimize, Change, Translate, Review) open a chat session through the **[Datamates](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server)** extension. Make sure Datamates is installed and active before invoking these actions. ## Start Query Explanation You can get an explanation for the entire query or a selected portion. Select the code you want explained first (or leave nothing selected to explain the whole file), then trigger the action one of four ways. ### 1. Right-click → Altimate Code → Explain with Altimate Open the right-click context menu on a `.sql` (or `.jinja-sql`) file, expand the **Altimate Code** submenu, and choose **Explain with Altimate**. The default Altimate Code submenu shows four actions: **Explain**, **Optimize**, **Change**, and **Translate**. Two more appear conditionally: - **Ask Altimate About Selection** — visible only when text is selected. - **Review with Altimate** — visible only when the file has uncommitted git changes. ### 2. Code lens at the top of the file A code-lens row appears above every SQL file. Click **✦ Explain** to start the same flow. ### 3. Editor title bar → Open Altimate Code Chat The sparkle icon in the editor title bar opens an Altimate Code chat directly. From there you can paste, ask, or use the file as context. ### 4. Utilize SQL actions menu Press "SQL actions" button from the toolbar. It will open the "SQL actions" menu drawer, as shown below. Please select the "Explain query" action. ## Read the explanation in the Altimate Code chat panel Altimate Code opens in a side-panel chat (powered by the Datamates extension). It streams an explanation of the selected code and you can ask follow-up questions in the input box at the bottom. ## Recorded demo Please provide feedback on the generated explanations using thumbs up / down buttons. Your feedback will help us tremendously to improve this functionality. This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You can convert existing SQL into dbt model as below. The extension automatically converts SQL to jinja-sql by populating right references. This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) Generating model from sources defined in yaml file is very easy as below: You can configure a file name template and prefix in the extension settings Why does the generated model appear with the syntax {{ adapter.quote(column_name)}}? This syntax provides a safe way for the adapter to quote the columns. Since the extension supports different adapters, this is the easiest way to ensure that it works for all of them. # Optimize SQL with Altimate Code Optimize with Altimate analyzes a SQL query (or selected snippet) and suggests rewrites for performance — join order, predicate pushdown, redundant scans, unnecessary `DISTINCT` / `ORDER BY`, and dialect-specific anti-patterns. Requires the Datamates extension Altimate Code features (Explain, Optimize, Change, Translate, Review) open a chat session through the **[Datamates](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server)** extension. Make sure Datamates is installed and active before invoking these actions. ## Start an optimization Open a `.sql` (or `.jinja-sql`) file. Optionally select the part you want to optimize — otherwise the whole file is used. You can trigger Optimize from two places. ### 1. Right-click → Altimate Code → Optimize with Altimate Open the right-click context menu on the file, expand the **Altimate Code** submenu, and choose **Optimize with Altimate**. Where to find it **Optimize with Altimate** is the second entry in the Altimate Code submenu (after Explain) and only appears on `.sql` / `.jinja-sql` files. ### 2. Code lens at the top of the file A code-lens row appears above every SQL file. Click **⚡ Optimize** to run the same flow. ## Review the suggestions in the Altimate Code chat panel Altimate Code opens in a side panel and returns a rewritten query alongside an explanation of why each change should help. You can ask follow-up questions (e.g. "show me the EXPLAIN plan for the rewrite", or "keep the CTE structure but only fix the join order") in the input box at the bottom. Please provide feedback on the suggestions using thumbs up / down buttons. Your feedback helps us improve this functionality. This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You can translate SQL queries from one dialect to another using Altimate Code. For example, translate a query in Postgres SQL dialect to Snowflake SQL dialect. Requires the Datamates extension The **Translate with Altimate** action opens a chat session through the **[Datamates](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server)** extension. Make sure Datamates is installed and active before invoking it. ### Supported SQL dialects bigquery, clickhouse, databricks, doris, duckdb, hive, mysql, oracle, postgres, redshift, snowflake, spark, sqlserver, starrocks, synapse, teradata, trino ### Step 1: Create a new file and add the SQL query ### Step 2: Right-click → Altimate Code → Translate with Altimate Open the right-click context menu on the `.sql` file, expand the **Altimate Code** submenu, and select **Translate with Altimate**. Where to find it The Altimate Code submenu shows four default actions: **Explain**, **Optimize**, **Change**, and **Translate**. **Translate with Altimate** is the fourth entry and only appears on `.sql` / `.jinja-sql` files. ### Step 3: Pick source and destination dialects A two-step quick pick appears in VS Code: 1. **Translate SQL — Step 1 of 2** — pick the **source dialect** (the current dialect of the SQL in the file). 1. **Translate SQL — Step 2 of 2** — pick the **target dialect** (the dialect you want to translate to). The adapter type of your current dbt project is bubbled to the top of the list and marked "current project" — you can pick it or choose any other dialect. Translation works on the whole file. Altimate Code will treat the entire file as the source query. ### Step 4: Review the translated SQL and explanation Once both dialects are selected, Altimate Code opens beside the editor and returns the translated SQL alongside an explanation of what changed. Different databases use different functions and syntax for the same operation — Altimate Code translates the differences and explains them. ### Step 5: Convert SQL to dbt Model (optional) If needed, you can convert the translated SQL into a dbt model with the [SQL → dbt Model](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) functionality. ### Limitations Following are a few limitations - If there are functions we can't identify, we will not be able to convert them — they are kept as-is. - We do not look at data types. If the target database does not support some data types, those may not be translated. ### Recorded demo Updating or changing an existing dbt (or SQL) model using natural language is straightforward through Altimate Code. Requires the Datamates extension The **Change with Altimate** action opens a chat session through the **[Datamates](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server)** extension. Make sure Datamates is installed and active before invoking it. ### Step 1: Trigger the operation Open a `.sql` (or `.jinja-sql`) file. Optionally select the portion you want to change. Right-click and choose **Altimate Code → Change with Altimate**. Where to find it The Altimate Code submenu shows four actions by default: **Explain**, **Optimize**, **Change**, and **Translate**. **Change with Altimate** is the third entry and only appears on `.sql` / `.jinja-sql` files. ### Step 2: Describe the change Altimate Code opens in a side panel and asks for context about the change you want. Type the instruction (e.g. "add a column for monthly revenue, joined from `orders`"). It may ask clarifying questions before producing a diff — answer them inline. ### Step 3: Review the accomplished changes Altimate Code shows an Accomplished summary listing every change it made (replaced columns, preserved business logic, validated builds, etc.). Review the summary then continue iterating with follow-up questions if needed. Please provide feedback on the result using thumbs up / down buttons. Your feedback will help us tremendously to improve this functionality. This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) This page covers the setup steps necessary to view your dbt documentation and lineage in the SaaS UI. The steps below ship your manifest.json and catalog.json projects to SaaS UI in order to visualize information like dbt model/column descriptions and column lineage. Please note that this lineage and documentation in UI functionality is not yet supported with dbt 1.8 If you want to re-create any existing dbt core integration using Connections, kindly delete the existing integration first and then create a fresh connection. ## Step 1: Create a dbt Core Connection 1. Navigate to **Settings -> Connections** and click **Create new connection** 1. Select **dbt Core** as the connection type & provide the required connection name & description details 1. Provide **Environment Name** & Click **Create Connection** to create the dbt Core connection | Field | Description | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Connection name | Unique connection name, this can be mapped to your dbt Project | | Connection description | A brief description of the connection (e.g., "Production dbt Core project for analytics") | | Environment name | Environment name can be based on which environment that you are going to upload manifest.json and catalog.json files from. For now, just add the value as "prod" for your production environments. | ## Step 2: Install the open-source DataPilot CLI The next step is to install the latest version of DataPilot CLI. It will be used to upload manifest and catalog files to the SaaS instance. Please run the following command to install the latest version of the DataPilot CLI. ```text pip install altimate-datapilot-cli --upgrade ``` Here's the link to the repo: ## Step 3: Execute the command for uploading the manifest and catalog files Go to **Settings -> Connections** page and click on the dbt core connection name for the connection created. Copy the command for uploading files in the overlay screen on the side. manifest and catalog files don't contain any information about your data. It's all metadata about your environment. Please feel free to check our [security page](/dbt-power-user/arch/faq/) for more info on how we protect your metadata. You need to update the following placeholders in the copied command - | Placeholder | Description | Example | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | Path/to/manifest/file | This is path to your manifest file in the project directory. It's usually stored in the 'target' directory in your dbt project. | ./target/manifest.json | | Path/to/catalog/file | This is the path to your catalog file in the project directory. It's usually stored in the 'target' directory in your dbt project. | ./target/catalog.json | | Path/to/run-results/file | Path to your run results file in the project directory | ./target/run_results.json | | Path/to/semantic-manifest/file | Path to your semantic manifest file in the project directory | ./target/semantic_manifest.json | | Path/to/sources/file | Path to your sources file in the project directory | ./target/sources.json | In addition to the required `manifest.json` and `catalog.json`, we now support uploading additional artifacts — `run_results.json`, `semantic_manifest.json`, and `sources.json` — for richer insights. These are optional but recommended for complete visibility into your dbt project. If you are missing manifest.json or catalog.json files in the target directory, please run the `dbt build` and `dbt docs generate` commands. Also, you can add steps to upload the manifest and catalog files command in your dbt pipelines. That way, you will always have up-to-date documentation and lineage in UI without any manual steps. Here's the sample output after running the command and successfully uploading your files. ```text (.venv) pradnesh@pradneshs-MacBook-Air jaffle_shop % datapilot dbt onboard --backend-url https://api.tryaltimate.com --token 00x0x0x0x0x0x0 --instance-name freemegatenant --dbt_core_integration_id 1 --dbt_core_integration_environment prod --manifest-path ./target/manifest.json --catalog-path ./target/catalog.json Manifest onboarded successfully! Catalog onboarded successfully! Manifest and catalog ingestion has started. You can check the status at https://freemegatenant.demo.tryaltimate.com/settings/integrations/1/prod ``` It takes a few minutes to upload the files and sync that info with the rest of the UI. You can check the status of the upload by going to the link provided in the command output. ## Automating with CI/CD Pipelines To ensure your dbt documentation and lineage in the UI stays up-to-date automatically, we strongly recommend integrating the manifest and catalog upload process into your CI/CD pipeline. This eliminates manual steps and ensures that any changes to your dbt project are immediately reflected in the SaaS UI. ## Automatic Sync with dbt Cloud Connection For dbt Cloud users, you can now set up automatic artifact syncing in the SaaS UI using the dbt Cloud API connection. This eliminates the need for manual file uploads or CLI commands. ### Prerequisites: Create a dbt Cloud Service Token Before setting up the connection, create a service token in dbt Cloud with **Job Viewer** permission. This grants read-only access to the Jobs API for fetching artifacts (manifest.json, catalog.json) from your dbt Cloud runs. 1. Click your account name in the left menu and select **Account settings** 1. Select **Service Tokens** from the left sidebar 1. Click **+ New Token** 1. Enter a descriptive name (e.g., "Altimate Integration") 1. Assign the **Job Viewer** permission and select the projects you want to sync 1. Click **Save** 1. **Important**: Copy and save the token immediately — you won't be able to view it again > **Note**: Permission availability may vary by dbt Cloud plan. Refer to the [dbt Cloud Service Tokens documentation](https://docs.getdbt.com/docs/dbt-cloud-apis/service-tokens) for details. ### Setup Steps 1. Navigate to **Settings -> Connections** and click **Create new connection** 1. Select **dbt Cloud** as the connection type 1. Provide the required connection details: 1. **Service Account Token**: Generate a new Service Token from dbt Cloud Account Settings ([learn more](https://docs.getdbt.com/docs/dbt-cloud-apis/service-tokens)) 1. **Account ID**: Available at `https://cloud.getdbt.com/next/settings/accounts/{{account_id}}` 1. **Custom URL** (optional): For custom dbt Cloud instances (defaults to `https://cloud.getdbt.com/api/v2/`) 1. Click **Test Connection** to verify your setup 1. Configure the sync schedule: - **Scheduled**: Sync artifacts on a regular schedule. Select from Daily, Weekly, or Monthly frequency options and choose the time (UTC) when sync should occur (e.g., Daily at 12:00 AM UTC) - **Real-time**: (Coming soon) Immediate sync when dbt Cloud runs complete 1. Click **Create Connection** After creation, your dbt Cloud projects and environments will be automatically discovered. Automatic syncing keeps your documentation and lineage always up-to-date without manual intervention The dbt cloud connection deletion has a processing delay of a few hours. If you need to recreate the same connection immediately, contact us. This page highlights functionality for searching and viewing documentation for your DBT Projects. Please go to Code -> dbt from the navigation menu on the left-hand side to view all your dbt models, seeds, and other components. [Setups steps](https://help.altimate.ai/dbt-power-user/discover/setupui/index.md) needed for the information to show in SaaS UI ## Search and Filter On top of that, you can search for specific entities or columns by name via the search bar. This search also searches across the descriptions written for models and columns. On the left-hand side, there are different filters available for dbt project name, entity type, materialization etc., so you can filter different entities easily. ## View Schema Suppose you want to get a quick view of the schema. Click "View Schema" button for a particular dbt Model, and the side screen will quickly show the view of schemas. In this view, you can also quickly see the documentation written for the model and columns. ## View Details (Docs) The "View details" button takes you to a more detailed view, where you can see the schema, documentation, lineage, and code information. In addition to schemas, you can also view the actual code and compiled code in the "Code" tab. ## Recorded Demo Using this feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) Also, you need to perform the setup steps outlined on the [Setup UI page](https://help.altimate.ai/dbt-power-user/discover/setupui/index.md) In the DataPilot SaaS UI, you can see model level as well as column level lineage. You can also see the types of changes that occurred during the column lineage traversal e.g. column was unchanged or alias was used [Setups steps](https://help.altimate.ai/dbt-power-user/discover/setupui/index.md) needed for the information to show in SaaS UI ## View Model Level Lineage Go to code -> dbt from the left-hand navigation menu and see the available list of dbt Models. You can also search on the top or use provided filters to find the exact model you are looking for. Click on the "View Details" button and go to the Lineage tab. You can expand the lineage further by clicking on (+) signs on individual blocks. If you click on the specific model in the lineage view, the lineage graph for only that model will be highlighted, as shown in the image above. ## View Column Level Lineage In order to view column-level lineage, first click on "View Details" button in one of models shown in the lineage view. This will display a list of columns present in the model. Click on the column for which you need to view the lineage. Once you click on the column, you will see the column lineage view as below: ## Code transformations You can also see how that particular column was created from previous stage columns via transformation information available as icons at each block level. The following type of transformations are shown in this view: | Type | Description | | -------------- | ----------------------------------------------------- | | Original | The original column in the lineage graph | | Alias | Alias was used on the previous stage columns | | Transformation | Transformation was used on the previous stage columns | | Unchanged | No change was made in the previous stage column | | Not sure | Not known how this column was created | If code is available for a particular transformation, a small code icon is displayed. When you click on the code icon, it shows the list of code transformations that were performed to create that column. ## Recorded Demo Using this feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) Also, you need to perform the setup steps outlined on the [Setup UI page](https://help.altimate.ai/dbt-power-user/discover/setupui/index.md) # Support for dbt Doc Blocks Power User for dbt provides comprehensive support for dbt doc blocks, allowing you to create, manage, and reference documentation blocks throughout your dbt project. ## What are dbt Doc Blocks? Doc blocks are reusable documentation components in dbt that allow you to define documentation once and reference it multiple times across your project. They're defined in `.md` files and can contain any markdown content including text, images, tables, and code snippets. ```markdown {% docs doc_description %} This is a reusable documentation block that can be referenced throughout your dbt project. {% enddocs %} ``` ## Referencing Doc Blocks ### In Schema Files Doc blocks can be referenced in your `schema.yml` files for consistent documentation across models: ```yaml version: 2 models: - name: my_model description: "{{ doc('my_model') }}" columns: - name: model_id description: "{{ doc('model_id') }}" ``` ## Propagating Doc Blocks Using the Propagate Docs Selector - you can select which downstream models you want to propagate docs to: Instead of writing documentation manually, you can generate the documentation! ### Single-column hover shortcut The fastest way to add a description or test to **one** column is to hover the `name:` value of that column in your `schema.yml`. Two Altimate Code actions appear in the hover popup: - ✏️ **Suggest description** — drafts a clear description with business context. - 🧪 **Suggest tests** — suggests appropriate dbt tests (`not_null`, `unique`, `accepted_values`, `relationships`, etc.). Clicking either action opens Altimate Code chat beside the editor with a pre-filled prompt — no need to open the Documentation Editor for a single column. The hover only fires on the **value** of a column's `name:` field — not on the `name` key, not on the dash, not on the description line below. The YAML structure has to match `models: → columns: → name:`. ```yaml models: - name: stg_customers columns: - name: customer_id # ← hover INSIDE these letters description: primary key ``` The popup shows `(column) customer_id` on top with a divider, then the two action links. Column detection uses YAML AST traversal, so it correctly distinguishes column `name:` entries from model-level `name:` entries at any indentation level. Requires `yaml` or `jinja-yaml` language The file's language ID (bottom-right of the editor) must be `yaml` or `jinja-yaml`. If the file shows as "Plain Text" or another language the hover won't fire. The file also has to live inside a workspace the extension recognizes as a dbt project. ### Bulk generate documentation Bulk documentation generation is possible for all columns. You can also choose to bulk-generate documentation only for columns that are missing descriptions. ### Regenerate documentation based on preferences around length and persona We have added the DataPilot chat panel on the left-hand side. There, you can regenerate documentation based on specific preferences e.g. personas, content length. ### Language and Persona Settings When it comes to generating documentation, the following settings are available:\ **Language:** You can choose between French, English, Dutch, German at this time.\ **Personas:** you can choose between technical user, business user and general user. If you specify general user, we don't use specific persona to generate documentation. Settings can be configured in the settings panel. Settings panel is opened by clicking "Settings" button in the top right corner of the Documentation Editor tab. Existing documentation (whether generated or written manually) can be further updated using regeneration functionality with DataPilot. Save changes in YAML file You can save the changes in the existing or a new YAML file with save button at the bottom of the panel. If you see any issues with the content that's saved in the YAML file, please check the [optional config section](https://help.altimate.ai/dbt-power-user/setup/optConfig/#column-name-setup-for-yaml-file-updates). ### Propagate docs to downstream models You can propagate already written descriptions to downstream model columns easily. **First, click on "Docs Propagation" button for the particular column** **Select columns in different models where docs should be propagated** Select the checkboxes for right columns in models and click on the "Propagate documentation to selected models" button ### Personalize and Coach AI You can personalize and coach the Documentation Writer AI teammate. Personalize and Coach Documentation Writer AI Please check more info about how to personalize and coach documentation writer AI teammate [here](https://help.altimate.ai/dbt-power-user/teammates/coach/index.md). If you would like to learn more about AI teammates, please check this [doc page](https://help.altimate.ai/dbt-power-user/teammates/introduction/index.md) ### Documentation Collaboration You can also enable reviews of documentation via collaboration workflow. Please check details [here](https://help.altimate.ai/dbt-power-user/govern/collaboration/#document-collaboration-workflow) ### Interactive Demo Here's a demo of generating model and column descriptions: Document generation or propagation requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai) ### Recorded Demo You can write descriptions for dbt models and columns in the Documentation Editor. The documentation editor also shows the descriptions that were written previously. Those previously written descriptions can be updated as well. For columns that are not referenced in the dbt model, you can click “sync with db” button to get those columns shown in the documentation editor. Save changes in YAML file You can save the changes in the existing or a new YAML file with the save button at the bottom of the panel. If you see any issues with the content that's saved in the YAML file, please check the [optional config section](https://help.altimate.ai/dbt-power-user/setup/optConfig/#column-name-setup-for-yaml-file-updates). You can also generate the documentation, please refer the section on [generate documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md) Collab functionality enables you to discuss code and documentation easily with the stakeholders via VSCode and UI. Many stakeholders are not comfortable using IDE directly; this functionality enables them also to have a discussion with technical users. ## Code Collaboration Workflow Code Collaboration workflow allows you to discuss code without creating a PR ### Start a discussion You can start a discussion at the file or code block levels (single or multiple lines) by pressing (+) sign next to the code. If you click on the display icon as shown in the image above, you can show details of the discussion previously started When a discussion is started, the extension generates dbt docs and uploads those docs to the Altimate AI SaaS instance so that non-technical stakeholders can contribute to the discussion via SaaS UI as well. ### Add a comment Once the discussion is started, you can publish a comment and also tag other users from the Altimate AI SaaS instance. If you don't want to tag the user but still want to share the link with them, just copy the link from the comments box, and share it with them manually (Slack, Email etc.) ### Email notification (if a user is tagged) Tagger user receives an email notification with a link to open the discussion in the Altimate AI UI. ### Non-technical users can reply to comment via UI ### Technical user can see the comment in IDE directly The technical user who started the discussion in IDE can see the replies from other users directly in the IDE. The discussion can continue from here onwards or it can be resolved by clicking resolve action available on top of the comment textbox. Discussion can be started from a UI also similarly, by clicking on (+) sign next to the code blocks. ## Document Collaboration Workflow Table and column descriptions can also be reviewed and discussed with this functionality. ### Start a discussion Discussion can be started via VSCode in the Documentation Editor panel or from SaaS product UI also from the link shared as covered in code collaboration workflow above. ### Add a comment You can add a comment and tag a user to the comment. In that case, that particular user will receive an email notification to open the discussion. Please check the code collaboration workflow for email notification example. ### View all doc discussions You can view all doc discussion on line no. 1 of the model file, and copy discussion links from there. Click on the display icon shown on the left-hand side of line no. 1. You can copy the documentation discussion link from here and share it with other users. You can also resolve the discussion as needed. ## Lineage Export Workflow You can export lineage from IDE to SaaS UI and share the URL with other team members for better collaboration ### Export lineage You can export model-level and column-level lineage. Just click the export button at the top of the panel and give the export a name. Once you create an export, a link will be generated at the bottom. You can copy this link and share it with others. ### View Lineage in SaaS Anyone can use this link, and view the lineage in SaaS UI. You can also view the lineage from the list of all exported lineage views available from "Collab" -> "Export Lineage" left-hand side navigation In order to view the lineage in SaaS UI from the link, a user needs to be registered in the same Altimate AI instance ## Recorded Demo This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) Prevent issues from getting shipped to production! Project governance functionality lets you swiftly scan all dbt projects in your workspace against dbt best practices and organizational guidelines to quickly bring issues to your attention. ## Available via Extension & Python Package Project governance functionality is available in the power user extension and the open-source Python package. Also, the project governance functionality is available as a Python package, so the checks can be integrated in your Git, CI/CD workflows. More details [here](https://datapilot.readthedocs.io/en/latest/insights.html) ## Configure Checks You can configure different checks per your preferences in a local YAML file or the SaaS configuration stored in the Altimate AI backend. Navigate to the Action panel in the extension First, navigate to the Actions panel in the extension and go to "Project Governance" tab. Then, choose the dbt project for which you want to perform a governance check. ### Manual Configuration of Checks The configuration of checks and the list of checks to be performed can be defined in a YAML file. More details on the configuration and YAML file [here](https://datapilot.readthedocs.io/en/latest/configuration.html#project-health-configuration) Select the YAML file by clicking on "Select Config Path" ### SaaS Configuration of Checks SaaS configuration method allows you to share multiple configurations and reference those as per environments, teams, and projects. First, navigate to governance menu item on left hand side nav and choose "new dbt Governance Config". In the governance config, a name and description should be provided. The owner field is automatically populated by the name of the current user. In the model section, you can define regex patterns for names to define different types of models. The default configuration is already pre-populated as: ```text staging: "^stg_.*" # Regex for staging models mart: "^(mrt_|mart_|fct_|dim_).*" # Regex for mart models intermediate: "^int_.*" # Regex for intermediate models base: "^base_.*" # Regex for base models ``` Below that section, there are different types of checks available. Few of the checks, require additional configuration. In that case, please click on the "configure" button next to the check to provide necessary configuration. You can search for specific checks and select / deselect checks that should be included in the config. This list also shows files required to perform the check. Checks require either a manifest file or catalog file or both files. You can filter checks based on the type of files required. Please hit the "save" button after you are done creating dbt Governance config on this screen. Select the right config for checks from the list ## Do the Scan Click the start scan button. You may be asked to install Altimate AI DataPilot package. DataPilot python package is [open source package](https://github.com/AltimateAI/datapilot), that's actually used to do governance checks with the power user extension The scan usually runs in a few seconds, but depending on the size of your project and manifest / catalog files it may take longer. ## View Scan Results View the scan results right below the "Start Scan" button after the scan is finished. Scan results are organized by file type and check type and can be filtered on the same. You can clear results via a button or start the scan again. ## List of Checks Checks between the Python package and Power User extension are the same. You can find a complete list of checks [here](https://datapilot.readthedocs.io/en/latest/insights.html) ## Recorded Demo # Multi Project Support with dbt-loom Power User extension now supports dbt-loom, where native features like query preview, compiled code, column lineage support multi-project references. ## Setup dbt-loom in your project - Instructions on how to [install and configure dbt-loom](https://github.com/nicholasyager/dbt-loom) - Sample project [example with dbt-loom configured](https://github.com/Bl3f/dbt-loom-example) Please make sure dbt_loom.config.yml file is in the root of your multi-project directory ## Reference models from other projects in code via auto-complete Use standard dbt-loom syntax to reference models from other projects. For example, ```text {{ ref('core', 'orders') }} ``` where 'orders' model from the 'core' project is referenced. ## Visualize Lineage with models from the other projects When you visualize the model or column lineage, models from other projects will be shown with the special "ext" type as below. ## Limitations - Clicking on referenced model name in the code, and then opening that model file doesn't work for multi-project references. ## Recorded Demo **Why Notebooks?** Notebooks allow you to codify your usual ad-hoc data analysis, data preparation workflows, so they can be reused. For example, if you have a workflow for standard data analysis - check for duplicates, check timezone field, make sure only certain values are present for a "customer_type" column - you can create a notebook to codify these steps. Then, you can always trigger this notebook with a click of button for a table or data output of particular model to validate or clean the data. In these notebooks, you can create different 'cells' mapping to jinja-sql, python or markdown text in a single file, and you can execute these cells together. **Notebook templates** You can also utilize some out-of-the-box notebook templates for common tasks - e.g. profile the data results, create a config file for the project, create dbt staging models etc. **Notebook sharing** Many times, this ad-hoc work is dependent on organizational best practices and the type of data that your team works on. So, these notebooks can be reused by your team members as well as extended teams. That's why we have enabled sharing - where you can share notebooks with other users in your Altimate AI saas instance. This is especially useful when you have popular notebooks spread across multiple code repositories. We would love to hear your feedback on what additional functionality we can build in this area. If you have encountered any issues in this functionality, please message us over [chat](https://app.myaltimate.com/contactus) ## Enable notebooks in VSCode You just need to add the following line to the settings.json file in your .vscode directory at the root of your repo. ```text "dbt.enableNotebooks": true, ``` If you don't have the .vscode directory at the root of the repo, please create it Then, reload or restart your VSCode. ## Create new notebook You can create a notebook by going to File -> New File and then choosing the option of DataPilot Notebook as shown below. After this, it will give you an option of creating a blank notebook or use one of the existing templates. For now, let's choose a "blank notebook". The first code cell will be automatically created for you. You can add additional code cells or markdown text cells. There are additional options available for the code cell to run cells, split, delete etc. as below After you are done, you can just save the notebook file like any other file in VSCode. ## Use notebook templates There are a few ways in which you can trigger notebook templates. The notebook templates may use some standard Python packages, and VSCode may ask for your confirmation before installing the necessary packages **There is a contextual notebook menu available at the top of the file when you open any SQL file in VSCode** After notebook is created based on the template, just click on "Run all" button on top to execute the notebook and get results. Following notebook templates are available today: ### [Template] Profile the query This template will have two cell blocks. First block will have SQL / jinja query and it will produce preview of data results. The second block will have python code for profiling the query. ### [Template] Get test suggestions This template will recommend tests based on the context of the dbt model, and generate code for those tests as well. ### [Template] Generate dbt base model SQL This template will generate base model SQL based on your input of source name and table information. ### [Template] Generate dbt model yaml This template creates config yaml for documentation and tests for the particular dbt model from where the action is triggered. ### [Template] Generate dbt model CTE This template generates model CTEs from dbt model file. **You can also create notebooks from the "Actions" tab in VSCode (present in the bottom panel)** There are some notebook templates available as pre-configured notebooks. These templates are used at dbt Project level. ### [Template] Generate dbt source yaml Based on schema name specified in the code block, it can generate source yaml for you automatically. You need to provide schema name as an input in the code block. ### [Template] Extract exposures from Metabase This template helps extract exposures from Metabase We would love to hear your feedback on what additional templates or functionality we can build in this area. If you have encountered any issues in this functionality, please message us over [chat](https://app.myaltimate.com/contactus) ## Share notebook Once you save the notebook, you can share it with other users in DataPilot instance. This enables you to share notebooks across repositories with the whole organization. ## Recorded demo # Query History and Bookmarks Now, you can see the history of all the SQL queries or dbt models you ran. So, you can re-run them to view and compare results to see how your data has changed between code changes. You can also look at the compiled SQL code of queries that were run previously. Queries from the query history can also be bookmarked and tagged. So, you can reuse those queries next time you need to do a similar ad-hoc analysis. Users can also share their query bookmarks with other users in your org-specific DataPilot SaaS instance. That way, you can have a shared repository of the most useful queries across the team. Your VSCode session stores only the last 10 queries in the query history, and this info is stored locally on your machine and not in the SaaS instance. ## View Query History You can view query history in the "History" tab of the "Query History" panel. You can also search your query history for specific queries. ## Execute Query from History If you hover over the query from the history, you can perform a few actions, like executing the query (play icon) or bookmarking the query (bookmark icon). If you execute the query, the results are shown in the main code editor window as shown below: In this way, you can [compare query results](/dbt-power-user/test/queryResults/#compare-query-results) between different runs of your query ## Add Bookmark If you execute some query frequently, you can also bookmark that query by clicking the bookmark button when you hover the query entry in the history. You can add tags to your queries for better organization. You can also search your bookmarks by text or by tags. Many users use tags to categorize queries based on a specific purpose or a project. ## Share Bookmark You can share your bookmarks with other users in your Altimate AI instance so they can utilize those queries. When you share a bookmark, it's shared with all the users in "your" Altimate AI SaaS instance. ## View Code Query or bookmark code can be easily viewed by clicking on the query. Also, this code can be opened in the main code editor window by clicking on the icon as shown below: ## Recorded Demo This feature requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) # Configuration Settings This page provides a comprehensive overview of all available configuration settings in the Power User for dbt extension. The settings are organized by category for easy reference. ## Core Settings ### dbt Integration Settings #### dbt.dbtIntegration - **Type**: string - **Default**: "core" - **Options**: ["core", "cloud", "fusion", "corecommand"] - **Description**: Choose how you want to integrate with dbt. Use "core" for local dbt installations with Python bridge, "cloud" for dbt Cloud integration, "fusion" for dbt Fusion CLI integration, or "corecommand" for command-line based dbt core integration. This setting determines how the extension interacts with your dbt environment. #### dbt.dbtPythonPathOverride - **Type**: string - **Description**: Specify a custom path to your Python executable or entrypoint. This is useful when you need to use a specific Python environment different from the VS Code Python extension's default. Most users should leave this empty and configure their Python environment through the VS Code Python extension instead. #### dbt.dbtCustomRunnerImport - **Type**: string - **Default**: "from dbt.cli.main import dbtRunner" - **Description**: Customize the Python import statement used to import the dbt runner. This is only applicable when using dbt core integration. Useful when you have a custom dbt implementation or need to use a specific dbt runner class. #### dbt.installDepsOnProjectInitialization - **Type**: boolean - **Default**: true - **Description**: Controls whether the extension automatically runs dbt deps when initializing a project. When enabled, the extension will automatically install all package dependencies specified in your packages.yml file when you first open a dbt project. ## Project Configuration #### dbt.allowListFolders - **Type**: array of strings - **Default**: [] - **Description**: Specify which folders in your workspace should be considered for dbt operations. This is particularly useful in monorepos or workspaces with multiple dbt projects. Paths should be relative to the workspace root. #### dbt.deferConfigPerProject - **Type**: object - **Description**: Configure how the extension handles model dependencies across environments. - **Properties**: - `deferToProduction`: boolean - When true, allows running models without rebuilding parent models - `manifestPathForDeferral`: string - Path to the manifest file containing parent model information - `favorState`: boolean - When true, uses the deferred state even if the model exists in both environments ## Command Settings #### dbt.runModelCommandAdditionalParams - **Type**: array of strings - **Default**: [] - **Description**: Add extra command-line parameters to all dbt run commands. Each parameter must be a separate array entry. #### dbt.buildModelCommandAdditionalParams - **Type**: array of strings - **Default**: [] - **Description**: Add extra command-line parameters to all dbt build commands. Similar to runModelCommandAdditionalParams, but specifically for build commands. ## Query Settings #### dbt.queryLimit - **Type**: integer - **Default**: 500 - **Minimum**: 1 - **Description**: Controls the maximum number of rows returned when using the Preview SQL Query command. #### dbt.queryTemplate - **Type**: string - **Default**: "select from ({query}\\n) as query limit {limit}" - **Description**: Customize how preview queries are constructed. The template must include {query} and {limit} placeholders. ## UI/Display Settings #### dbt.perspectiveTheme - **Type**: string - **Default**: "Vintage" - **Options**: ["Vintage", "Pro Light", "Pro Dark", "Vaporwave", "Solarized", "Solarized Dark", "Monokai"] - **Description**: Choose the visual theme for the query results viewer. ## Model Generation Settings #### dbt.fileNameTemplateGenerateModel - **Type**: string - **Default**: "{prefix}{sourceName}{tableName}" - **Options**: - "{prefix}{sourceName}{tableName}" - "{prefix}{tableName}" - "{tableName}" - **Description**: Define how new model filenames are generated when creating models from sources. #### dbt.prefixGenerateModel - **Type**: string - **Default**: "base" - **Description**: Set the default prefix used when generating new models from sources. ## SQL Formatting #### dbt.sqlFmtPath - **Type**: string - **Description**: Specify the path to your SQL formatter executable (sqlfmt). #### dbt.sqlFmtAdditionalParams - **Type**: array of strings - **Default**: [] - **Description**: Add extra parameters to the SQL formatting command. ## Altimate AI Integration #### dbt.altimateAiKey - **Type**: string - **DisplayName**: "Altimate AI API Key" - **Description**: Required for features that need backend support. Sign up for a free Altimate AI account at app.myaltimate.com/register. #### dbt.altimateInstanceName - **Type**: string - **DisplayName**: "Altimate AI Instance Name" - **Description**: The instance name for your Altimate AI account. ## Feature Toggles #### dbt.enableNewLineagePanel - **Type**: boolean - **Description**: Enable or disable the new lineage panel in dbt. #### dbt.enableCollaboration - **Type**: boolean - **Default**: true - **Description**: Enable or disable the documentation collaboration features. #### dbt.disableQueryHistory - **Type**: boolean - **Default**: false - **Description**: Control whether the extension keeps track of your query history and bookmarks. #### dbt.enableNotebooks - **Type**: boolean - **Default**: false - **Description**: Enable or disable the Datapilot notebooks feature. ## Lineage Settings #### dbt.lineage.showSelectEdges - **Type**: boolean - **Default**: true - **Description**: Control the visibility of SELECT statement relationships in the lineage graph. #### dbt.lineage.showNonSelectEdges - **Type**: boolean - **Default**: false - **Description**: Control the visibility of non-SELECT relationships in the lineage graph. #### dbt.lineage.defaultExpansion - **Type**: number - **Default**: 1 - **Description**: Set how many levels of relationships are automatically expanded when viewing the lineage graph. ## Other Settings #### dbt.unquotedCaseInsensitiveIdentifierRegex - **Type**: string - **Description**: Define a regular expression pattern to identify unquoted identifiers in your SQL code. #### dbt.conversationsPollingInterval - **Type**: integer - **Default**: 900 - **Minimum**: 30 - **Description**: Set how frequently (in seconds) the extension checks for new comments and conversations in documentation. # Cursor IDE: Installation Workaround Known Cursor Issue Some Cursor IDE users experience the Power User for dbt extension installation freezing for several minutes, followed by a **"Failed to fetch"** error dialog. This is a **known issue on Cursor's side** and has been reported and acknowledged by the Cursor team. See the [Cursor forum thread](https://forum.cursor.com/t/dbt-power-user-extension-installation-freezes-with-repeated-extensionquery-requests-and-failed-to-fetch-error/149385/4) for details. Until the Cursor team resolves this, please try the workarounds below. ## Problem When installing the Power User for dbt extension in Cursor IDE: 1. The installation **freezes for several minutes** with repeated `extensionQuery` requests. 1. An error dialog appears with a **"Failed to fetch"** message. 1. The extension fails to install through the normal marketplace flow. ______________________________________________________________________ ## Workaround 1: Register extension metadata and reinstall This workaround tricks Cursor into recognizing the extension entry, then lets you cleanly reinstall it. **Step 1.** Open the Cursor extensions metadata file at: | Platform | Path | | ------------- | -------------------------------------------------- | | macOS / Linux | `~/.cursor/extensions/extensions.json` | | Windows | `%USERPROFILE%\.cursor\extensions\extensions.json` | **Step 2.** Add the following JSON object to the array in that file: Update the paths Replace `` with your actual home directory path (e.g. `/Users/jane`, `/home/jane`, or `C:/Users/jane`). ```json { "identifier": { "id": "innoverio.vscode-dbt-power-user" }, "version": "0.59.1", "location": { "$mid": 1, "fsPath": "/.cursor/extensions/innoverio.vscode-dbt-power-user-0.59.1-universal", "path": "/.cursor/extensions/innoverio.vscode-dbt-power-user-0.59.1-universal", "scheme": "file" }, "relativeLocation": "innoverio.vscode-dbt-power-user-0.59.1-universal", "metadata": { "installedTimestamp": 1768889206275, "pinned": false, "source": "gallery", "id": "4e4743d1-e423-44b9-88a4-d639da0996d1", "publisherId": "4a9e9d34-3546-42a6-971d-5a640a726245", "publisherDisplayName": "Altimate Inc.", "targetPlatform": "universal", "updated": false, "private": false, "isPreReleaseVersion": false, "hasPreReleaseVersion": false } } ``` Validate your JSON If `extensions.json` already has other entries, make sure to add a comma separator between objects so the JSON remains valid. **Step 3.** Save the file. **Step 4.** The extension will now appear as installed in Cursor, but it is not actually installed yet — this is just a metadata entry. **Step 5.** Reload the Cursor window: - Press `Cmd + Shift + P` (macOS) or `Ctrl + Shift + P` (Windows/Linux) - Type **"Developer: Reload Window"** and press Enter **Step 6.** Open the Power User for dbt extension page. You will see an error that the extension files don't exist — this is expected: ```text Unable to read file '.../.cursor/extensions/innoverio.vscode-dbt-power-user-0.59.1-universal/package.json' ``` **Step 7.** **Uninstall** the extension, then **reinstall** it. You can choose any version you want to install. The installation should now complete successfully. ______________________________________________________________________ ## Workaround 2: Manual VSIX installation If Workaround 1 does not resolve the issue, you can manually install the extension using a `.vsix` file. **Step 1.** Download the `.vsix` file from the [Open VSX Registry](https://open-vsx.org/extension/innoverio/vscode-dbt-power-user): - Go to the extension page and click **Download** to get the `.vsix` file. **Step 2.** Install the `.vsix` file in Cursor: - Open the **Extensions** panel in Cursor - Drag and drop the downloaded `.vsix` file into the Extensions panel The extension will install directly from the file, bypassing the marketplace fetch entirely. ______________________________________________________________________ Still having issues? If neither workaround resolves the problem, please reach out on the [#tools-dbt-power-user](https://getdbt.slack.com/archives/C05KPDGRMDW) Slack channel or [contact support](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). ## Frequently Asked Questions - **Why am I receiving a "Network Error" message when trying to log into my Altimate AI account on the Sign In page?** When logging into your Altimate AI account on the Sign In page, if you encounter a "Network Error" message, it's likely due to the use of the general URL: https://app.myaltimate.com/login. At Altimate AI, we assign a unique URL to each tenant as part of our commitment to ensuring data isolation and providing a seamless user experience. Therefore, to access your account without any issues, it's crucial to use the specific URL that was uniquely created for you at the time of your account registration. - **How to Customize the Target Profile for VS Code Power User for dbt Extension Functions?** To customize the target profile in VS Code for Power User for dbt extension functions, follow these steps: Open Your dbt Project: Ensure you have your dbt project open in VS Code where the Power User for dbt extension is installed. Locate the profiles.yml File: This file contains the configuration for your different dbt profiles. By default, the extension uses the 'dev' profile. Edit the Profile: In the profiles.yml file, you can define multiple profiles. Each profile can have different settings for your database connection and other preferences. Set Your Desired Profile: To change the active profile, you can use the dbt CLI command `dbt --profile your_profile_name debug` in the integrated terminal of VS Code. Alternatively, some extensions allow profile selection through the extension settings. Check if Power User for dbt has such an option by going to the extension settings in VS Code. Restart VS Code: After making changes, restart VS Code to ensure that the new profile settings are loaded. Verify the Change: Run a command like "compiled dbt preview" or "query preview" to verify that the extension is now using your specified profile. We've released our [Datamates Extension](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) - to give you the power to use AI TeamMates! [Click here](/datamates/) to learn more. There are a few different ways in which extension can be installed. You can install it natively or in a dev container. ## Install the extension natively You can install the extension from VSCode directly or from the [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user) You can install the extension from Cursor or any other VSCode compatible editors directly or from the [Open VSX Registry](https://open-vsx.org/extension/innoverio/vscode-dbt-power-user) Cursor IDE users: Installation may freeze Some Cursor users experience the extension installation freezing for several minutes and showing a "Failed to fetch" error. This is a known Cursor issue. If you encounter this, please follow the [Cursor installation workaround](https://help.altimate.ai/dbt-power-user/setup/cursor_installation_workaround/index.md) to resolve it. Here's how to install the extension in VSCode Need to setup environment variables? Refer to this [section](/dbt-power-user/setup/optConfig/#environment-variables-setup) If you are seeing the message "Reload required", please reload the VSCode or restart the VSCode. ## Install the extension in a dev container (or in codespaces) You need to do the below steps only if you need to setup the extension in a devcontainer (or GitHub Codespaces) Please add the following configuration in to your devcontainer.json file: ```text "customizations": { "vscode": { ... "files.associations": { "*.yaml": "jinja-yaml", "*.yml": "jinja-yaml", "*.sql": "jinja-sql", "*.md": "jinja-md" }, ... }, "extensions": [ ... "innoverio.vscode-dbt-power-user", ... ] } } ``` Please do NOT forget to do required configuration based on your dbt setup: [dbt Core](https://help.altimate.ai/dbt-power-user/setup/reqdConfig/index.md), [dbt Cloud](https://help.altimate.ai/dbt-power-user/setup/reqdConfigCloud/index.md), or [dbt Fusion](https://help.altimate.ai/dbt-power-user/setup/reqdConfigFusion/index.md), and [optional configuration](https://help.altimate.ai/dbt-power-user/setup/optConfig/index.md)!! ## Environment Variables Setup There are multiple sources from where the extension reads the environment variables. - [Using vscode Integrated terminal Profiles](#environment-variables-setup-using-the-integrated-terminal-profiles-vscodesettingsjson) - [Variables set outside of Visual Code in .zshrc or .bashrc](#environment-variables-set-outside-of-visual-code-zshrc-bashrc) - [dot env file (we get this from python extension)](#environment-variables-through-pythonenvfile) Environment variable available in vscode terminal doesn't necessarily will be available to the extension. Extension can only read environment variables if available in the above sources ### Environment variables set outside of Visual Code (.zshrc, .bashrc, ...) If you have variables set in .zshrc or .bashrc the extension automatically picks it up. These environment variables will be passed to all operations of the extension. If you make changes to the environment variables you need to restart vscode. The environment variable should be valid for all your dbt projects. For example DBT_PROFILES_DIR can be set to ., that way dbt will lookup the profiles.yaml file inside the root of the dbt project. ### Environment variables setup using the integrated Terminal Profiles ( .vscode/settings.json ) The extension will read any VSCode configurations in .vscode/settings.json and pass them to all operations of the extension: OSX: ```text "terminal.integrated.env.osx": { "ENV_VARIABLE_NAME": "VALUE" } ``` Windows: ```text "terminal.integrated.env.windows": { "ENV_VARIABLE_NAME": "VALUE" } ``` Linux: ```text "terminal.integrated.env.linux": { "ENV_VARIABLE_NAME": "VALUE" } ``` The official documentation can be found [here](https://code.visualstudio.com/docs/terminal/profiles) Visual Code variable substitution is not supported except the environment variable pattern ${env:\*} and ${workspaceFolder}. ### Environment variables through python.envFile The extension also loads an environment variable definitions file identified by the python.envFile setting. The default value of this setting is `${workspaceFolder}/.env`. This way supports all Visual Code variable substitution patterns but the environment variables will not be available to the vscode terminal. Read all about [environment variables](https://code.visualstudio.com/docs/python/environments#_environment-variables) supported by the Visual Code Python extension. Make sure the .env file is in the [right format](https://www.dotenv.org/docs/security/env) or else the extension won't be able to detected the variables. ### Listing Environment Variables detected by the extension We have a debugging utility available within the extension that lists down the environment variables available to the extension and the source from where it is read. Here is how you can trigger the debugging utility 1. Cmd +Shift + P (Ctrl + Shift + P in case of windows) to start the VSCode command bar 1. Select the option Power User for dbt: Print environment variable 1. It should print all the environment variables detected and the sources as well In certain scenarios, step 3 has to be executed twice to get the environment variables printed. ### Default DBT Env Support The following env variables when set are automatically picked by the extension DBT_PROFILES_DIR : This is used to override the folder where profiles file is located DBT_TARGET_PATH : This is for overriding the dbt target path ## Custom dbt Runner The dbt.dbtCustomRunnerImport configuration can be used to plug your own dbt runner. This dbt runner has to invoke dbt but can perform authentication or additional configuration steps before invoking dbt or your own custom dbt executable. Code can be imported from the selected Python environment, so just install your own library or inline the code in the configuration. Note that the Python code should be written in one line. For example let's add this custom dbt runner in your project root folder, called `my_custom_runner.py` . In this case we inherit from the existing dbtRunner from dbt, but that's optional, as long as the interface is compatible with dbt, it should work as expected. ```python from typing import List from dbt.cli.main import dbtRunner, dbtRunnerResult class MyCustomRunner(dbtRunner): def invoke(self, args: List[str], **kwargs) -> dbtRunnerResult: print("Here you can perform setup or authentication or modify args") super().invoke(args, **kwargs) ### patch the dbtRunner dbtRunner = MyCustomRunner ``` Now in the vscode config json add an entry for `"dbt.dbtCustomRunnerImport”` . ```json { "dbt.dbtCustomRunnerImport”: “from my_custom_runner import dbtRunner” } ``` Note that the custom dbtRunner is only used for dbt command invocations. Some operations like metadata fetching, query execution will directly use dbt api and will therefore not use the instructions set up in the custom dbt runner. For more information you can check out these resources: - [Programmatic Invocation Support in dbt](https://docs.getdbt.com/reference/programmatic-invocations) - [dbt Runner Implementation in dbt core](https://github.com/dbt-labs/dbt-core/blob/ddd6506beafd410847d0702267c1e87150377668/core/dbt/cli/main.py#L43) ## [Deprecated] MSSQL, Synapse, Oracle - Query Preview Config It is no longer required to specify query template for any of the adapter. Your database may not support standard SQL LIMIT statements like `SELECT * from table LIMIT 10`. You can override this default behaviour through `dbt.queryTemplate`. Please make a PR in the [dbt-power-user repo](https://github.com/AltimateAI/vscode-dbt-power-user) if you find that you need to change `dbt.queryTemplate` for your favourite adapter and help the community. ### `dbt.queryTemplate` for Oracle Change to `select * from ({query})\n where ROWNUM <= {limit}` ### `dbt.queryTemplate` for MS SQL, Synapse Change to `set rowcount {limit}; {query}` or `{query}\n order by 1 OFFSET 0 ROWS FETCH FIRST {limit} ROWS ONLY` (note that your query can't have an order by clause). ## Enable color highlighting of terminal output on Windows These instructions are for setting the TERM environment variable to xterm-256color in a VSCode terminal instance. This configuration instructs the terminal to operate in a mode that supports 256 colors and various text formatting options, enhancing the display of colored output. So, the relevant dbt command outputs e.g job status "Success" or "Failure" are shown in the right color. ```text "terminal.integrated.env.windows": { "TERM": "xterm-256color" } ``` Above instructions for color highlighting are for Windows machines only ## Skip Project To specify project folders explicitly and control which projects are included in the build process, you can configure the `dbt.allowListFolders` setting. This can be particularly useful when you have a large number of projects in the same workspace. You can define workspace-relative paths to include as follows: ```json "dbt.allowListFolders": [ "folder1", "folder2" ] ``` ## Configure Source to Model file name template You can configure the file name template for source to model files. To do so, go to the extension setting and choose the template you want to use and specify the prefix. ## Configure sqlfmt sqlfmt is a SQL formatter that you can use with dbt-power-user VSCode extension so your dbt models are always correctly formatted. ### Install `sqlfmt` We recommend installing sqlfmt with the jinjafmt extra (which will also install the Python code formatter, Black). Install sqlfmt by running, ```text pipx install 'shandy-sqlfmt[jinjafmt]' ``` If you don't have 'pipx' installed, please install it using instructions [here](https://github.com/pypa/pipx). Find more about sqlfmt in their [docs](https://docs.sqlfmt.com/getting-started/installation). ### Configure `dbt.sqlFmtPath` or `dbt.sqlFmtAdditionalParams` You can configure the path to sqlfmt through `dbt.sqlFmtPath` and you can configure additional parameters through `dbt.sqlFmtAdditionalParams`. ### Usage Please select "Power User for dbt" (extension id:`innoverio.vscode-dbt-power-user`) as the default formatter. You can do this either by using the context menu (right click on a open dbt model in the editor) and select "Format Document With...", or you can add the following to your settings: ```json "[jinja-sql]": { "editor.defaultFormatter": "innoverio.vscode-dbt-power-user" } ``` ### Format on save You can enable format on save for python by having the following values in your settings: ```json "[jinja-sql]": { "editor.defaultFormatter": "innoverio.vscode-dbt-power-user", "editor.formatOnSave": true } ``` ## Setup Altimate API credentials using Environment variables You can now setup the Altimate Instance Name and Key using environment variables add following entries to .env file ```bash ALTIMATE_KEY= ALTIMATE_INSTANCE_NAME= ``` Now, the vscode settings.json to include ```text { "dbt.altimateAiKey": "${env:ALTIMATE_KEY}", "dbt.altimateInstanceName": "${env:ALTIMATE_INSTANCE_NAME}" } ``` This setting is available in v0.37.9 and onwards. ## Column name setup for YAML file updates DataPilot can update your YAML files when documentation or tests are added or edited. Different databases use different column casing conventions. For example, Snowflake always uses upper-case column names, whereas Postgres uses lower-case column names by default. These database-specific standards may create issues in DataPilot behavior without the correct configuration. These issues may include - - The documentation editor may save column names in incorrect casing in YAML files. - Operations like "bulk generate" documentation for missing columns may generate documentation for existing columns. If you are facing these issues, you can adjust the following settings: - New column names are always saved in lowercase in YAML files, except for columns with [quoted identifiers](https://docs.getdbt.com/reference/resource-properties/quote), regardless of the database. (dbt handles database-specific casing automatically this way) If you want to save the column name as it is in the database, set `dbt.showColumnNamesInLowercase`=false in .vscode/settings.json - If you update documentation or tests for the existing columns, we will not change the casing for column names that are already present in YAML files If there are columns with [quoted identifiers](https://docs.getdbt.com/reference/resource-properties/quote), we don't change the casing of such columns; we add the 'quote: true' attribute for those columns. You can also set a regex string to find unquoted identifiers by adding `dbt.unquotedCaseInsensitiveIdentifierRegex`= 'your_regex' in .vscode/settings.json or change it in VSCode extension settings. ## Disable setup walkthrough pop-up To disable the popup that prompts for extension to be setup when loaded for the first time set the setting dbt.hideWalkthrough to true in vscode's settings.json ```text { "dbt.hideWalkthrough": true } ``` Only use the following steps for "dbt Core" environments. If you have a dbt Cloud environment, use the [required config instructions for "dbt Cloud" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfigCloud/index.md). If you have a dbt Fusion environment, use the [required config instructions for "dbt Fusion" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfigFusion/index.md). ## Use the setup wizard for configuration (recommended) Need to setup environment variables? Refer to this [section](/dbt-power-user/setup/optConfig/#environment-variables-setup) This method will save a bunch of time for you, and you can also validate your configuration. Setup wizard will help you in associating sql files with jinja-sql, selecting the right Python interpreter, make sure dbt dependencies are correctly installed etc. In the end, it will also validate your configuration. You can start the setup wizard by clicking on dbt status icon in bottom status bar, and perform following necessary steps as shown in click-through demo below: **Here are steps covered in the setup wizard** **Select Python Interpreter** Click on the action button - "Select Python Interpreter" and choose your preferred python interpreter. Usually, choosing interpreter that's recommended, or mapped to your virtual environment software (e.g. venv) as per the list is a good idea. If you know the path of your Python environment, you can choose it from the list or if the path is not present there, you can enter it manually. If needed, please run 'where python' command on terminal to see if it shows path to Python interpreter that you are using. **Install dbt** If dbt is not installed in your environment (dbt status icon on bottom status bar will show it), Click on "Install dbt" button in the next step. It will ask for dbt version and adapter that's need for your database environment (e.g. Snowflake). Based on these inputs, setup wizard will automatically install dbt in your environment **Install dbt deps** Many times project failures or weird errors are seen if dbt dependencies are not installed. In this step, once you click on 'Run dbt deps' button, setup wizard will automatically run dbt deps command for your project. **Validate Project** Last step is clicking on button - "Validate Project" It will run a bunch of checks to make sure your dbt environment and project are setup correctly. If there are some issues, it will tell you exactly what's wrong as well. If you still can't get the extension setup correctly, please contact us via slack or chat through [support page](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) ## Manual method of configuration Please follow the manual method only if you couldn't use the setup wizard above. ### Associate \*.sql files with jinja-sql There are two different methods to do this. Please follow only one method: #### Method 1: Configure in Preferences > Settings in the extension #### Method 2: Update the settings.json file directly Type 'settings.json' in the VS Code command pallet to open it and add following lines at the end of settings.json ```text "files.associations": { "*.sql": "jinja-sql", "*.yml": "jinja-yaml" }, ``` ### Associate Python Interpreter with dbt installation Ensure that the Python interpreter selection is always visible on the bottom strip of the VS Code for ease of use: Enable python interpreter visibility by updating VSCode settings Select the Python interpreter that has dbt installed. Tip If you select a python environment with dbt already installed, the dbt label on the bottom strip of the VS Code will show a checkmark. If dbt is shown as not installed in the extension, the extension can install dbt for you automatically - just click on the dbt status icon on the bottom strip of the VSCode. Warning for Python path overrides Avoid using the setting dbt.dbtPythonPathOverride unless using Meltano, the extension depends on the Python interpreter for visual code compatible environment variable parsing. ## Enable SaaS features by adding API key There are multiple features in the extension, including [generate dbt documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md), [column lineage](https://help.altimate.ai/dbt-power-user/test/lineage/index.md), [query explanation](https://help.altimate.ai/dbt-power-user/develop/explanation/index.md), [generate dbt model from SQL](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) that require an API key. You can get an API key for free by signing up at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You need to add the API key from "Settings->API key" in your Altimate instance to the VSCode extension settings. You also need to add "Instance name" in the extension settings. Please get your instance name from your Altimate AI URL. If your URL for Altimate instance is - "companyx.app.myaltimate.com", then instance name is "companyx". Go to VSCode extension settings, and add API key and instance name there. Here's demo of how to add instance name and API Key to the extension settings Only use the following steps for "dbt Cloud" environments. If you have a dbt Core environment, use the [required config instructions for "dbt Core" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfig/index.md). If you have a dbt Fusion environment, use the [required config instructions for "dbt Fusion" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfigFusion/index.md). dbt Cloud integration is available as beta functionality ## Enable dbt Cloud Integration by adding an API key dbt Cloud integration in Power User VSCode extension requires an API key. There are also multiple preview features in the extension including [generate dbt documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md), [column lineage](https://help.altimate.ai/dbt-power-user/test/lineage/index.md), [query explanation](https://help.altimate.ai/dbt-power-user/develop/explanation/index.md), [generate dbt model from SQL](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) that are also enabled with an API key. You can get an API key for free by signing up at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You need to add the API key from "Settings->API key" in your Altimate instance to the VSCode extension settings. You also need to add "Instance name" in the extension settings. Please get your instance name from your Altimate AI URL. If your URL for Altimate instance is - "companyx.app.myaltimate.com", then instance name is "companyx". Go to the VSCode extension settings, and then add an API key and instance name. Here's a demo of how to add an instance name and an API Key to the extension settings ## Use the setup wizard for configuration (recommended) Need to setup environment variables? Refer to this [section](/dbt-power-user/setup/optConfig/#environment-variables-setup) This method will save a bunch of time for you, and you can also validate your configuration. Setup wizard will help you in associating sql files with jinja-sql, selecting the right Python interpreter, make sure dbt dependencies are correctly installed etc. In the end, it will also validate your configuration. You can start the setup wizard by clicking on dbt status icon in bottom status bar, and performing following necessary steps as shown in the recorded demo below: **Here are the steps covered in the setup wizard** **Select Python Interpreter** Click on the action button - "Select Python Interpreter" and choose your preferred python interpreter. Usually, choosing interpreter that's recommended, or mapped to your virtual environment software (e.g. venv) as per the list is a good idea. If you know the path of your Python envionment, you can choose it from the list or if the path is not present there, you can enter it manually. If needed, please run 'where python' command on terminal to see if it shows path to Python interpreter that you are using. **Install dbt** If dbt is not installed in your environment (dbt status icon on bottom status bar will show it), Click on "Install dbt Cloud" button in the next step. This will install latest version of dbt Cloud CLI in your environment. **Validate Project** Last step is clicking on button - "Validate Project" It will run a bunch of checks to make sure your dbt environment and project are setup correctly. If there are some issues, it will tell you exactly what's wrong as well. If you still can't get the extension setup correctly, please check the [troubleshooting page](https://help.altimate.ai/dbt-power-user/troubleshooting/index.md) ## Questions and Answers #### Is dbt Cloud integration free? Answer: Yes, integration with dbt Cloud is free and treated the same as integration with dbt Core. It will not count towards the usage quota. #### Why do I need to add the Altimate API key? The API key is necessary for authentication with our backend. VSCode supports login-based authentication, but it often logs out between sessions, which can disrupt the workflow. The API key provides a more stable and streamlined experience. This is particularly beneficial for large teams, allowing them to integrate the key into their deployment secrets when setting up VSCode as a remote environment. In the future, integration with [Cloud Service token](https://docs.getdbt.com/docs/dbt-cloud-apis/authentication)s might be necessary for deeper cloud interactions, thus having the Altimate integration in place from the start makes sense. #### What benefits does registering an API key provide? A direct line of communication with our users is established with the authentication in place. This is essential for efficiently communicating hotfixes, new releases, and deprecation warnings. It helps to minimize operational challenges and ensures that users are not left with outdated versions or unaware of updates due to the limitations of VSCode or lack of IDE restarts. Our main goal is to prevent any disruption in your development environment and to support our users proactively. #### What if I don't want to use preview features or accidentally send data to Altimate? We understand the concern about using preview features and the risk of accidental data transmission. To address this, we have implemented stringent data security practices, which you can review in our [security FAQ](/dbt-power-user/arch/faq/). Our solutions have passed security reviews by several large organizations in the US, and we are open to undergoing similar reviews for your organization. Additionally, we are working on making some preview features available offline through our [open-source Python CLI package](https://github.com/AltimateAI/datapilot-cli). #### How are you addressing concerns about data transmission in preview features? To directly address concerns about data transmission, we have added a "local-mode-only" setting in VSCode. If enabled, this setting prevents backend calls for any feature except authentication. This setting can be reviewed by your security team since our [client code](https://github.com/AltimateAI/vscode-dbt-power-user/blob/master/src/altimate.ts) is open-source. Add the following setting in vscode settings.json ```json { dbt.isLocalMode: True } ``` Only use the following steps for "dbt Fusion" environments. If you have a dbt Core environment, use the [required config instructions for "dbt Core" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfig/index.md). If you have a dbt Cloud environment, use the [required config instructions for "dbt Cloud" environments](https://help.altimate.ai/dbt-power-user/setup/reqdConfigCloud/index.md). dbt Fusion integration provides enhanced performance and features ## What is dbt Fusion? dbt Fusion is a command-line interface that provides enhanced dbt functionality with improved performance and additional features. Unlike standard dbt Core, dbt Fusion is a standalone executable that doesn't require a Python environment, making it easier to install and manage. ### Key Benefits of dbt Fusion Integration: - **Standalone Installation**: No Python environment required - **Enhanced Performance**: Optimized execution compared to standard dbt - **Cross-Platform Support**: Available for macOS, Linux, and Windows - **Simple Setup**: Single executable installation - **Full VSCode Integration**: Complete feature support in the extension ## Use the setup wizard for configuration (recommended) Need to setup environment variables? Refer to this [section](/dbt-power-user/setup/optConfig/#environment-variables-setup) This method will save a bunch of time for you, and you can also validate your configuration. The setup wizard will help you in associating SQL files with jinja-sql, installing dbt Fusion if needed, and validating your project configuration. You can start the setup wizard by clicking on the dbt status icon in the bottom status bar, and perform the following necessary steps: **Here are the steps covered in the setup wizard** **Select dbt Integration Type** In the setup wizard, choose "dbt Fusion" as your integration type. This will configure the extension to use the dbt Fusion CLI for all dbt operations. **Install dbt Fusion** If dbt Fusion is not installed in your system (the dbt status icon on the bottom status bar will show it), click on "Install dbt Fusion" button. The setup wizard will automatically install the latest version of dbt Fusion using the appropriate method for your operating system: - **macOS/Linux**: Uses curl to download and install from dbt Labs CDN - **Windows**: Uses PowerShell to download and install from dbt Labs CDN **Associate SQL Files** The wizard will help you associate `*.sql` files with `jinja-sql` language mode for proper syntax highlighting and IntelliSense support. **Validate Project** The last step is clicking the "Validate Project" button. It will run a bunch of checks to make sure your dbt Fusion environment and project are set up correctly. If there are issues, it will tell you exactly what's wrong. If you still can't get the extension setup correctly, please contact us via slack or chat through [support page](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) ## Manual method of configuration Please follow the manual method only if you couldn't use the setup wizard above. ### Step 1: Install dbt Fusion #### Automatic Installation via Extension 1. Open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) 1. Type "Power User for dbt: Install dbt" 1. Select the command and choose "dbt Fusion" when prompted 1. The extension will automatically download and install dbt Fusion for your platform #### Manual Installation **macOS and Linux:** ```bash curl -fsSL https://public.cdn.getdbt.com/fs/install/install.sh | sh -s -- --update ``` **Windows (PowerShell):** ```powershell irm https://public.cdn.getdbt.com/fs/install/install.ps1 | iex ``` #### Verify Installation After installation, verify that dbt Fusion is properly installed by running: ```bash dbt --version ``` You should see output that includes "dbt-fusion" in the version information. ### Step 2: Configure dbt Integration Type Set the integration type to fusion in your VSCode settings: #### Method 1: Via VSCode Settings UI 1. Open VSCode Settings (`Ctrl+,` / `Cmd+,`) 1. Search for "dbt integration" 1. Set "Dbt: Dbt Integration" to "fusion" #### Method 2: Via settings.json Add the following to your VSCode settings.json: ```json { "dbt.dbtIntegration": "fusion" } ``` ### Step 3: Associate \*.sql files with jinja-sql #### Method 1: Configure in Preferences > Settings #### Method 2: Update settings.json directly ```json { "files.associations": { "*.sql": "jinja-sql", "*.yml": "jinja-yaml" } } ``` ### Step 4: Verify Configuration After configuration, check that: 1. The bottom status bar shows "dbt fusion" with a checkmark 1. You can execute dbt commands through the extension 1. IntelliSense and syntax highlighting work in your dbt files ## Enable SaaS features by adding API key There are multiple features in the extension, including [generate dbt documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md), [column lineage](https://help.altimate.ai/dbt-power-user/test/lineage/index.md), [query explanation](https://help.altimate.ai/dbt-power-user/develop/explanation/index.md), [generate dbt model from SQL](https://help.altimate.ai/dbt-power-user/develop/genmodelSQL/index.md) that require an API key. You can get an API key for free by signing up at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You need to add the API key from "Settings->API key" in your Altimate instance to the VSCode extension settings. You also need to add "Instance name" in the extension settings. Please get your instance name from your Altimate AI URL. If your URL for Altimate instance is - "companyx.app.myaltimate.com", then instance name is "companyx". Go to VSCode extension settings, and add API key and instance name there. Here's demo of how to add instance name and API Key to the extension settings ## Feature Support dbt Fusion integration supports most extension features with some exceptions: ### ✅ Supported Features - **Query Execution**: Execute models and preview results - **SQL Compilation**: View compiled SQL code - **Auto-completion**: IntelliSense for models, macros, and sources - **Column Lineage**: Trace data lineage between models - **SQL Validation**: Validate SQL without execution - **Defer to Production**: Run models without rebuilding dependencies - **Test Generation**: AI-powered test generation - **Query Explanation**: AI-powered SQL explanation ### ❌ Limited Features - **Documentation Generation**: Not supported in dbt Fusion CLI - **Some Advanced Features**: May have limitations compared to dbt Core integration ## Questions and Answers #### What is dbt Fusion and how is it different from dbt Core? dbt Fusion is an enhanced command-line interface for dbt that provides improved performance and additional features. Unlike dbt Core, which requires a Python environment, dbt Fusion is a standalone executable that can be installed independently. #### Is dbt Fusion integration free? Yes, dbt Fusion integration is free and treated the same as integration with dbt Core. It will not count towards the usage quota for AI features. #### Do I need Python installed to use dbt Fusion? No, dbt Fusion is a standalone executable that doesn't require a Python environment. This makes it easier to install and manage compared to dbt Core. #### Can I switch between dbt Core and dbt Fusion integrations? Yes, you can switch between integration types by changing the `dbt.dbtIntegration` setting in VSCode. The extension will automatically detect and use the appropriate dbt executable. #### What if dbt Fusion is not available for my platform? dbt Fusion supports macOS, Linux, and Windows. If you encounter installation issues, you can fall back to using dbt Core or dbt Cloud integrations instead. #### Why do I need to add the Altimate API key? The API key is necessary for advanced AI-powered features like query explanation, test generation, and column lineage. Basic dbt operations (execution, compilation) work without an API key. If you would like to use SSO for authentication, please follow the instructions below. We support OIDC (OpenID Connect) today, and SAML is not yet supported. We will explain the process for Okta as authentication provider below, but similar steps can be used for other authentication providers as well. ## OKTA SSO Setup ## Step 1: Create a web app Choose authentication method as "OIDC" and type of application as "web application". Add additional config for - **Sign-in redirect URI**: https://"instance-url"/login/callback/okta\ **Sign-out redirect URI**: https://"instance-url"/login Your instance-url may be either "instance-name".app.getaltimate.com or "instance-name".app.myaltimate.com If you don't know the instance-name in above URIs, please contact the support team Also, in "Assignments" section, please choose "skip group assignments" for now. Finally, save the config to create the Okta app. ## Step 2: Share config info with our support team Share Client-ID, Client-Secret, OIDC provider (Okta) URL (e.g.https://trial-1627894-admin.okta.com/admin/app/) with the support team. ## Step 3: Start using Altimate AI instance with SSO Once our support team has done necessary config based on the info provided by you in the earlier step, we will notify you. You can also create a bookmark app in Okta by following these [instructions from Okta documentation](https://support.okta.com/help/s/article/create-a-bookmark-app?language=en_US) Please use URL as https://.getaltimate.com/login-redirect/okta or https://.myaltimate.com/login-redirect/okta based on instructions shared by our support team. After this point, you can start using your Altimate AI instance with SSO and start onboarding users! You need to have an enterprise plan for the SSO integration. ## Azure AD SSO Setup ## Step 1: Create Azure AD App Go to Azure [home](https://portal.azure.com/#home) and search “Active Directory” in search bar, and select active directory Click + Add and select App registration. Enter a valid application name and in “Redirect URI” section, select “Web” and enter url “https:///login/callback/active-directory” (replacing “instance url” with your instance url) Your instance-url may be either "instance-name".app.getaltimate.com or "instance-name".app.myaltimate.com If you don't know the instance-name in above URIs, please contact the support team After registration, in overview section of the application, copy and save “Application (client) ID”. Then, Click “Add a certificate or secret” click “New client secret”. Enter description and select expiration according to your preferences. Make sure to contact us to update the secrets if it is expired. Copy and save the secret value - Click “Default Directory | App registrations” link in the top left breadcrumb - Click “Endpoints” - Copy and save “OpenID Connect metadata document” url ## Step 2: Share config info with our support team From instructions in 'Step1' above, copy following information and share it with our support team ```text Application (client) ID client secret OpenID Connect metadata document url ``` ## Step 3: Start assigning users / groups to app Once our support team has done necessary config based on the info provided by you in the earlier step, we will notify you. After this point, you can start with additional steps necessary as below: ### Update the app to require user assignment 1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). 1. If you have access to multiple tenants, use the Directories + subscriptions filter in the top menu to switch to the tenant containing the app registration from the Directories + subscriptions menu. 1. Browse to Identity > Applications > Enterprise applications, then select All applications. 1. Select the application you created earlier. Use the filters at the top of the window to search for a specific application. 1. On the application's Overview page, under Manage, select Properties. 1. Locate the setting Assignment required? and set it to Yes. 1. Select Save on the top bar. ### Assign the app to users and groups to restrict access Once you've configured your app to enable user assignment, you can go ahead and assign the app to users and groups. 1. Under Manage, select the Users and groups then select Add user/group. 1. Under Users, select None Selected, and the Users selector pane opens, where you can select multiple users and groups. 1. Once you're done adding the users and groups, select Select. 1. (Optional) If you have defined app roles in your application, you can use the Select role option to assign the app role to the selected users and groups. 1. Select Assign to complete the assignments of the app to the users and groups. 1. On return to the Users and groups page, the newly added users and groups appear in the updated list. If needed, please check Microsoft Entra documentation [here](https://learn.microsoft.com/en-us/entra/identity-platform/howto-restrict-your-app-to-a-set-of-users) ## Azure AD Troubleshooting If you encounter email related error during login with active directory like below, ask your Azure Active directory admin to add a valid email to the user as explained in next steps Solution: In Azure, go to “Users” by searching in top search input. Select the user who has email issue and go to “Properties” and click edit button near “Contact Information”. Enter a valid email in “Email” field and save. User should be able to login now # Altimate Code in IDE ## What is Altimate Code? [Altimate Code](/code/) is the open-source data engineering harness with 100+ deterministic tools for building, validating, optimizing, and shipping data products. It brings AI-powered data engineering directly into your IDE through the Datamates extension, or can be used standalone via CLI and TUI. ## Getting Started in Your IDE ### Install the Datamates Extension - **VS Code** — [Microsoft Marketplace](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) - **Cursor / other VS Code-compatible editors** — [Open VSX Registry](https://open-vsx.org/extension/altimateai/vscode-altimate-mcp-server) ### Open Altimate Code Chat 1. Press `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux) to open the command palette 1. Type `Altimate MCP` 1. Select **Altimate MCP: Open Altimate Code Chat** This opens the Altimate Code chat panel where you can interact with agents and run data engineering tools. ## Features ### Agent Modes Altimate Code provides three agent modes to match your workflow: | Mode | Access Level | Use Case | | ----------- | --------------- | ------------------------------------------------------------------- | | **Builder** | Full read/write | Scaffolding dbt projects, writing models, generating tests and docs | | **Analyst** | Read-only | Exploring schemas, running queries, analyzing lineage | | **Plan** | Minimal access | Planning changes, reviewing impact before execution | ### 100+ Data Engineering Tools - **SQL Tools** — Validation without execution, query optimization, anti-pattern detection, dialect translation, PII scanning - **dbt Tools** — Model generation, test generation, documentation generation, project scaffolding, troubleshooting - **Lineage Tools** — Column-level lineage, impact analysis, downstream dependency tracking - **Schema Tools** — Schema exploration, table/column discovery, metadata indexing - **FinOps Tools** — Cost analysis, warehouse spend reports, optimization recommendations - **Warehouse Tools** — Direct query execution, result preview, connection management ## Benchmarks Altimate Code is **#1 on ADE-Bench** — the industry benchmark for AI data engineering agents, created by Benn Stancil (founder of Mode) in collaboration with dbt Labs. It evaluates agents on real-world analytics and data engineering tasks using actual dbt projects and databases. **The harness — not the model — is the differentiator.** Despite using Sonnet 4.6 (not the most expensive model), Altimate Code outperforms agents running on more capable models, demonstrating that purpose-built tooling and deterministic operations outperform raw model capability alone. ### ADE-Bench (DuckDB Local) | Tool | Model | Score | Pass Rate | | ---------------------- | ---------- | --------- | --------- | | **Altimate Code** | Sonnet 4.6 | **32/43** | **74.4%** | | Cortex Code CLI | Opus 4.6 | 28/43 | 65% | | dbt Labs | Sonnet 4.5 | ~25/43 | 59% | | Claude Code (baseline) | Sonnet 4.6 | ~17/43 | 40% | ### Other Benchmarks | Benchmark | Result | | ---------------------------------------- | ---------------------------------------------------------------------------- | | **SQL Anti-Pattern Detection** | 100% accuracy across 1,077 queries, 19 categories. Zero false positives. | | **Column-Level Lineage** | 100% edge match across 500 queries with complex joins, CTEs, and subqueries. | | **Snowflake Query Optimization (TPC-H)** | 16.8% average execution speedup (3.6x vs baseline). | [Full benchmark details →](https://www.altimate.sh/benchmarks) ## LLM Access Two options for powering the AI chat: - **BYOK (Bring Your Own Key)** — Free and unlimited. Use any of 35+ supported providers (Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, Ollama, and more) - **[Altimate LLM Gateway](https://help.altimate.ai/dbt-power-user/arch/llm-gateway/index.md)** — Managed LLM access with dynamic routing across Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, and more. 10M tokens free to get started — no API keys to manage ## Standalone Usage Altimate Code can also be used outside the IDE: | Interface | Description | | ----------------- | ---------------------------------------------- | | **TUI** | Interactive terminal UI — `altimate` | | **CLI** | Command-line for scripting — `altimate run` | | **Web UI** | Browser-based interface — `altimate web` | | **CI/CD** | Headless mode for pipelines — `altimate check` | | **GitHub/GitLab** | Automated PR review and issue triage | Install standalone: ```bash npm install -g altimate-code ``` ## Full Documentation - **Altimate Code docs** — [Altimate Code section](/code/) - **Altimate MCP docs** — [Altimate MCP section](/datamates/) You can coach and personalize your AI teammates by giving instructions in the natural language. First, enable AI teammates functionality by going in settings -> teammates menu. Unless you enable teammates in the SaaS instance, coaching and personalization outlined below won't work. ## Documentation Writer Documentation writer AI teammate is available via the documentation editor panel in the Power User VSCode extension. Here are more details on how to [generate documentation](https://help.altimate.ai/dbt-power-user/document/generatedoc/index.md) ### Trigger coaching If you want to coach your documentation writer, after the documentation is generated, click on "do you want to coach AI" icon as shown below: ### Provide instructions You can provide instructions in the natural language first and then the AI teammate will show you what it has understood. You can edit that understanding further as shown below: ### Curate and update learnings All the learnings done by AI teammates can be curated further by you in the settings -> teammates are in the SaaS UI. You can edit the earlier learnings, enable / disable them or you can simply delete them as well. ## What are AI Teammates? As AI is evolving, now we can create virtual AI teammates where some pieces of work can be done autonomously by them. You can coach these virtual teammates just like new members of your team, so the work they deliver is perfectly tailored for your organizations requirements. ## What work AI Teammates can Do? In certain scenarios, they can assist you vs. doing work completely autonomously and you can personalize these assistants as per your requirements. Today, work done by data teams can be divided in three simple buckets - 1. Done by humans 2. Done by humans and AI together 3. Done by AI autnomously ## How AI Teammates Work with Us? AI teammates are integrated in day to day work of data teams through Power User VSCode extension, Python package, and SaaS UI. Power User extension already has comprehensive AI functionality ranging from dbt model,test,docs generation to SQL query translation & explanation. For more info, please check [our website](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You can run ad hoc SQL queries or dbt Models in the "Query Results" tab ## Click on the "New Query" Button The "New Query" button is available in the "Query Results" bottom panel. ## Enter a Query Enter the SQL or dbt query that you want to run ## Run the Query Click on play button to run the query and see the results in the bottom panel For dbt models running in Big Query, you can get the estimate of the data processed for that model right inside VSCode as below: Note This feature is supported for dbt version 1.6 and above. Defer functionality in dbt allows the user to run a subset of models or tests without having to first build their upstream parents. Usually, it leads to significant cost and time savings during testing of the dbt models. More information about this functionality is available in [dbt docs](https://docs.getdbt.com/blog/defer-to-prod). ### Step 1: Enable Defer to production functionality in the "Actions" panel as below ### Step 2: Choose where your manifest file is stored for the production environment You can either use this functionality in the local mode where your manifest files stay in your local computer. You can also use the SaaS instance to store your manifest files so multiple team members can benefit from prod or staging data. ## Local Mode Choose the location of your local manifest file as shown in the image below: ## SaaS Mode To use the Altimate SaaS instance, you will need to install the `altimate-datapilot` python package. You can install it using the following command: `pip install altimate-datapilot`. This package is required to upload the manifest file to the SaaS instance. You can find more information about the package [here](https://github.com/AltimateAI/datapilot). First, create the dbt integration in the Altimate AI SaaS instance by going to Settings -> Integrations from left side navigation menu. This is just to create a reference where you can upload respective manifest files to point to. If you would like to connect your on-premise storage for manifest file uploads, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. Then, copy the command (last column in above image) from the UI to upload manifest files mapped to this integration. The command will look something like this - "datapilot dbt onboard --token --instance-name --dbt_core_integration_id --manifest-path 'Path/to/file'" (You need to replace 'Path/to/file' with the path to your manifest file e.g. /Users/mrx/documents/repos/jaffle_shop/target/manifest.json) You can use this command to run at regular intervals in your CI/CD or orchestration tool so the latest manifest is always available for reference automatically in other environments Now, choose the right dbt integration to reference in your VSCode as below: ### Step 3: Enable/disable favor state Turn on favor-state if you need it. If it's turned on, the defer functionality will favor using the node defined in the referenced integration, even if the node exists in the current project. ## Recorded demo video ## Interactive demo Using defer to prod with SaaS instance requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) Local mode doesn't require an API key. Lineage is available as model level lineage and column level lineage. You need to add an API key to view column level lineage. You can view model level lineage without an API key. ## Model lineage - Different dbt entities like sources, seeds, models, tests, metrics, exposures, and model types are shown in the lineage view. - For applicable components, Clicking on "Details" shows a list of columns with descriptions as well as dbt tests that are written for that particular component. ## Expand and collapse lineage graph You can adjust the lineage scope without re-opening it: - **Expand** at a single level by clicking the (+) handle on individual blocks, or expand multiple levels at once with the **Depth** popover. - **Collapse** at a single level by clicking the (−) handle on individual blocks, or use the **Depth** popover to decrease the parent / children depth. Collapse is **root-preserving** — the open-file node is never dropped, and any orphaned siblings are pruned automatically. ## Column lineage - After clicking on "Details" for the component, you can see a list of columns. Then, you can click on a column name to change model lineage to column lineage view. - In the column lineage view, links between components are shown as select links and non-select links. Select links are shown as solid lines if there is a direct flow of data between columns through select statements. Non-Select links are shown as dotted lines if columns appear in the condition/clause like where, join, having, etc. Check the Settings tab if you want to disable certain types of links or set specific expansion levels by default. ## Code transformations - On each individual component, you can see small icons that show how that column was created (through transformation, just name change or passed unchanged). If code is available for a particular transformation, a small code icon is displayed. - When you click on the code icon, it shows the list of code transformations that were performed to create that column. Column lineage with code transformation is also available in SaaS UI. Please refer to the section on [SaaS Discovery UI](https://help.altimate.ai/dbt-power-user/discover/viewlineage/index.md) Following are a few limitations in the column level lineage - Snapshots are not supported (coming soon) - Operators that may result in an incomplete lineage - Unnest - Lateral View Flatten - Json flatten to columns ## Export lineage You can export lineage view to a web page. Please check more details [here](https://help.altimate.ai/dbt-power-user/govern/collaboration/#lineage-export-workflow) ## Interactive demo - column lineage ## Recorded demo - column lineage Column lineage requires an API key. You can get it by signing up for free at [www.altimate.ai](https://www.altimate.ai?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) You can preview the resulting data and SQL query from your code with the extension, export it as CSV and do further analysis. You can also use [Altimate Code](https://help.altimate.ai/dbt-power-user/teammates/altimate-code/index.md) to explain your SQL or to profile a query for performance. ## Preview results, export and analyze You can preview results for the entire dbt model or select part of the dbt model to preview results only for that selection. After you select, Press Cmd+Enter (Mac) or Control+Enter (Windows/Linux) to run a query. You can also preview query results via "execute dbt SQL" operation from the toolbar on the top right corner. You have to click on the "play" button as shown in the image below. You can view and copy the SQL query that was executed to get the data results. In order to view executed SQL query, you need to click on SQL tab inside "Query Results" bottom panel. There is a copy SQL button also, it becomes visible only when you hover over the top right corner. ## Configure settings for query preview There are multiple actions available as actions on the top of query results preview window. Please click “configure” button to make it visible. | Action | Details | | ----------- | ---------------------------------------------------------------------------------------------------- | | Dark Mode | You can change configuration of preview results display to light, dark, solarized etc. display modes | | Scroll Mode | Free scroll or aligned scroll | | Read only | Read only or editable mode (Note: editable mode doesn’t save values in the database) | | Reset | Reset button to reset the view | | Export | You can export the data in CSV format | | Copy | You can copy the data shown in the preview. There are multiple options like CSV and JSON format | Query preview is limited to 500 rows by default, this can be configured in Settings area or you can configure query results options in "Help" tab in the bottom panel as below. You can also change table zoom level with 'scale' setting so you can see more columns in a single view or you can clear results by clicking “clear results” button. ## Explain with Altimate Code Open the "SQL" tab inside the "Query Results" bottom panel and click the "Explain with Altimate Code" button shown above the SQL. [Altimate Code](https://help.altimate.ai/dbt-power-user/teammates/altimate-code/index.md) opens in a chat and explains the code from the file you have open in the editor, or the part you have selected. ## Profile this query Once a query returns results, a "Profile this query" button appears in the "Query Results" toolbar. Click it to start an [Altimate Code](https://help.altimate.ai/dbt-power-user/teammates/altimate-code/index.md) session that reviews your query for performance bottlenecks, data distribution issues and optimization opportunities. ## Compare Query Results You can save query results by opening in a tab. Then, make changes to a query and run query results. Now, you can compare previous results with new results easily as below: ## Run an ad-hoc query You can run ad hoc SQL queries or dbt Models in the "Query Results" tab # Preview CTEs (Common Table Expressions) Power User for dbt allows you to preview individual CTEs (Common Table Expressions) within your dbt models, making it easier to debug and understand complex queries by examining each component separately. ## What are CTEs? Common Table Expressions (CTEs) are temporary named result sets that exist within the execution scope of a single SQL statement. They help break down complex queries into more manageable, readable pieces. In dbt, CTEs are often used to organize complex transformations into logical steps. ## Preview Individual CTEs ### Using the CTE Preview Feature You can preview the results of individual CTEs within your dbt model: 1. **Open your dbt model** in the editor 1. **Locate the CTE** you want to preview 1. **Click on Execute CTE** right above the CTE There are two methods to run dbt model tests. You can either do it from the top right corner toolbar or from the extension side panel. ### Method 1: Run tests from the toolbar The toolbar action to run tests is present on the top right corner of the VSCode, as shown in the image below: ### Method 2: Run tests from the side panel On the left side of the navigation, click on the Power User for dbt extension icon to open the left-side panel, as shown in the image below. Then, click on the "Test dbt Model" button (hover over the area shown by the red circle to make it visible) to execute dbt model tests. Identify SQL issues like non-existent columns, keyword typos, extra parentheses easily Following SQL checks are available: | Check | Details | | ---------------------------- | ----------------------------------------------------------------------------------------------- | | Identify non-existent column | If SQL is referencing some columns that don't exist, those columns will be identified as error. | | Keyword typos | If there are some typos in SQL keywords, those keywords will be flagged | | Missing or extra parentheses | If there are missed or extra parentheses, that SQL area will be highlighted | ## Errors and quick fix Every error popup raised by Validate SQL includes a **Fix with Altimate Code** button. Clicking it opens the Altimate Code chat with the model name and raw SQL pre-filled, so you can ask for a fix without restating the problem. In addition to the SQL checks above, the four pre-execution paths that previously failed silently now each show a descriptive error popup with its own Fix button: | Path | What you'll see | | -------------------------------------------- | ------------------------------------------- | | dbt manifest not loaded | *dbt manifest not loaded. Run `dbt parse`…* | | Model not present in manifest | *Model `X` not found in manifest…* | | Parent graph entry missing | *Could not find model graph entry…* | | SQL compilation failed (broken `ref()` etc.) | *Unable to compile SQL for model `X`…* | After Validate SQL writes diagnostics to the Problems panel, an error notification with a **Fix this SQL** button also appears. The prompt sent to Altimate Code contains the compiled SQL plus the validation errors. See also: Problems panel quick fix The Validate SQL errors that land in the Problems panel also get the **Fix with Altimate Code** quick-fix light-bulb and inline link covered in [Troubleshooting → Fix with Altimate Code (any error row)](https://help.altimate.ai/dbt-power-user/troubleshooting/#fix-with-altimate-code-any-error-row). # SQL Visualizer (Beta) The new SQL visualizer translates complex SQL queries into intuitive graphical representations. SQL visualizer functionality shows the SQL structure of your code and how different components of the code are connected. The provided SQL query is visually broken down into nodes representing CTEs, joins, filters, and unions, making it easier to understand, refactor, and debug the query components. ### Key Benefits - Enhanced Comprehension: Quickly grasp SQL structure and flow through visual elements. - Improved Productivity: Drag-and-drop functionality for faster query modification. - Better Collaboration: Visual diagrams are effective documentation and are easier to share. - Easier Refactoring: Simplify query restructuring with the visual graph of all components. - Simplified Debugging: Identify and correct errors quickly by visually tracing query logic. This functionality is still in beta. The functionality may change further to streamline the experience ## Trigger the functionality ### Actions Toolbar Click on "SQL Actions" icon as shown in the image below and choose "Visualize SQL" option from the drop down as below: ## View the SQL components flow Please use the bottom left corner buttons to zoom in / zoom out, etc. ## Hover over connections to view the code You can hover over connections like join, group, union to see the code. You can also click on "View Details" within the component to see the list of columns and descriptions. ## Same view is available in the SaaS Discovery UI SQL visualizer is also available in the SaaS Discovery UI where you can also see column lineage, dbt Model documentation and compiled code. Please check more details on how to set up SaaS Discovery UI [here](https://help.altimate.ai/dbt-power-user/discover/setupui/index.md) ## Recorded Demo ## dbt logs viewer (force tailing) You can generate, view, edit and delete dbt tests in VS Code under the Documentation Editor section. Following are a few limitations - The [alternative method for defining tests](https://docs.getdbt.com/reference/resource-properties/data-tests#alternative-format-for-defining-tests) is not supported yet - the definition of tests defined as macro is not available yet ## View dbt Tests The documentation editor shows the tests that have been added for the dbt model and columns. You can see the details of the tests by clicking on the test name. ## Add dbt Tests You can add default dbt tests: unique, not_null, accepted_values, relationship by clicking (+) sign next to the "Tests:" label. ## Generate dbt Tests You can also generate test code for custom tests based on `dbt_utils` and `dbt_expectations` packages. In the Documentation Editor, click the **(+)** sign next to the **Tests:** label and choose **custom tests**. Altimate Code opens in a side panel, asks any clarifying questions it needs, and writes the test (using `dbt_utils` / `dbt_expectations` if installed, or a custom macro otherwise). Requires the Datamates extension Custom test generation runs through Altimate Code, which is powered by the **[Datamates](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server)** extension. Make sure Datamates is installed and active before invoking custom test generation. Altimate Code may occasionally retry dbt commands before producing a successful test, and in rare cases may ignore installed packages or generate inaccurate code. Review the generated test before saving. ## Edit/delete dbt Tests You can edit existing dbt tests if they are default dbt tests: unique, not_null, accepted_values, relationships by clicking on the test and using the "pencil" icon from the details screen. You can delete any dbt test by clicking on the test and using the "trash can icon" from the details screen ### Getting distinct values for "accepted_values" test As shown in the image above, there is a button to quickly get distinct values for a specific column with a click of a button. This helps you write the "accepted_values" test easily. Save changes in YAML file You can save the changes in the existing or a new YAML file with save button at the bottom of the panel. If you see any issues with the content that's saved in the YAML file, please check the [optional config section](https://help.altimate.ai/dbt-power-user/setup/optConfig/#column-name-setup-for-yaml-file-updates). # Altimate MCP # Blog Our blog has moved to [https://altimate.ai/blog](https://altimate.ai/blog?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). You will be redirected to our blog page in a few seconds. ## Click-through Demo In this example we pull context from your dbt best practices stored in Knowledge Hub, pull requirements from a JIRA ticket, and update dbt models all within Cursor. ## Walkthrough This example demonstrates how our Altimate MCP can be used to build, test, and deploy dbt (data build tool) models, streamlining analytics engineering workflows. - Altimate MCP retrieve ticket details from Jira. - They understand the dbt project structure and existing models/schema. - An initial comment is added to the Jira ticket to signify the start of work. - The process includes adding documentation and tests to new dbt models, referencing organizational best practices. - The system helps in building the new model, documenting it, and testing the changes. Knowledge Hub: Our Knowledge Hub centralizes an organization's best practices and tribal knowledge, providing verified context for IDEs. This allows AI workflows to move beyond generic code generation. The dbt Best Practices document from the Knowledge Hub is used as a reference for agents. Integration Tools: Our Altimate MCP integrates with dbt, Jira, and Cursor to execute the correct tools needed to refactor the dbt model. This example illustrates a process where Altimate MCP automates the creation of a new dbt mart layer based on requirements from a Jira ticket (e.g., Jira ticket AI-2984). ## Click-through Demo See how Altimate MCP uses AI to quickly debug Airflow DAGs. By combining platform integrations and best-practice templates from the Knowledge Hub, Altimate MCP identifies issues, suggests fixes, and applies improvements automatically. Shared memories across Altimate MCP boost context and consistency for faster, smarter troubleshooting. ## Walkthrough The above demo goes over the following steps to improve the debugging process. By creating an Altimate MCP - engineers can work in their IDE without content switching or pouring over airflow log files. **Creating an Altimate MCP:** The presentation begins by showing how to create an Altimate MCP with the necessary integrations. The example uses an "Airflow tester" Altimate MCP configured with Memory, Airflow, GitHub, Databricks, and Jira integrations. **Adding Context from Knowledge Hub:** Altimate's Knowledge Hub is introduced as a way to provide context to agents. It offers templates that users can fork and modify to fit their company's best practices. The "Airflow Cookbook" from the Knowledge Hub is used in this example to help debug Airflow DAGs. The URL of the knowledge document can be copied and provided to the coding assistant for context. **Debugging an Airflow DAG:** A problematic Airflow DAG named asset1_producer is shown to have failed runs, indicated by red "X failed" statuses. The bug is identified as a ZeroDivisionError due to error_count being 0 in a success rate calculation. **AI-Assisted Triage and Fixes:** The user prompts the coding assistant with the problem and provides the link to the "Airflow Cookbook" from the Knowledge Hub. The Altimate MCP, utilizing its built-in memory and the provided context, identifies the ZeroDivisionError and suggests fixes based on the best practices outlined in the cookbook, such as proper error handling, input validation, numerical operations, structured logging, and exception handling. The agent then applies the recommended code changes. **Successful DAG Run and Memory Hub:** After applying the fixes, the DAG runs successfully. Finally, the presentation highlights the Memory Hub, which stores a list of memories shared across Altimate MCP, leading to enhanced contextual understanding, increased efficiency, and reduced repetition. # Examples Welcome to our Examples Gallery! Using Altimate MCP you can automate data engineering, analytical engineering, data infrastructure and governance workflows ## Getting Started We recommend starting with the **[Setup Guide](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md)** for a step-by-step tutorial to setup Altimate MCP before diving into these examples. ## Example Use Cases | Example | Description | | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Build, Test, Docs for dbt Models](https://help.altimate.ai/datamates/examples/build-test-document-dbt-model/index.md) | Pull context from your dbt best practices stored in Knowledge Hub, pull requirements from a JIRA ticket, and update dbt models all within Cursor | | [Find Broken Views in Snowflake](https://help.altimate.ai/datamates/examples/find-broken-views-snowflake/index.md) | Create an Altimate MCP called "Sprint Work Agent" that integrates Snowflake, dbt, and Jira into GitHub Copilot to find empty Snowflake views and file tickets | | [Optimize Cost and Performance](https://help.altimate.ai/datamates/examples/optimize-costs-and-performance/index.md) | Automate the discovery and implementation of cost and performance optimization opportunities across Snowflake, Databricks and BigQuery | | [Migrate a pyspark project to dbt](https://help.altimate.ai/datamates/examples/migrate-pyspark-dbt/index.md) | Walkthrough of migrating a PySpark-based e-commerce reporting project in Databricks to dbt with automated conversion assistance | | [Debug an Airflow DAG](https://help.altimate.ai/datamates/examples/debug-airflow-dag/index.md) | Use AI to quickly debug Airflow DAGs by combining platform integrations and best-practice templates from the Knowledge Hub | | [Write Snowflake UDFs](https://help.altimate.ai/datamates/examples/write-snowflake-udfs/index.md) | Use the knowledge hub to create a guide for LLMs to create Snowflake UDFs with best practices and coding examples | ## Click-through Demo In this example we create an Altimate MCP called "Sprint Work Agent" that integrates Snowflake, dbt, and Jira into GitHub Copilot to find empty Snowflake views, their dbt models and filing a ticket to JIRA all within the VS Code IDE. ## Walkthrough The process begins by configuring Altimate MCP to integrate with these tools. Once set up, a user can prompt GitHub Copilot to perform a series of actions. In the demo, the prompt asks Copilot to: Query Snowflake tables in a specified schema (JAFFLE_CASTLE_20250521.DEV) to identify empty views in the mart layer. Find the associated dbt model if an empty view is found. Determine the root cause of the empty tables. Create a Jira ticket in the "AI" project, categorizing the issue as a "Task". GitHub Copilot then outlines its steps to address the request: - List available Snowflake connections. - Query the mart layer views. - Check for empty tables. - Review corresponding dbt models. - Create Jira tickets for any issues discovered. During this process, Altimate MCP provides GitHub Copilot with the necessary tools to connect to Snowflake and execute queries. Copilot successfully identifies that the MART_STORE_LIFETIME_VALUE view in Snowflake is empty. It then investigates the corresponding dbt model (mart_store_lifetime_value.sql) and discovers that a WHERE store_id IS NULL condition in a CTE (store_orders) is filtering out all records, noting that this was a test condition left in the code. Finally, Copilot utilizes Altimate MCP's Jira "Create Issue Tool" to file a ticket for this issue. In essence, the demonstration highlights how AI agents, powered by Altimate MCP, can automate complex data engineering tasks, from identifying issues in a data warehouse (Snowflake) and debugging code (dbt) to creating project management tickets (Jira), all within a single integrated development environment (VS Code). ## Click-through Demo This demo provides a walkthrough of migrating a PySpark-based e-commerce reporting project in Databricks to dbt. With Altimate MCP, you can investigate and plan migration scope, convert code automatically, test thoroughly, execute in phases, validate results, and maintain detailed documentation. Transform PySpark code to dbt models with Altimate MCP's conversion assistance. You can analyze PySpark repositories, and create equivalent dbt models and marts. ## Walkthrough 1. Select an Altimate MCP and context from Knowledge Hub: The demo begins on the "Altimate MCP" page within Altimate AI, where you would select an "Altimate MCP" (an AI teammate for data tasks). It then guides you to the "Knowledge hub," which is a central repository for verified context and information relevant to your projects, helping to reduce AI hallucinations and rework. 1. Utilizing the Knowledge Hub for Migration Guidance: Within the Knowledge Hub, you can find specific guides, such as "pyspark dbt migratiion which provides help with PySpark to dbt migration. The demo highlights the ability to copy a dynamic URL for your knowledge document, making it accessible to anyone with the link and usable in various IDEs. It also outlines key benefits of migrating to dbt, such as faster batch processing, increased data, and improved collaboration and data governance, and helps determine when to migrate versus when to keep PySpark. 1. Initiating the Migration Process: The user indicates they have an e-commerce reporting project in Databricks using PySpark and need to migrate it to dbt, adhering to their organization's best practices. The Altimate MCP (AI assistant) confirms its role in assisting with the migration and begins by understanding the current setup and gathering relevant information. 1. Codebase Understanding and Migration Planning: The Altimate MCP intelligently searches for relevant previous memories to reduce hallucinations or rework, demonstrating its understanding of your entire tech stack, coding styles, and architectural choices. It analyzes the existing PySpark project structure, including main application entry points, data readers, data quality validation, and transformation modules for revenue, customer, product, and time series analytics. The AI examines transformation modules to understand the business logic to be migrated and reviews the profiles.yml file to understand the data warehouse setup. The Altimate MCP then proceeds to plan and implement the migration based on the organization's best practices. 1. Review, Edit, and Testing: The process involves reviewing, editing, and accepting changes, with every interaction personalizing the Altimate MCP for you. Finally, the migration is ready to be tested. ## Click-through Demo With Altimate MCP, you can automate the discovery and implementation of cost and performance optimization opportunities.You can get context and execute actions on Snowflake, Databricks and BigQuery automatically. Discover and create improvement tasks, execute changes, measure impact, document and memorize successful patterns for future use. ## Overview Lower your Databricks expenses using Altimate MCP's cluster, job management and notebook management capabilities. You can list all clusters to identify underutilized resources, retrieve configurations to analyze sizing, and monitor job runs for optimization opportunities. Execute commands to terminate idle clusters, create right-sized configurations, and optimize job scheduling. Altimate MCP helps you examine notebook workloads, analyze job history, and implement cost-saving measures like scheduled auto-termination and right-sized cluster configurations. Detect and optimize costly queries with Altimate MCP's multi-platform SQL execution capabilities. You can run analysis queries across Snowflake, BigQuery, and Databricks to identify resource-intensive operations. Altimate MCP helps you query rewrite queries for better performance,query system tables for consumption metrics, and test optimizations. Execute comparative analyses across platforms to ensure consistent performance in your multi-cloud environment. # Automating Snowflake UDF Creation with Altimate MCP ## Click-through Demo In this example we use the [knowledge hub](https://help.altimate.ai/datamates/user-guide/components/knowledgehub/index.md) to create a guide for LLMs to create Snowflake UDFs. ## Walkthrough 1. **Overview**\ In this walkthrough, we'll see how we can use Altimate MCP to automate the creation of Snowflake User-Defined Functions (UDFs) for data validation and formatting tasks. 1. **Setting Up the Guide**\ First we'll create an artifact in the [knowledge hub](https://help.altimate.ai/datamates/user-guide/components/knowledgehub/index.md). In this example we create a piece of knowledge called "Snowflake UDFs For LLMs". This guide has best practices and coding examples of how to build Snowflake UDFs. It's written in a format to allow coding assistants to grab the context of the guide. 1. **Prompting Cursor**\ Next we prompt Cursor with "Create a set of UDFs that validate user emails and phone numbers for my user table in snowflake. Store them in the folder snowflake-udfs" We reference our Guide in the step above by adding the context as a Cursor Doc. 1. **Generated UDFs**\ The following UDFs are created with best practices in mind: | UDF Name & Signature | Description | | -------------------------------------- | -------------------------------------------------------------- | | `validate_email(email VARCHAR)` | Validates the format of an email address. | | `validate_email_domain(email VARCHAR)` | Validates the email and categorizes its domain. | | `validate_phone(phone_number VARCHAR)` | Checks the format of a phone number. | | `format_phone_number()` | Formats phone numbers according to the specified country code. | | `validate_username()` | Validates usernames based on length constraints. | | `mask_pii()` | Masks personally identifiable information. | 1. **Documentation Generation**\ As a final step, Altimate MCP automatically generates a `README.md` file summarizing all the created UDFs, providing clear documentation for future reference. By following these steps, Altimate MCP streamlines the process of building, organizing, and documenting Snowflake UDFs, making it easier for teams to implement robust data validation and formatting logic. # Altimate MCP Pricing FAQ ### **Info about pricing plans is available on the [Pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link)** ### **Are you going to charge for current free features in Altimate MCP?** No. We have no plans to convert previously available free features into paid features. Newly developed features may be released with a credit quota for the free community plan. Please check the pricing page for more details. ### **What exactly is credit for the feature?** You can find the definition of credit for different features in the table below. | Feature | Definition of credit | | ------------------------ | ------------------------------------------------------------------- | | Tool Calls | 10 tool calls across all possible tools and Altimate MCP = 1 credit | | Knowledge Base Retrieval | Each knowledge base retrieved across Altimate MCP = 1 credit | | Memory Storage | 10 memories added per Altimate MCP = 1 credit | | Memory Recall | 5 memories recalled = 1 credit | | Guardrails Applied | 100 guardrails applied across Altimate MCP = 1 credit | ### **What is considered an upgrade or downgrade of the subscription?** Upgrade or downgrade of the subscription is determined based on the price of the subscription plan. If the price of the original subscription plan is higher than the price of the newer subscription plan, it's considered a downgrade. If the price of the original subscription plan is lower than the price of the new subscription plan, it's considered an upgrade. ### **What happens during an upgrade of the subscription?** As soon as you upgrade the subscription, changes will be made to your instance for the new subscription. You will be charged the difference between a new subscription price and the prorated current subscription price based on the no. of credits remaining. ### **What happens during a downgrade of the subscription?** Your current subscription will be downgraded at the end of the current billing cycle. There is no refund when you downgrade your subscription, as the subscription is downgraded at the end of the billing cycle. ### **What happens if I change from a yearly subscription to a monthly subscription?** If the price of the monthly subscription is lower than the yearly subscription, it's considered a downgrade. So, the change in the subscription will be made only after the current billing period is over. If you would like to make an immediate change to your subscription, make the change at a yearly plan level. It will be considered an upgrade and will be effective immediately. ### **How do Altimate MCP integrations affect credit usage?** Connecting integrations to Altimate MCP (Jira, GitHub, Snowflake, dbt, Airflow, etc.) is completely free and does not consume any credits. You can connect as many integrations as needed without worrying about credit usage. Credits are only consumed when Altimate MCP actively uses these integrations through the following actions: - **Tool Calls**: When Altimate MCP calls tools from your connected integrations (10 calls = 1 credit) - **Knowledge Base Retrievals**: When Altimate MCP retrieves information from your knowledge bases (1 retrieval = 1 credit) - **Memory Operations**: When Altimate MCP stores (10 additions = 1 credit) or recalls memories (5 recalls = 1 credit) - **Guardrails**: When security guardrails are applied to protect your data (100 applications = 1 credit) This means you can have comprehensive integrations set up without any ongoing costs - you only pay when Altimate MCP actively helps you accomplish tasks. ### **What happens if I exceed my credit limit?** Altimate MCP actions are credit-based. When you exceed your monthly credit allocation, your subscription will remain active but functionality will be limited. You can either upgrade your plan for immediate access to more credits, or wait until your credits reset at the next billing cycle. ______________________________________________________________________ ## Altimate LLM Gateway Pricing ### **How does the Altimate LLM Gateway pricing work?** The [Altimate LLM Gateway](https://help.altimate.ai/datamates/user-guide/components/llm-gateway/index.md) uses **token-based pricing**. You get a monthly token allowance (input + output combined), and we dynamically route between the best models for each task. The price stays the same regardless of which model handles your request. ### **What are the LLM Gateway pricing tiers?** | Plan | Price | Tokens/mo | $/M tokens | Overage (per 1M tokens) | | -------------- | ------ | -------------- | ---------- | ----------------------- | | **Community** | $0/mo | 10M (one-time) | Free | BYOK only | | **Pro Tier 1** | $29/mo | 20M | $1.45 | $5/M tokens | | **Pro Tier 2** | $89/mo | 70M | $1.27 | $3/M tokens | | **Enterprise** | Custom | Custom | Custom | Negotiated | All tiers get access to all models (Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, GPT-5.4-mini). The upgrade incentive is volume, not capability. ### **Is BYOK (Bring Your Own Key) free?** Yes. **BYOK is always free and unlimited.** If you have your own API keys from Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, or any of 35+ supported providers, you can use them at no charge. The LLM Gateway pricing only applies when you use Altimate-managed LLMs. ### **What would the LLM Gateway cost me compared to buying tokens directly?** Buying 20M tokens directly from providers: | Model | Direct Cost (20M tokens) | With Altimate Pro Tier 1 | Savings | | ----------------------- | ------------------------ | ------------------------ | ------- | | Sonnet 4.6 | ~$84 | **$29** | ~65% | | Opus 4.6 | ~$140 | **$29** | ~79% | | GPT-5.4 (short context) | ~$75 | **$29** | ~61% | | GPT-5.4 (long context) | ~$135 | **$29** | ~79% | ### **How do LLM Gateway tokens relate to Altimate MCP credits?** LLM Gateway tokens and Altimate MCP credits are separate. Altimate MCP credits cover tool calls, knowledge base retrieval, memory, and guardrails. LLM Gateway tokens cover the AI model usage for chat and code generation. Both systems operate independently. If you can't find your question here, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via Slack. # Security FAQs ### How are credentials stored and managed? **All credentials are stored and processed locally on your machine** they never leave your work environment: - Credentials are encrypted and stored locally using your IDE's secure storage API - All connections are established directly from your machine through stdio, Streamable HTTP, or SSE. [Learn More](https://modelcontextprotocol.io/docs/concepts/transports) ### What data does Altimate MCP Server collect? We DO NOT collect any **Actual Customer Data** We collect minimal **Metadata** necessary for full functionalities: - Usage Metadata - Configuration Metadata (tool registrations, guardrail settings) - For debugging, we might ask for logs, and check other telemetry data per [VSCode guidelines](https://code.visualstudio.com/docs/getstarted/telemetry#_disable-telemetry-reporting) for error reporting and usage metrics. - Users can choose to switch on Memory at a individual Altimate MCP level. This would include a high level summary of metadata around tasks being executed in IDEs to be referenceable in future work as added context. The lifecycle of this can be controlled. ### What is your security architecture? Altimate MCP uses a local-first architecture where the MCP server runs on your machine. All data processing, credential management, and tool integrations happen locally. Our SaaS platform runs on AWS infrastructure within a private VPC, isolated from public internet. Only metadata and usage analytics are transmitted to our platform over TLS 1.3 encrypted connections. ### What compliance certifications and infrastructure security do you maintain? We maintain compliance with industry security standards: - **SOC 2 Type II**: Audited annually for security, availability, and confidentiality controls - **Enterprise Security**: Our infrastructure is hosted on AWS within a private VPC, with network isolation, security groups, and AWS IAM-based RBAC access controls. Only authorized developers can access production systems through AWS SSO with MFA enforcement for any debugging. If you need us to do a security review with your IT / security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ### Do you use my data to train your AI models? At Altimate AI, our primary objective is allow our users to automate their Data related work using Altimate MCP, locally within the confines of their system. We do not use any customer data to train any models. Any data processed by our service is not repurposed for model training or enhancement. Your data is - NOT available to other customers. NOT available to Altimate AI for any model training or improvements. NOT used to improve any 3rd party products or services ### How is the knowledge base secured? Organization-specific knowledge bases uploaded to the SaaS UI are encrypted at rest and in transit via TLS. The embedded Altimate MCP server locally hosts documents as **Private Links** which provides referenceable links that can only be authenticated through your specific IDE integration. ### How does the PII Guardrails feature work? Detected PII is automatically sanitized or blocked based on configured policies, preventing sensitive data exposure to any agentic interface like Github Copilot, Cursor, Cline, Windsurf, etc. ### What's your stance on GDPR? We do not store any actual customer data, we only store aggregate statistics and metadata. As a result, GDPR data deletion requests do not need to be propagated to us because we do not store such data. Our customers typically do not request or require DPAs. However, we're happy to provide a DPA or review a vendor DPA if your organization needs it. ### LLM & AI Security ### How does Altimate handle LLM access? Altimate gives you two options for LLM access: - **BYOK (Bring Your Own Key)** — Always free and unlimited. Use your own API keys from any of 35+ supported providers (Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, Ollama, and more). With BYOK, your data goes directly to your chosen provider — **Altimate never sees it**. - **[Altimate LLM Gateway](https://help.altimate.ai/datamates/user-guide/components/llm-gateway/index.md)** — A managed option for users who don't want to manage API keys. The gateway dynamically routes to the best model for each task. See below for its security details. ### Does the Altimate LLM Gateway store my prompts or responses? Your full prompts and responses are not retained after processing. Your data is not used to train, fine-tune, or improve any models. The gateway does store limited **metadata** for each request: - Number of prompt and completion tokens - Latency - Model used This metadata is used for billing, performance monitoring, and routing optimization. Additionally, a small number of prompts are sampled for **anonymous categorization** to power routing and model ranking. This categorization is stored completely anonymously and is never associated with your account or user ID. No code, SQL, credentials, or PII are retained. You can opt out of all telemetry by reaching out to us via the Intercom chat built into the [Altimate dashboard](https://app.myaltimate.com). ### Can I use my own API keys instead of the Altimate LLM Gateway? Yes. **BYOK (Bring Your Own Key) is always free and unlimited.** Altimate Code supports 35+ LLM providers including Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, Ollama, and many more. With BYOK, your data goes directly to your chosen provider — Altimate never sees it. This is ideal for users with existing API keys or strict data residency requirements. ### What metadata does the Altimate LLM Gateway collect? | Metadata | Purpose | | ----------------------------------------- | -------------------------- | | Number of prompt tokens | Usage tracking and billing | | Number of completion tokens | Usage tracking and billing | | Latency | Performance monitoring | | Model used | Routing optimization | | Anonymous prompt categorization (sampled) | Model ranking and routing | Prompt categorization is stored completely anonymously — never linked to your account or user ID. You can opt out via the Intercom chat in the [Altimate dashboard](https://app.myaltimate.com). ### 🔒 Key Security Promise **Your Credentials Never Leave Your Machine** - All credentials are encrypted and stored locally on your device - All connections are made from your machine - SOC 2 Type II certified with enterprise-grade security controls - Zero trust architecture with automatic PII detection and sanitization If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. # Troubleshooting This guide helps you resolve common issues with the Datamates extension. Follow the solutions below or contact our support team if you need additional assistance. ## Quick Diagnostics Before diving into specific issues, run these quick checks: ### 1. Extension Status Check ```text Command: Datamates: Run Altimate Diagnostics ``` This command provides: - Environment and extension info - Altimate API connectivity status - MCP server status and available tools - Altimate MCP and integration configuration - Extension settings with override sources ### 2. VS Code Output Panel 1. Open VS Code Output panel (`View > Output`) 1. Select "Altimate MCP" from the dropdown 1. Look for error messages or warnings ### 3. Extension Settings 1. Open Settings (`Ctrl+,` / `Cmd+,`) 1. Search for "altimate" 1. Verify configuration values ## Common Issues ### Extension Installation Problems #### Issue: Extension Not Found in Marketplace **Symptoms:** - Cannot find "Datamates" in VS Code marketplace - Search returns no results **Solutions:** 1. **Check Internet Connection** - Ensure stable internet connectivity - Verify marketplace access isn't blocked 1. **Update VS Code** 1. Ensure VS Code version 1.95.0 or higher 1. Restart VS Code after updating 1. **Clear Extension Cache** ```bash # Close VS Code first rm -rf ~/.vscode/extensions/altimateai.vscode-altimate-mcp-server* # Then reinstall from marketplace ``` 1. **Install via Command Line** ```bash code --install-extension altimateai.vscode-altimate-mcp-server ``` #### Issue: Installation Fails **Symptoms:** - Installation starts but fails to complete - Error messages during installation **Solutions:** 1. **Check Disk Space** - Ensure sufficient disk space available - Clear temporary files if needed 1. **Retry Installation** 1. Restart VS Code 1. Try installing again 1. **Install from VSIX** 1. Download VSIX file from releases page 1. Install manually: `code --install-extension altimate-mcp-server.vsix` ### Extension Activation Issues #### Issue: Extension Installed but Not Working **Symptoms:** - Extension appears in installed list but doesn't function - No commands available in Command Palette - Datapilot not available in chat **Solutions:** 1. **Restart VS Code** - Complete restart of the application - Check if extension activates on restart 1. **Check Extension Host** 1. Open Command Palette 1. Run "Developer: Restart Extension Host" 1. **Verify Prerequisites** 1. VS Code version 1.95.0+ 1. No conflicting extensions 1. **Reset Extension Settings** ```json { "altimate.onboardedMcpServer": false, "altimate.disableMcpServer": false } ``` ### MCP Server Connection Issues #### Issue: MCP Server Not Starting **Symptoms:** - Health check shows server offline - Tools not registering - Datapilot responses timeout **Solutions:** 1. **Check Server Status** ```text Command: Datamates: Run Altimate Diagnostics ``` 1. **Restart MCP Server** 1. Disable and re-enable extension 1. Or restart VS Code 1. **Check Firewall Settings** 1. Ensure VS Code can make network connections 1. Whitelist extension if necessary 1. **Network Proxy Issues** 1. Configure proxy settings if in corporate environment 1. Check proxy authentication #### Issue: Tool Registration Failures **Symptoms:** - Some tools not available - Empty tool list - Context detection not working **Solutions:** 1. **Verify Workspace Type** - Ensure project has proper configuration files - Check if workspace is supported type 1. **Check Permissions** 1. Verify file access permissions 1. Ensure configuration files are readable 1. **Check Integration Configuration** 1. Open the Datamates panel in the sidebar 1. Verify your integrations are configured for the active Altimate MCP ### Datapilot Chat Issues #### Issue: Datapilot Not Responding **Symptoms:** - @datapilot doesn't appear in chat suggestions - No response to messages - Chat participant not registered **Solutions:** 1. **Verify Chat Participant Registration** - Check if @datapilot appears when typing @ - Look for extension errors in Output panel 1. **Restart Chat Service** 1. Close all chat windows 1. Restart VS Code 1. Open new chat window 1. **Check Extension Activation** 1. Ensure extension is enabled 1. Verify no conflicting chat extensions #### Issue: Slow Response Times **Symptoms:** - Datapilot takes long time to respond - Chat interface appears frozen - Timeout errors **Solutions:** 1. **Check Network Connection** - Verify stable internet connectivity - Test with simple commands first 1. **Optimize Query Complexity** 1. Break complex requests into smaller parts 1. Avoid very large data operations 1. **Clear Chat History** 1. Start fresh conversation 1. Avoid very long conversation threads ### Database Connection Issues #### Issue: Cannot Connect to Database **Symptoms:** - Connection test failures - SQL execution errors - Authentication problems **Solutions:** 1. **Verify Credentials** - Open the Datamates panel in the sidebar and check your connection settings - Check username/password - Verify database host and port - Test connection manually 1. **Network Connectivity** 1. Ensure database is reachable 1. Check firewall rules 1. Verify VPN connection if required 1. **Driver Issues** 1. Ensure database drivers are available 1. Check compatibility with database version #### Issue: Query Execution Failures **Symptoms:** - SQL queries return errors - Permission denied errors - Timeout errors **Solutions:** 1. **Check Query Permissions** - Verify user has required database permissions - Test query directly in database client 1. **Optimize Query Performance** 1. Add appropriate indexes 1. Limit result set size 1. Break complex queries into steps 1. **Connection Pool Issues** 1. Check connection limits 1. Restart database connections ### dbt Integration Issues #### Issue: dbt Commands Not Working **Symptoms:** - dbt models not detected - Compilation errors - Profile not found **Solutions:** 1. **Verify dbt Installation** ```bash dbt --version ``` 1. **Check dbt Configuration** 1. Verify `dbt_project.yml` exists 1. Check profiles configuration 1. Ensure target environment is set 1. **Path Issues** 1. Verify dbt profiles directory 1. Check project root directory 1. Ensure proper file permissions ### Configuration Issues #### Issue: Settings Not Saving **Symptoms:** - Configuration changes don't persist - Settings reset after restart - Unable to save credentials **Solutions:** 1. **Check File Permissions** - Ensure VS Code can write to settings files - Verify user permissions 1. **Workspace vs User Settings** 1. Check if settings are workspace-specific 1. Verify correct settings scope 1. **Clear Configuration Cache** ```bash # Close VS Code first rm -rf ~/.vscode/extensions/altimateai.vscode-altimate-mcp-server*/cache ``` ### Performance Issues #### Issue: Extension Running Slowly **Symptoms:** - Slow command execution - High CPU usage - VS Code becomes unresponsive **Solutions:** 1. **Check Resource Usage** - Monitor CPU and memory usage - Close unnecessary applications 1. **Optimize Configuration** 1. Reduce number of active connections 1. Limit concurrent operations 1. **Disable Debug Mode** ```json { "altimate.debugMode": false, "altimate.verboseLogging": false } ``` ## Advanced Troubleshooting ### Extension Logs #### Collecting Detailed Logs 1. **Enable Debug Mode** ```json { "altimate.debugMode": true, "altimate.verboseLogging": true } ``` 1. **Reproduce Issue** 1. Restart VS Code 1. Perform action that causes issue 1. **Collect Logs** 1. Open Output panel 1. Select "Altimate MCP" 1. Copy relevant log entries #### Log Analysis Common log patterns to look for: ```text ERROR: Connection failed - Check database credentials WARN: Tool registration timeout - Check network connectivity INFO: MCP server started successfully DEBUG: Query executed in 250ms ``` ### Network Diagnostics #### Testing Connectivity 1. **Basic Network Test** ```bash ping api.altimate.ai ``` 1. **Port Connectivity** ```bash telnet your-database-host 5432 ``` 1. **DNS Resolution** ```bash nslookup your-database-host ``` ### Reset Extension #### Complete Reset If all else fails, perform a complete reset: 1. **Uninstall Extension** ```bash code --uninstall-extension altimateai.vscode-altimate-mcp-server ``` 1. **Clear All Data** ```bash # Clear extension cache and settings rm -rf ~/.vscode/extensions/altimateai.vscode-altimate-mcp-server* # Clear VS Code settings (optional) # Backup first if you have other important settings ``` 1. **Reinstall Extension** 1. Install from marketplace 1. Reconfigure settings 1. Test functionality ## Getting Help If you can't resolve the issue: ### Before Contacting Support 1. **Gather Information** 1. VS Code version 1. Extension version 1. Operating system 1. Error messages 1. Steps to reproduce 1. **Try Safe Mode** 1. Start VS Code with `--disable-extensions` 1. Install only Datamates 1. Test if issue persists ### Contact Options - [**Support Chat**](https://app.myaltimate.com/contactus) - [**Book a Meeting**](https://calendly.com/d/cncb-mfh-wpq/demo-request-platform-cost-savings?month=2025-07) ### Include in Support Request - **System Information** - Operating system and version - VS Code version - Extension version - **Error Details** - Complete error messages - Steps to reproduce - Screenshots if helpful - **Configuration** - Relevant settings (remove sensitive information) - Project structure - Database type and version ______________________________________________________________________ Most issues can be resolved with the solutions above. If you continue experiencing problems, don't hesitate to reach out to our support team. [← Back to Documentation](https://help.altimate.ai/datamates/index.md) # Introduction ## What is Altimate MCP? Altimate MCP is an end-to-end platform for building AI TeamMates for data teams. Altimate MCP easily integrates with your AI coding assistants using Altimate AI's [extension](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) or [package](https://www.npmjs.com/package/@altimateai/datamate). Data teams use Altimate MCP to automate and accelerate: - Refactoring data pipelines - Debugging Airflow DAGs - Migrating code between systems - Optimizing their data models and sql code ## Why Altimate MCP? Altimate MCP assists with data work ranging from building data pipelines to managing your data infrastructure. Altimate MCP [integrates with](https://help.altimate.ai/datamates/user-guide/components/integrations/integrations/index.md) your entire tool stack like Databricks, Snowflake, Airflow, dbt, Jira, Cursor, GitHub Copilot, Windsurf, Claude Code, Gemini CLI, and many others. Altimate MCP has context from your Knowledge Hubs like Confluence, Google Docs, Notions etc. Check out some examples of how to use Altimate MCP [**here**](https://help.altimate.ai/datamates/examples/examples/index.md)! ## Altimate Code Chat Altimate MCP now includes [**Altimate Code Chat**](https://help.altimate.ai/datamates/user-guide/components/altimate-code/index.md) — built on the open-source data engineering harness [Altimate Code](/code/) with 100+ deterministic tools. **#1 on [ADE-Bench](https://www.altimate.sh/benchmarks) (74.4%)** — the industry benchmark for AI data engineering agents by Benn Stancil and dbt Labs. Use AI-powered chat directly in your IDE to validate SQL, generate dbt models, analyze lineage, optimize costs, and more. **Getting started:** Press `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux), type `Altimate MCP`, and select **Altimate MCP: Open Altimate Code Chat**. ## Altimate LLM Gateway Power your AI chat with the [**Altimate LLM Gateway**](https://help.altimate.ai/datamates/user-guide/components/llm-gateway/index.md) — managed LLM access with dynamic routing across Sonnet 4.6, Opus 4.6, GPT-5.4, and more. **10M tokens free** to get started, no API keys to manage, and **60-80% cheaper** than buying tokens directly from providers. Prefer to use your own API keys? **BYOK is always free and unlimited** — use any of 35+ supported providers. ## Interactive Demo Here's a demo updating a dbt model with context from JIRA: # Altimate Code Chat ## What is Altimate Code? [Altimate Code](/code/) is the open-source data engineering harness with 100+ deterministic tools for building, validating, optimizing, and shipping data products. It is now integrated into the Datamates extension, giving you AI-powered data engineering chat directly in your IDE. ## Getting Started ### Open Altimate Code Chat 1. Press `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux) to open the command palette 1. Type `Altimate MCP` 1. Select **Altimate MCP: Open Altimate Code Chat** This opens the Altimate Code chat panel where you can interact with agents and use all 100+ data engineering tools alongside your Altimate MCP integrations. ## Features ### Agent Modes Altimate Code provides three agent modes to match your workflow: | Mode | Access Level | Use Case | | ----------- | --------------- | ------------------------------------------------------------------- | | **Builder** | Full read/write | Scaffolding dbt projects, writing models, generating tests and docs | | **Analyst** | Read-only | Exploring schemas, running queries, analyzing lineage | | **Plan** | Minimal access | Planning changes, reviewing impact before execution | ### 100+ Data Engineering Tools - **SQL Tools** — Validation without execution, query optimization, anti-pattern detection, dialect translation, PII scanning - **dbt Tools** — Model generation, test generation, documentation generation, project scaffolding, troubleshooting - **Lineage Tools** — Column-level lineage, impact analysis, downstream dependency tracking - **Schema Tools** — Schema exploration, table/column discovery, metadata indexing - **FinOps Tools** — Cost analysis, warehouse spend reports, optimization recommendations - **Warehouse Tools** — Direct query execution, result preview, connection management ### Works with Altimate MCP Integrations Altimate Code Chat has full access to your configured Altimate MCP integrations — Snowflake, BigQuery, Databricks, PostgreSQL, dbt, Airflow, Dagster, Jira, Linear, GitHub, and more. The chat agent can query your warehouse, inspect your dbt project, check your Jira tickets, and review your GitHub PRs — all from a single conversation. ## Benchmarks Altimate Code is **#1 on ADE-Bench** — the industry benchmark for AI data engineering agents, created by Benn Stancil (founder of Mode) in collaboration with dbt Labs. It evaluates agents on real-world analytics and data engineering tasks using actual dbt projects and databases. **The harness — not the model — is the differentiator.** Despite using Sonnet 4.6 (not the most expensive model), Altimate Code outperforms agents running on more capable models, demonstrating that purpose-built tooling and deterministic operations outperform raw model capability alone. ### ADE-Bench (DuckDB Local) | Tool | Model | Score | Pass Rate | | ---------------------- | ---------- | --------- | --------- | | **Altimate Code** | Sonnet 4.6 | **32/43** | **74.4%** | | Cortex Code CLI | Opus 4.6 | 28/43 | 65% | | dbt Labs | Sonnet 4.5 | ~25/43 | 59% | | Claude Code (baseline) | Sonnet 4.6 | ~17/43 | 40% | ### Other Benchmarks | Benchmark | Result | | ---------------------------------------- | ---------------------------------------------------------------------------- | | **SQL Anti-Pattern Detection** | 100% accuracy across 1,077 queries, 19 categories. Zero false positives. | | **Column-Level Lineage** | 100% edge match across 500 queries with complex joins, CTEs, and subqueries. | | **Snowflake Query Optimization (TPC-H)** | 16.8% average execution speedup (3.6x vs baseline). | [Full benchmark details →](https://www.altimate.sh/benchmarks) ## LLM Access Two options for powering the AI chat: - **BYOK (Bring Your Own Key)** — Free and unlimited. Use any of 35+ supported providers (Anthropic, OpenAI, AWS Bedrock, Azure OpenAI, Google, Ollama, and more) - **[Altimate LLM Gateway](https://help.altimate.ai/datamates/user-guide/components/llm-gateway/index.md)** — Managed LLM access with dynamic routing across Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, and more. 10M tokens free to get started — no API keys to manage ## Standalone Usage Altimate Code can also be used outside the IDE as a standalone CLI/TUI: | Interface | Description | | ----------------- | ---------------------------------------------- | | **TUI** | Interactive terminal UI — `altimate` | | **CLI** | Command-line for scripting — `altimate run` | | **Web UI** | Browser-based interface — `altimate web` | | **CI/CD** | Headless mode for pipelines — `altimate check` | | **GitHub/GitLab** | Automated PR review and issue triage | Install standalone. **macOS / Linux:** ```bash curl -fsSL https://www.altimate.sh/install | bash ``` **Windows:** ```bash npm install -g altimate-code ``` ## Full Documentation - **Altimate Code docs** — [Altimate Code section](/code/) - **Altimate MCP docs** — [Altimate MCP section](/datamates/) # Components Overview Altimate MCP consists of 4 main components: - [**Integrations**](https://help.altimate.ai/datamates/user-guide/components/integrations/integrations/index.md) ______________________________________________________________________ Connect with popular data tools like Airflow, BigQuery, dbt, Databricks, GitHub, Jira, PostgreSQL, and Snowflake - [**Knowledge Hub**](https://help.altimate.ai/datamates/user-guide/components/knowledgehub/index.md) ______________________________________________________________________ Centralize your organization's tribal knowledge and best practices with expert-built templates and context-aware AI assistance - [**Memory Hub**](https://help.altimate.ai/datamates/user-guide/components/memory/index.md) ______________________________________________________________________ Enable intelligent context management by storing conversations, managing team knowledge, and providing personalized assistance - [**Guardrails**](https://help.altimate.ai/datamates/user-guide/components/guardrails/index.md) ______________________________________________________________________ Protect sensitive data by controlling exposure to LLM providers and managing PII and confidential information ## Integrations Our platform integrates with popular data tools and services. You can customize your Altimate MCP by adding tools from different integrations, this creates an ideal agent for whatever workflow you need. ## Knowledge Hub The Knowledge Hub centralizes your organization's tribal knowledge and best practices. It allows you to: - Create and maintain unified knowledge bases - Use expert-built templates - Provide context-aware AI assistance - Share knowledge across your team ## Memory Hub Memory Hub enables intelligent context management by: - Storing and recalling past conversations and decisions - Managing add, reference, and recall memories - Providing personalized assistance based on historical context - Sharing memories across tools and IDEs ## Guardrails Guardrails protect your sensitive data by: - Controlling data exposure to LLM providers - Managing PII and confidential information - Setting custom data protection rules - Ensuring compliance with security policies Each component is designed to work seamlessly together, providing a secure and efficient environment for data development and management. # Guardrails Protect sensitive data with custom guardrails. Control what information is shared from your data ecosystem to LLM providers. Prevent PII and confidential data exposure. ## How to Use Guardrails The Guardrails feature allows you to manage and control the exposure of sensitive data types within your system. You can specify which types of data should be blocked or allowed when interacting with LLM providers. ### Data Protection Settings On the Guardrails page, you will see a list of data types under **Data protection**. Each data type (e.g., Email, Phone Number, IP Address, SSN, Credit Card) has a status indicating whether it is currently set to `block`, `mask`, or `allow`. - **block**: The data will not be passed and the tool call will be blocked. - **mask**: The data will be passed but obscured. - **allow**: The data will be passed unobscured. ### Editing Guardrails To change the protection status for any data type: 1. Click the **Edit** button on the right side of the Data protection section. 1. Adjust the settings for each data type as needed (choose between `block` or `allow`). 1. Save your changes to update the guardrails. ### Navigation - Use the navigation buttons at the bottom to move between steps (e.g., **Knowledge**, **Next: Overview**). - The progress bar at the top shows your current step in the setup process. ### Best Practices - Block data types that are considered PII (Personally Identifiable Information) or confidential, such as Email and Phone Number, to enhance data privacy. - Review and update your guardrails regularly to ensure compliance with your organization's data protection policies. ______________________________________________________________________ For more information, refer to the main documentation or contact your system administrator. ## Introduction The Altimate Knowledge Hub empowers your organization to centralize and leverage its tribal knowledge and best practices, directly within your AI workflows, particularly in your IDEs like Cursor, Github Copilot, Windsurf. By providing this curated information as verified Context, you can achieve more reliable and relevant AI-generated outputs, curb hallucinations, and move beyond generic code generation to solutions tailored to your specific organizational needs. LLMs rely on outdated or generic information about the libraries or components you use. The "best" LLM doesn't know about any internal knowledge or best practices that have been built through years of collective human effort. This guide will walk you through accessing, creating, and utilizing your knowledge within the Altimate Knowledge Hub. ## What You Can Do - **Create Unified Knowledge:** Keep all your team's best practices, code standards, and guides in one spot - **Leverage Expert-Built Templates:** Start with pre-built templates created by Altimate, drawing on our years of in-house data technology expertise and best practices refined through working with multiple global technology giants. - **Contextualise your AI Workflows:** Each knowledge doc gets a unique link which can be used in your IDE of choice to get AI to understand your team's specific context. When you open the Knowledge Hub, you'll see: - **My Knowledge:** This is where your team's custom knowledge documents live. If it's your first time, this might be empty. - **Altimate Knowledge Templates:** A list of ready-to-use documents (e.g., "DataOps Best Practices," "PySpark Best Practices"). You can: - **View Details:** See what's inside a template. - **Fork:** Copy a template to "My Knowledge" to customize it. - **Create New Knowledge button:** Lets you start a new knowledge document from zero. ## Creating New Knowledge **1. Forking (Copying) a Template:** This is the fastest way to start. 1. Find a template you like in "Altimate Knowledge Templates." 1. Click **Fork**. 1. Give your new document a clear name (e.g., "Our Team's Python Standards"). 1. Click **Fork** again in the pop-up. Your new document will now appear in "My Knowledge." **2. Creating from Scratch:** 1. Click the **Create New Knowledge** button (usually top-right). 1. Follow the steps to set up your knowledge. You can paste upto 1MB of text ## Using Available Knowledge This is where Knowledge Hub shines. You tell your IDE agents like Cursor, Github Copilot, Windsurf, Cline, etc. to use your team's specific knowledge for context. First, get the link **Get the Link:** - Go to "My Knowledge" in the Altimate Knowledge Hub. (https://.app.getaltimate.com/knowledge-catalog) - Open the document you want the AI to use by clicking "View Details." - Copy its **Link** (e.g., `https://apimi.getaltimate.com/knowledge_...`). Private Links - Request Only. Access your Internal organisation knowledge as locally a hosted knowledge hub. You can contact us over [Slack](https://getdbt.slack.com/archives/C05KPDGRMDW) or [Chat](https://app.myaltimate.com/contactus). ### For Cursor Users **Use it in Cursor:** - In Cursor, go to Agent Mode (Cmd + I) or (Ctrl + Shift + I) - Type `@doc` select Docs, scroll to the bottom of the list and click on add a new doc - Paste the copied link. - Provide a name for your doc (my-kb) - Now you can reference your knowledge as @my-kb in your tasks. Example - ```text Refactor this @model.sql file using my best practices @my-kb ``` Follow this tutorial to use your knowledge in Cursor - ### For Github Copilot Users **Use it in Github Copilot:** - In Github Copilot, go to Agent Mode (Cmd + Control + I) or (Ctrl + Shift + I) - Type `#fetch` and paste the copied link - Approve Github Copilot to access the link - (Optional) If you don't want to explicitly approve every time, you can add this link to your Trusted Domains in VSCode Example - ```text Refactor this @model.sql file using my best practices #fetch ``` ### For Cline Users **Use it in Cline:** - In Cline, type @ Example - ```text Refactor this @model.sql file using my best practices @ ``` ### For Windsurf Users **Use it in Windsurf:** - In Windsurf, type @web Example - ```text Refactor this @model.sql file using my best practices @web ``` ## Knowledge Engine Enterprise Feature Knowledge Engine is available in the Enterprise edition only. Contact us over [Slack](https://getdbt.slack.com/archives/C05KPDGRMDW) or [Chat](https://app.myaltimate.com/contactus) to upgrade. ### What is Knowledge Engine? Knowledge Engine is an intelligent document processing system that transforms your uploaded documents into queryable knowledge bases. When you upload documents to a knowledge base, the Knowledge Engine: 1. **Parses the Document:** Extracts text and processes embedded images 1. **Creates Retrievable Context:** Indexes content for intelligent retrieval through AI agents 1. **Improves performance and efficiency:** Instead of sending full documents as context to AI agents - which consumes a lot more tokens and bloats overall context quality, Knowledge Engine surfaces only the relevant knowledge snippets as context ### Why Knowledge Engine Knowledge engine goes beyond simple text storage by: - **Processing Multiple Formats:** Upload PDF, Word (.docx), Markdown (.md), or text files - **Understanding Multimodal Content:** Extracts insights from both text and embedded images (diagrams, charts, screenshots) - **Document Editing:** Update and edit your uploaded documents to keep knowledge current - **Intelligent Context for Agents:** Automatically provides relevant context to AI agents in your IDE through MCP integration ### Knowledge Engine Components The Knowledge Engine interface provides three key views: #### 1. Document Tab Shows your uploaded document once it is parsed. #### 2. Learnings Tab Shows the structured knowledge extracted from your document: - **Learning name:** Name given to a certain group of information within the document - **Tags:** Auto-generated categorization - **Document:** Name of the actual document - **Retrieval Count:** Track how often each learning is accessed #### 3. History Tab Monitor document processing and versions: - Upload history with timestamps - Processing status (Uploading → Processing → Completed/Failed) - Version control for document updates - File metadata (filename, type, size, uploaded by etc) ### Enabling Knowledge Engine for Your Altimate MCP To use Knowledge Engine with your Altimate MCP in the IDE: 1. Navigate to **Altimate MCP** in your Altimate platform 1. Select or create an Altimate MCP 1. In the Altimate MCP, locate the **Knowledge Hub** section 1. Toggle On the **Knowledge Engine** option 1. Select which knowledge bases your Altimate MCP should have access to Once enabled, your Altimate MCP can automatically retrieve relevant context from your knowledge bases when you query it through the MCP server in your IDE. # Altimate LLM Gateway The Altimate LLM Gateway is a managed LLM service that gives you access to the best AI models — **60-80% cheaper** than buying tokens directly from providers. No API keys to manage, no billing across multiple providers, no rate limits to worry about. ## How It Works The gateway dynamically routes each request to the best model for the task across **Sonnet 4.6, Opus 4.6, GPT-5.4, GPT-5.3, and GPT-5.4-mini**. You pay a flat token price regardless of which model handles your request — no surprise bills from expensive model routing. ## Pricing | Plan | Price | Tokens/mo | $/M tokens | Overage (per 1M tokens) | | -------------- | ------ | -------------- | ---------- | ----------------------- | | **Community** | $0/mo | 10M (one-time) | Free | BYOK only | | **Pro Tier 1** | $29/mo | 20M | $1.45 | $5/M tokens | | **Pro Tier 2** | $89/mo | 70M | $1.27 | $3/M tokens | | **Enterprise** | Custom | Custom | Custom | Negotiated | Tokens are counted as input + output combined. All tiers get access to all models — the upgrade incentive is volume, not capability. ## What Would This Cost You Directly? Buying 20M tokens directly from providers: | Model | Direct Cost (20M tokens) | With Altimate Pro Tier 1 | Savings | | ----------------------- | ------------------------ | ------------------------ | ------- | | Sonnet 4.6 | ~$84 | **$29** | ~65% | | Opus 4.6 | ~$140 | **$29** | ~79% | | GPT-5.4 (short context) | ~$75 | **$29** | ~61% | | GPT-5.4 (long context) | ~$135 | **$29** | ~79% | With Altimate, you pay $29 flat regardless of which model handles your task. Buying the same 20M tokens directly from providers would cost $75-140 depending on the model — and you'd have to manage API keys, billing, and rate limits across multiple providers yourself. ## BYOK vs. Gateway | | BYOK (Bring Your Own Key) | Altimate LLM Gateway | | ------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | | **Cost** | Free and unlimited | Token-based pricing (10M tokens free) | | **API Keys** | You manage your own keys | No keys needed | | **Models** | Any model from your provider | Dynamic routing across best-in-class models | | **Data Path** | Direct to your provider — Altimate never sees it | Through Altimate — see [Security FAQ](https://help.altimate.ai/datamates/faq/security/#llm-ai-security) for data handling details | | **Best For** | Users with existing API keys or strict data residency requirements | Users who want simplicity and cost savings | Both options are always available. You can use BYOK and the gateway side by side. ## Models Available The gateway routes across the following models based on task complexity, context length, and quality requirements: | Model | Provider | Strengths | | --------------------- | --------- | ----------------------------------------------------------- | | **Claude Sonnet 4.6** | Anthropic | Excellent price/performance for most data engineering tasks | | **Claude Opus 4.6** | Anthropic | Highest quality for complex reasoning and analysis | | **GPT-5.4** | OpenAI | Strong general-purpose capabilities | | **GPT-5.3** | OpenAI | Cost-effective for simpler tasks | | **GPT-5.4-mini** | OpenAI | Fast, lightweight tasks | You don't choose the model — the gateway selects the optimal one for each request automatically. ## Security The Altimate LLM Gateway is designed with enterprise security requirements in mind: ### Data Handling - **Your data is not used to train, fine-tune, or improve any models.** - The gateway stores limited metadata (token counts, latency, model used) for billing and routing. - A small number of prompts are sampled for anonymous categorization to improve routing. See [Security FAQ](https://help.altimate.ai/datamates/faq/security/#llm-ai-security) for full details. ### Compliance - **SOC 2 Type II** certified - **TLS 1.3** encryption for all data in transit - AWS infrastructure in private VPC with network isolation - IAM-based RBAC with MFA enforcement for developer access If you need us to do a security review with your IT/security teams, please [contact us](https://www.altimate.ai/support?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) via chat or Slack. ## Getting Started 1. Install the [Datamates extension](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) in your IDE 1. Open the command palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and select **Altimate MCP: Open Altimate Code Chat** 1. The Community plan with 10M free tokens is available immediately — no credit card required To upgrade or manage your plan, visit the [Altimate pricing page](https://www.altimate.ai/pricing?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). ## Overview Memory gives an Agent the ability to recall relevant information. Capture every coding insight, architectural decision, and tribal knowledge with our intelligent memory management system. We built a Memory Hub to enable Data Teams to share Agent memories across tools and IDEs. ## Enable Memory Altimate MCP uses memory to provide personalized IDE assistance by automatically recalling past conversations, coding decisions, and organizational knowledge. Memory settings can be configured per Altimate MCP instance to ensure appropriate context access. This enables Altimate MCP to: - Reference past discussions, requirements, and architectural choices when answering questions or generating code. - Surface relevant tribal knowledge, best practices, and project-specific details without you needing to repeat yourself. - Adapt responses based on your team's unique workflows, security guardrails, and compliance needs. - Store new insights, decisions, and learnings as memories, making them available for future interactions. All memories are accessible and manageable through the Memory Hub, giving you full control over what is remembered and shared. ## Use Memory Enable memory in your Altimate MCP settings to automatically store conversations, decisions, and preferences. Add new memories by telling your Altimate MCP to remember specific information (e.g., "remember we use snake_case for SQL tables"). Ask questions about past decisions to retrieve relevant memories. ## Tools When Memory is enabled, Altimate MCP supply your coding agent with 3 tools: add_memory, search_memory, and list_memories: | Tool Name | Description | Parameters | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `add_memories` | Add a new memory. This method is called everytime the user informs anything about the project, their preferences, or anything that has any relevant information which can be useful in the future conversation. This can also be called when the user asks you to remember something. | - `messages` (array): Array of message objects containing: - `content` (string): The text of the memory - `role` (string, optional): The role of the memory (defaults to "user") | | `search_memory` | Returns relevant information for the user's question. This must be called EVERYTIME before answering the user's question. | - `query` (string): Search query to find relevant memories | | `list_memories` | List all memories in the user's memory | None | # Airflow Tools Documentation This document lists all available Airflow tools and their usage. ## Tools | Tool Name | Description | Parameters | | ----------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `airflow_get_task_log` | Get logs for a specific Airflow task instance | - `dag_id` (string): The ID of the DAG - `dag_run_id` (string): The ID of the DAG Run - `task_id` (string): The ID of the task - `try_number` (number): The try number of the task instance | | `airflow_list_dags` | List all DAGs in Airflow | - `limit` (number, optional): Number of results per page - `offset` (number, optional): Page offset | | `airflow_get_dag` | Retrieve a specific DAG by ID | - `dag_id` (string): The ID of the DAG | | `airflow_update_dag` | Update a DAG (e.g., pause/unpause) | - `dag_id` (string): The ID of the DAG - `is_paused` (boolean): Set to true to pause the DAG | | `airflow_list_dag_runs` | List DAG runs for a specified DAG ID | - `dag_id` (string): ID of the DAG - `order_by` (string, optional): Order By - `page_offset` (number, optional): Page Offset (default 0) - `page_limit` (number, optional): Page Limit (default 100) - `states` (string[], optional): States - `run_after_gte` (string, optional): Run After Gte - `run_after_lte` (string, optional): Run After Lte - `logical_date_gte` (string, optional): Logical Date Gte - `logical_date_lte` (string, optional): Logical Date Lte - `start_date_gte` (string, optional): Start Date Gte - `start_date_lte` (string, optional): Start Date Lte - `end_date_gte` (string, optional): End Date Gte - `end_date_lte` (string, optional): End Date Lte | ## Configuration For enhanced security, it is recommended that you use token-based authentication: 1. Generate an API token in your Airflow instance: 1. Log into the Airflow web UI 1. Navigate to your user profile 1. Look for the "API Tokens" or "Authentication" section 1. Generate a new token 1. Enter the token and other details in the your Altimate MCP configuration 1. In the configuration panel, set "Authentication Type" to "Token" For more details about Airflow authentication, refer to the [official Airflow documentation](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html). # Alation Tools Documentation This document lists all available Alation tools and their usage. ## Configuration Requirements To use these tools, you need to configure the following: - Alation Base URL - Alation Access Token ## Tools | Tool Name | Description | Parameters | | ------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `get_lineage` | Get lineage information for an object from Alation | - `otype` (enum): Type of the object in Alation. Possible values: 'table', 'column', 'schema', 'bi_report', 'bi_report_column', 'bi_datasource', 'bi_datasource_column', 'file', 'directory', 'external', 'dataflow' - `oid` (string): ID or key of the object in Alation | # Altimate Tools Documentation This document lists all available Altimate tools and their usage for analyzing Snowflake queries and tables with AI-powered optimization insights. These tools are Altimates specialized agents for Snowflake Cost Optimizations for queries, tables, and warehouses ## Tools | Tool Name | Description | Parameters | | ------------------------------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `altimate_analyze_snowflake_query` | Analyze a specific query using Altimate's query analysis API | - `query_id` (string): The ID of the query to analyze | | `altimate_analyze_snowflake_table` | Analyze a specific table using Altimate's table analysis API | - `table_name` (string): The name of the table to analyze | | `altimate_analyze_query_opportunity` | Get plain text explanation for a query optimization opportunity | - `opportunity_id` (string): The opportunity_id to analyze. This field is required - `query_id` (string, optional): The query_id to analyze (optional) - `query_hash` (string): The hash of the query. This field is required | ## Configuration There is no additional config required for Altimate Tools. You need to have an Enterprise plan to use these tool. # Custom API Tools Documentation This document lists all available Custom API tools and their usage. ## Configuration Requirements To use these tools, you need to configure the following: - API Key - Base URL - Headers (optional) ## Tools | Tool Name | Description | Parameters | | ----------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `customApi` | Make HTTP requests to a custom API endpoint | - `endpoint` (string): The API endpoint to call - `method` (string): HTTP method to use (GET, POST, PUT, DELETE) - `parameters` (object, optional): Request parameters (path, query, body) | # Azure DevOps Tools Documentation This document lists all available Azure DevOps tools and their usage. ## Configuration Requirements To use these tools, you need to configure the following: - Organization - Project - Personal Access Token ## Tools | Tool Name | Description | Parameters | | --------------- | ----------------------------------------------------- | ---------------------------------------- | | `get_work_item` | Get details of a specific work item from Azure DevOps | - `id` (string): The ID of the work item | # BigQuery Tools Documentation This document lists all available BigQuery tools and how to connect to BigQuery. ## Tools | Tool Name | Description | Parameters | | ------------------------------------ | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `bigquery_execute_database_query` | Execute SQL queries against Google Cloud BigQuery | - `connection_id` (string): The ID of the BigQuery connection to use - `sql_query` (string): The SQL query to execute | | `bigquery_list_database_connections` | List all available BigQuery connections | None | ## Configuration ### Required Configuration Parameters Before connecting to BigQuery, you'll need to gather the following information: 1. **BigQuery Project ID** - Your Google Cloud project ID (e.g., `my-project-123`) 1. **BigQuery Credentials** - A JSON service account key file with appropriate BigQuery permissions 1. **BigQuery Location** - The geographic location of your BigQuery datasets (e.g., `US`, `EU`, `asia-northeast1`) ### Setting Up Service Account Credentials 1. **Create a Service Account:** 1. Go to the [Google Cloud Console](https://console.cloud.google.com/) 1. Navigate to "IAM & Admin" > "Service Accounts" 1. Click "Create Service Account" 1. Give it a name and description 1. **Assign BigQuery Permissions:** 1. Add the following roles to your service account: - `BigQuery Data Viewer` (for read-only access) - `BigQuery Job User` (for running queries) - `BigQuery Data Editor` (for write access, if needed) 1. **Generate JSON Key:** 1. Click on your service account 1. Go to the "Keys" tab 1. Click "Add Key" > "Create new key" 1. Choose "JSON" format 1. Download the JSON file 1. **Configure in Altimate MCP:** 1. Copy the contents of the downloaded JSON file 1. Paste it into the "BigQuery Credentials" field in your Altimate MCP configuration # Dagster Tools Documentation This document lists all available Dagster tools and their usage. ## Tools | Tool Name | Description | Parameters | | --------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dagster_list_repositories` | List all available Dagster repositories | None | | `dagster_list_jobs` | List all jobs in a specific repository | - `repository_location` (string): The name of the repository location - `repository_name` (string): The name of the repository | | `dagster_list_assets` | List all assets in a specific repository | - `repository_location` (string): The name of the repository location - `repository_name` (string): The name of the repository | | `dagster_get_recent_runs` | Get recent Dagster runs | - `limit` (number, optional): Number of runs to retrieve | | `dagster_get_run_info` | Get detailed information about a specific run | - `run_id` (string): The ID of the run | | `dagster_launch_run` | Launch a Dagster job run | - `repository_location` (string): The name of the repository location - `repository_name` (string): The name of the repository - `job_name` (string): The name of the job to launch - `run_config` (string, optional): JSON string of run configuration | | `dagster_materialize_asset` | Materialize a specific Dagster asset | - `asset_key` (string): The asset key to materialize - `repository_location` (string): The name of the repository location - `repository_name` (string): The name of the repository | | `dagster_terminate_run` | Terminate an in-progress Dagster run | - `run_id` (string): The ID of the run to terminate | | `dagster_get_asset_info` | Get detailed information about a specific asset | - `asset_key` (string): The asset key to get information about | | ## Configuration | | | To use these tools, you need to configure a User level API Token. Step 1: Sign in to your Dagster instance Step 2: Click the user menu (your icon) > Organization Settings. Step 3: Click the Tokens tab. Step 4: Click + Create user token. Step 5: Copy this and save in a secure place Only locally hosted Dagster is supported right now. COMING SOON: Support for Dagster+ deployments (Cloud + Hybrid) # Databricks Tools Documentation This document lists all available Databricks tools and their usage. ## Tools | Tool Name | Description | Parameters | | ------------------------------ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `databricks_list_clusters` | List all Databricks clusters | None | | `databricks_create_cluster` | Create a new Databricks cluster | - `config` (object): Cluster configuration object | | `databricks_terminate_cluster` | Terminate a Databricks cluster | - `cluster_id` (string): Cluster ID to terminate | | `databricks_get_cluster` | Get information about a Databricks cluster | - `cluster_id` (string): Cluster ID to retrieve | | `databricks_start_cluster` | Start a terminated Databricks cluster | - `cluster_id` (string): Cluster ID to start | | `databricks_list_jobs` | List all Databricks jobs | None | | `databricks_run_job` | Run a Databricks job | - `job_id` (number): Job ID to run - `params` (object, optional): Job parameters | | `databricks_list_notebooks` | List notebooks in workspace directory | - `path` (string): Absolute workspace path | | `databricks_export_notebook` | Export a notebook from workspace | - `path` (string): Notebook path - `format` (string): Export format (SOURCE, HTML, JUPYTER, DBC) | | `databricks_list_files` | List files and directories in DBFS path | - `path` (string): DBFS absolute path | | `databricks_execute_sql` | Execute a SQL statement | - `warehouse_id` (string): SQL warehouse ID - `statement` (string): SQL statement to execute - `catalog` (string, optional): Catalog name - `schema` (string, optional): Schema name | | `databricks_list_job_runs` | List runs for a Databricks job | - `job_id` (number): Job ID to list runs for | ## Configuration You would need the following details for using Databricks - - Databricks API URL (DATABRICKS_HOST) - Databricks Token (Personal Access Token) **API URL** - - This environment variable is set to the URL of either your Databricks account console `http://accounts.cloud.databricks.com` or your Databricks workspace URL `https://{workspace-id}.cloud.databricks.com`. Choose a host URL type based on the type of operations you will be performing in your code. - If you are using Databricks [account-level CLI commands or REST API requests](https://docs.databricks.com/api/account), set this variable to your Databricks account URL. - If you are using Databricks [workspace-level CLI commands or REST API requests](https://docs.databricks.com/api/workspace), use your Databricks workspace URL. **Pesonal Access Token (PAT)** - Complete the following steps to generate a PAT - Step 1: In Databricks UI click on your Databricks username Icon on the right top corner and then click click **Settings** Step 2: In **Settings** navigate to **Developer** section and click on click on **Manage** Access Tokens Step 3: Click on Generate Token and set an expiry date Step 4: Copy the token immediately (you won't be able to see it again) Step 5: Add to your Altimate MCP Config For more details about Databricks personal access token, refer to the [official Databricks documentation](https://docs.databricks.com/aws/en/dev-tools/auth/pat). # dbt Tools Documentation This document lists all available dbt tools and their usage. ## Tools | Tool Name | Description | Parameters | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `get_projects` | Returns detailed information about all available dbt projects. This must be called first to get the projectRoot parameter needed for all other tools. | None | | `get_columns_of_model` | Returns the column names and data types for a specified dbt model. Use this to understand a model's schema before querying it. | - `projectRoot` (string): The root directory path of the dbt project - `modelName` (string): The name of the dbt model | | `get_columns_of_source` | Returns the column names and data types for a specified dbt source. Use this to understand a source's schema before querying it. | - `projectRoot` (string): The root directory path of the dbt project - `sourceName` (string): The name of the dbt source - `tableName` (string): The name of the table in the source | | `get_column_values` | Returns the distinct values for a specified column in a model or source. Use this to understand the data distribution and possible values in a column. | - `projectRoot` (string): The root directory path of the dbt project - `model` (string): The model or source name - `column` (string): The column name | | `execute_sql` | Executes SQL queries against the database, returning processed results immediately. Use this to test queries and retrieve data from the database. | - `projectRoot` (string): The root directory path of the dbt project - `query` (string): The SQL query to execute - `modelName` (string): The model name (for context) | | `compile_model` | Converts a dbt model's Jinja SQL into raw SQL. Use this to inspect the generated SQL before executing it. | - `projectRoot` (string): The root directory path of the dbt project - `modelName` (string): The name of the dbt model | | `compile_query` | Compile query, this will only convert the Jinja SQL to SQL, not determine if the SQL actually works. | - `projectRoot` (string): The root directory path of the dbt project - `query` (string): The Jinja SQL query - `originalModelName` (string, optional): The original model name | | `run_model` | Executes a dbt model in the database. Use + for plusOperatorLeft to include parent models, and + for plusOperatorRight to include child models in the run. | - `projectRoot` (string): The root directory path of the dbt project - `plusOperatorLeft` (enum: "", "+"): Include parent models - `modelName` (string): The model name - `plusOperatorRight` (enum: "", "+"): Include child models | | `build_model` | Builds a dbt model in the database. Use + for plusOperatorLeft to include parent models, and + for plusOperatorRight to include child models in the build. | - `projectRoot` (string): The root directory path of the dbt project - `plusOperatorLeft` (enum: "", "+"): Include parent models - `modelName` (string): The model name - `plusOperatorRight` (enum: "", "+"): Include child models | | `build_project` | Builds the dbt project, this will run seeds, models and all related tests. | - `projectRoot` (string): The root directory path of the dbt project | | `run_test` | Run an individual test based on the test name in the dbt manifest. | - `projectRoot` (string): The root directory path of the dbt project - `testName` (string): The name of the test | | `run_model_test` | Run model tests, use this tool to run the existing tests defined for the dbt model. | - `projectRoot` (string): The root directory path of the dbt project - `modelName` (string): The name of the dbt model | | `add_dbt_packages` | Add dbt package(s) to the project, the dbt package string should be in the form of packageName@version. | - `projectRoot` (string): The root directory path of the dbt project - `packages` (string[]): Array of package strings | | `install_deps` | Install dbt package dependencies based on the dbt project's packages.yml file. | - `projectRoot` (string): The root directory path of the dbt project | | `get_children_models` | Returns the list of models that depend on the specified model (its children). Use this to understand a model's downstream impact and lineage. | - `projectRoot` (string): The root directory path of the dbt project - `table` (string): The model name | | `get_parent_models` | Returns the list of models that the specified model depends on (its parents). Use this to understand a model's upstream dependencies and lineage. | - `projectRoot` (string): The root directory path of the dbt project - `table` (string): The model name | ## Configuration To use these tools, you must have a valid dbt project open in your IDE and have the [Power Users for dbt](https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user) Extension installed in your IDE. For more on the Power User for dbt extension please see our documentation page [here](/dbt-power-user/setup/installation/) # GitHub Tools Documentation This document lists all available GitHub tools and their usage. ## Tools | Tool Name | Description | Parameters | | --------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `github_get_issue` | Get details of a specific issue or pull request in a GitHub repository. | - `owner` (string): The owner of the repository - `repo` (string): The name of the repository - `issue_number` (string): The number of the issue or pull request | | `github_create_issue` | Create a new issue in a GitHub repository. | - `owner` (string): The owner of the repository - `repo` (string): The name of the repository - `title` (string): The title of the issue - `body` (string, optional): The content of the issue - `labels` (string[], optional): Labels to apply to the issue | ## Configuration Our Github integration supports Personal Access Token based authentication. Below are instructions for setting up the two most common PAT token types: - Create a Classic PAT - Create a Fine Grained PAT (Recommended) ### Create a Classic PAT 1. Go to GitHub Settings: 1. Click your profile picture in the top right 1. Select "Settings" 1. Click "Developer settings" at the bottom of the left sidebar 1. Click "Personal access tokens" → "Tokens (classic)" 1. Generate a new token: 1. Click "Generate new token" → "Generate new token (classic)" 1. Give your token a descriptive name in the "Note" field 1. Set an expiration date (recommended for security) 1. Select the required scopes: 1. For basic repository access: `repo` scope 1. For private repositories: ensure `repo` is selected 1. For public repositories only: `public_repo` scope 1. Click "Generate token" and copy the token immediately (you won't be able to see it again) ### Create a Fine Grained PAT (Recommended) 1. Go to GitHub Settings: 1. Click your profile picture in the top right 1. Select "Settings" 1. Click "Developer settings" at the bottom of the left sidebar 1. Click "Personal access tokens" → "Fine grained tokens" 1. Generate a new token: 1. Click "Generate new token" → "Generate new token" 1. Give your token a name - Ideally separate `datamates_name` 1. Set an expiration date (recommended for security) 1. Select the repositories 1. Select the following permissions - Issues - `read` and `write` Metadata permissions are automatically granted read access by enabling any other permission Organization owners can restrict the access of personal access token (classic) to their organization. If you try to use a personal access token which has been access controled at your account level, your request will fail with a 4xx response. # Google Sheets Tools Documentation This document lists all available Google Sheets tools and their usage. ## Tools | Tool Name | Description | Parameters | | ----------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sheets_check_access` | Check access permissions for a spreadsheet | Returns information about what operations are allowed | | `sheets_get_values` | Get values from a specified range in a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to retrieve (e.g., "Sheet1!A1:C10") | | `sheets_batch_get_values` | Get values from multiple ranges in a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `ranges` (array): Array of A1 notation ranges to retrieve | | `sheets_get_metadata` | Get metadata about a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet | | `sheets_update_values` | Update values in a specified range of a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to update - `values` (array): 2D array of values to update | | `sheets_batch_update_values` | Update values in multiple ranges of a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `data` (array): Array of range and values objects | | `sheets_append_values` | Append values to the end of a table in a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to append to - `values` (array): 2D array of values to append | | `sheets_clear_values` | Clear values in a specified range of a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to clear | | `sheets_create_spreadsheet` | Create a new Google Sheets spreadsheet | - `title` (string): The title of the new spreadsheet - `sheets` (array, optional): Array of sheet properties to create | | `sheets_insert_sheet` | Add a new sheet to an existing Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `title` (string): The title of the new sheet | | `sheets_delete_sheet` | Delete a sheet from a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `sheet_id` (number): The ID of the sheet to delete | | `sheets_duplicate_sheet` | Duplicate a sheet within a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `source_sheet_id` (number): The ID of the sheet to duplicate - `new_sheet_name` (string, optional): Name for the duplicated sheet | | `sheets_copy_to` | Copy a sheet to another Google Sheets spreadsheet | - `source_spreadsheet_id` (string): The ID of the source spreadsheet - `source_sheet_id` (number): The ID of the sheet to copy - `destination_spreadsheet_id` (string): The ID of the destination spreadsheet | | `sheets_update_sheet_properties` | Update properties of a sheet in a Google Sheets spreadsheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `sheet_id` (number): The ID of the sheet - `properties` (object): Sheet properties to update | | `sheets_format_cells` | Format cells in a Google Sheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to format - `format` (object): Formatting properties (colors, fonts, alignment, number formats) | | `sheets_update_borders` | Update borders of cells in a Google Sheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range - `borders` (object): Border properties | | `sheets_merge_cells` | Merge cells in a Google Sheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to merge | | `sheets_unmerge_cells` | Unmerge cells in a Google Sheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range to unmerge | | `sheets_add_conditional_formatting` | Add conditional formatting rules to a Google Sheet | - `spreadsheet_id` (string): The ID of the spreadsheet - `range` (string): The A1 notation range - `rule` (object): Conditional formatting rule properties | ## Configuration To use these tools, you need to configure the following: 1. Google Cloud Project ID 1. Service Account Key (JSON credentials file) ### Step 1: Create a Google Cloud Project If you don't already have a Google Cloud project, create one in the Google Cloud Console. 1. Go to Google Cloud Console 1. Click "Select a project" and then "NEW PROJECT" 1. Enter a project name and click "Create" ### Step 2: Enable Google Sheets API 1. In your Google Cloud project, go to "APIs & Services" > "Library" 1. Search for "Google Sheets API" and click "Enable" ### Step 3: Create a Service Account 1. In the Google Cloud console, go to Menu menu > IAM & Admin > Service Accounts. Click Create service account. Fill in the service account details, then click Create and continue. 1. Navigate to "IAM & Admin" > "Service Accounts" in the left sidebar 1. Click "Create Service Account" 1. Enter a service account name (e.g., "sheets-mcp-integration"). Optionally add a description 1. Click "Create and Continue" 1. Grant the neccessary privileges 1. Click "Done" ### Step 4: Create and Download Service Account Key 1. Select your service account. Click Keys > Add key > Create new key 1. Select JSON, then click Create. Your new public/private key pair is generated and downloaded to your machine as a new file 1. Save the downloaded JSON file ### Step 5: Share Spreadsheets with Service Account Now we are good to create our spreadsheet in Google Sheets and share it with our credentials. To do that, open your downloaded json file, copy the client_email information, and share your spreadsheet with this email. Please be certain to share it with the "can edit" option. 1. Open your downloaded JSON service account key file 1. Copy the client_email value (it will look like your-service-account@your-project-id.iam.gserviceaccount.com) 1. Open any Google Sheets spreadsheet you want to access 1. Click the "Share" button 1. Add the service account email address 1. Set permissions to "Editor" to allow full read/write access # Altimate MCP Integrations Overview Altimate MCP provides seamless integration with various data platforms, tools, and services to enhance your workflow and productivity. These integrations allow you to connect, access, and manipulate data across different environments without leaving your IDE. ## How Integrations Work Altimate MCP integrations operate through secure API connections, enabling bidirectional data flow between your development environment and external services. Each integration is designed to: 1. **Authenticate securely** - Using API keys, OAuth tokens, or service credentials 1. **Access remote resources** - Query databases, manage workflows, or interact with cloud services 1. **Execute operations** - Run commands, submit jobs, or retrieve results directly from your IDE ## Available Integrations Altimate MCP currently supports the following integrations: | Integration | Capabilities | | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | [Airflow](https://help.altimate.ai/datamates/user-guide/components/integrations/airflow/index.md) | Manage DAGs, monitor workflows, trigger runs | | [Altimate](https://help.altimate.ai/datamates/user-guide/components/integrations/altimate/index.md) | Connect to Altimate services | | [BigQuery](https://help.altimate.ai/datamates/user-guide/components/integrations/bigquery/index.md) | Execute queries, manage datasets, explore tables | | [Dagster](https://help.altimate.ai/datamates/user-guide/components/integrations/dagster/index.md) | Manage DAGs, monitor workflows, trigger runs | | [Databricks](https://help.altimate.ai/datamates/user-guide/components/integrations/databricks/index.md) | Run notebooks, manage clusters, access DBFS | | [dbt](https://help.altimate.ai/datamates/user-guide/components/integrations/dbt/index.md) | Compile models, run tests, generate documentation | | [GitHub](https://help.altimate.ai/datamates/user-guide/components/integrations/github/index.md) | Manage repositories, issues, and pull requests | | [Google Sheets](https://help.altimate.ai/datamates/user-guide/components/integrations/google_sheets/index.md) | Get, update and manage Sheets | | [Jira](https://help.altimate.ai/datamates/user-guide/components/integrations/jira/index.md) | Create/update tickets, track progress | | [Linear](https://help.altimate.ai/datamates/user-guide/components/integrations/linear/index.md) | Create/update Issues, track progress, get documents, project info | | [PostgreSQL](https://help.altimate.ai/datamates/user-guide/components/integrations/postgresql/index.md) | Execute SQL, manage databases, explore schemas | | [Snowflake](https://help.altimate.ai/datamates/user-guide/components/integrations/snowflake/index.md) | Run queries, manage warehouses, explore data | | [Custom API](https://help.altimate.ai/datamates/user-guide/components/integrations/api/index.md) | Custom API integration capabilities | | **\*Alation (Coming Soon)** | Access data catalogs, query metadata | | **\*Azure DevOps (Coming Soon)** | Manage work items, pipelines, repositories | | **\*Service Now (Coming Soon)** | Create and Manage Incidents | ## Setting Up Integrations To configure an integration: 1. Navigate to the Altimate MCP settings panel in your IDE 1. Select the "Integrations" tab 1. Choose the service you want to connect 1. Enter your authentication credentials 1. Test the connection to verify access ## Benefits of Using Integrations - **Streamlined Workflow** - Access all your tools from a single interface - **Reduced Context Switching** - No need to leave your IDE to perform operations - **Enhanced Productivity** - Automate repetitive tasks across platforms - **Improved Collaboration** - Share connections and configurations with team members - **Centralized Management** - Monitor and control all your data resources in one place ## Best Practices - Regularly rotate API keys and access tokens - Use environment variables or secure storage for sensitive credentials - Set appropriate permission levels for each integration - Monitor usage patterns to optimize performance - Document custom integrations for team knowledge sharing For detailed information about specific integrations, please visit the individual integration pages linked in the table above. # Jira Tools Documentation This document lists all available Jira tools and their usage. ## Tools | Tool Name | Description | Parameters | | -------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `jira_get_issue` | Get details of a specific Jira issue. | - `issueIdOrKey` (string): The ID or key of the Jira issue | | `jira_create_issue` | Create a new Jira issue. | - `projectKey` (string): The project key in Jira (e.g., PROJ) - `summary` (string): A short summary of the issue - `description` (string): A detailed description of the issue - `issueType` (string): The type of the issue (e.g., Bug, Task) - `parent` (string, optional): Parent ticket ID (e.g., PROJ-123) | | `jira_get_child_issues` | Get all child issues from a parent ticket. | - `parentIssueKey` (string): The key of the parent issue (e.g., PROJ-123) | | `jira_add_comment` | Add a comment to a Jira ticket and optionally mention users. | - `issueIdOrKey` (string): The ID or key of the Jira issue to comment on - `comment` (string): The text of the comment to add - `mentionAccountIds` (string[], optional): List of Atlassian accountIds to mention at the start of the comment | | `jira_update_issue_status` | Update the status of a Jira ticket by performing a transition. | - `issueIdOrKey` (string): The ID or key of the Jira issue to update - `transitionId` (string): The ID of the transition to perform (corresponds to the desired status) | | `jira_get_available_transitions` | Get all possible transitions for a Jira issue. | - `issueIdOrKey` (string): The ID or key of the Jira issue to get transitions for | | `jira_link_issue` | Link two Jira issues using a specified link type and direction. | - `sourceIssueKey` (string): The key of the source Jira issue (e.g., PROJ-123) - `destinationIssueKey` (string): The key of the destination Jira issue (e.g., PROJ-456) - `linkType` (string): The type of link (e.g., 'Blocks') - `direction` (enum): Direction of the link: 'outward' (source affects destination) or 'inward' (destination affects source) | | `jira_get_link_types` | Get all available issue link types in Jira. | None | ## Configuration To use these tools, you need to configure the following: - Jira Domain - Jira Email - Jira API Token Get these by going to your [Atlassian's API Token](https://id.atlassian.com/manage-profile/security/api-tokens) page and creating a new API token with scopes. Enter your token and connection details when setting up the JIRA integration: # Linear Tools Documentation This document lists all available Linear tools and their usage. ## Tools | Tool Name | Description | Parameters | | ---------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `linear_create_issue` | Create a new issue in Linear | - `title` (string): The issue title - `description` (string, optional): The issue description as Markdown - `team` (string): The team ID - `cycle` (string, optional): The cycle ID to add the issue to - `priority` (number, optional): The issue priority. 0 = No priority, 1 = Urgent, 2 = High, 3 = Normal, 4 = Low. Do not set this field unless explicitly requested. - `project` (string, optional): The project ID to add the issue to - `state` (string, optional): The issue state ID - `assignee` (string, optional): The assignee user ID to assign - `delegate` (string, optional): The delegate user ID - `labels` (array[string], optional): Array of label IDs to set on the issue - `dueDate` (string, optional): The due date for the issue in ISO format - `parentId` (string, optional): The parent issue ID, if this is a sub-issue - `links` (array[object], optional): Array of link objects to attach to the issue. Each object must contain a valid `url` and a non-empty `title`. | | `linear_get_issue` | Get details of a specific issue by ID or identifier | - `id` (string): Issue ID or identifier (e.g., ENG-123) | | `linear_list_issues` | List issues with filtering and pagination | - `limit` (number, optional): The number of results to return (Max is 250) - `before` (string, optional): An ID to end at - `after` (string, optional): An ID to start from - `orderBy` (enum["createdAt", "updatedAt"], optional): The order in which to return results - `query` (string, optional): Search for content in the issue title or description - `team` (string, optional): The team ID to filter by - `state` (string, optional): The state ID to filter by - `cycle` (string, optional): The cycle ID to filter by - `label` (string, optional): A label ID to filter by - `assignee` (string, optional): The assignee user ID to filter by - `delegate` (string, optional): The delegate user ID to filter by - `project` (string, optional): The project ID to filter by - `parentId` (string, optional): The parent issue ID to filter by - `createdAt` (string, optional): Return only issues created on or after this ISO-8601 date-time or duration. e.g. -P1D to get issues created in the last day - `updatedAt` (string, optional): Return only issues updated on or after this ISO-8601 date-time or duration. e.g. -P1D to get issues updated in the last day - `includeArchived` (boolean, optional): Whether to include archived issues | | `linear_update_issue` | Update an existing issue | - `id` (string): The issue ID - `title` (string, optional): The issue title - `description` (string, optional): The issue description as Markdown - `priority` (number, optional): The issue priority. 0 = No priority, 1 = Urgent, 2 = High, 3 = Normal, 4 = Low. Do not set this field unless explicitly requested. - `project` (string, optional): The project ID to add the issue to - `state` (string, optional): The issue state ID - `cycle` (string, optional): The cycle ID - `assignee` (string, optional): The assignee user ID to assign - `delegate` (string, optional): The delegate user ID - `labels` (array[string], optional): Array of label IDs to set on the issue - `parentId` (string, optional): The parent issue ID, if this is a sub-issue - `dueDate` (string, optional): The due date for the issue in ISO format - `estimate` (number, optional): The numerical issue estimate value - `links` (array[object], optional): Array of link objects to attach to the issue. Each object must contain a valid `url` and a non-empty `title`. | | `linear_list_my_issues` | List issues assigned to the current user | - `limit` (number, optional): The number of results to return (Max is 250) - `before` (string, optional): An ID to end at - `after` (string, optional): An ID to start from - `orderBy` (enum["createdAt", "updatedAt"], optional): The order in which to return results | | `linear_list_issue_statuses` | List all workflow states for issues | - `teamId` (string, optional): Team ID to get states for | | `linear_list_issue_labels` | List all issue labels | - `teamId` (string, optional): Team ID to get labels for | | `linear_create_issue_label` | Create a new issue label | - `name` (string): Label name - `description` (string, optional): Label description - `color` (string, optional): Label color (hex code) - `teamId` (string, optional): Team ID | | `linear_list_comments` | List comments for a specific issue | - `issueId` (string): Issue ID - `first` (number, optional): Number of comments to return - `after` (string, optional): Cursor for pagination | | `linear_create_comment` | Create a new comment on an issue | - `issueId` (string): Issue ID - `body` (string): Comment content in markdown - `createAsUser` (string, optional): Name to display for the comment creator - `displayIconUrl` (string, optional): URL of the avatar to display | | `linear_list_cycles` | List cycles with filtering and pagination | - `first` (number, optional): Number of cycles to return - `after` (string, optional): Cursor for pagination - `team` (string, optional): Filter by team ID - `isActive` (boolean, optional): Filter by active status | | `linear_list_documents` | List documents with filtering and pagination | - `first` (number, optional): Number of documents to return - `after` (string, optional): Cursor for pagination - `project` (string, optional): Filter by project ID | | `linear_get_document` | Get details of a specific document | - `id` (string): Document ID | | `linear_list_projects` | List projects with filtering and pagination | - `limit` (number, optional): Number of projects to return - `after` (string, optional): Cursor for pagination - `before` (string, optional): Cursor for backward pagination - `team` (string, optional): Filter by team ID - `query` (string, optional): Search projects by name - `state` (enum["backlog", "planned", "started", "paused", "completed", "canceled"], optional): Filter by project state - `includeArchived` (boolean, optional): Include archived projects | | `linear_get_project` | Get details of a specific project | - `id` (string): Project ID | | `linear_create_project` | Create a new project | - `name` (string): Project name - `description` (string, optional): Project description - `teamIds` (array[string], optional): Team IDs - `leadId` (string, optional): Project lead user ID - `memberIds` (array[string], optional): Project member user IDs - `startDate` (string, optional): Project start date (ISO format) - `targetDate` (string, optional): Project target date (ISO format) - `priority` (number, optional): Project priority (1-4) | | `linear_update_project` | Update an existing project | - `id` (string): Project ID - `name` (string, optional): Project name - `description` (string, optional): Project description - `leadId` (string, optional): Project lead user ID - `memberIds` (array[string], optional): Project member user IDs - `startDate` (string, optional): Project start date (ISO format) - `targetDate` (string, optional): Project target date (ISO format) - `priority` (number, optional): Project priority (1-4) - `state` (enum["backlog", "planned", "started", "paused", "completed", "canceled"], optional): Project state | | `linear_list_project_labels` | List all project labels | - `teamId` (string, optional): Team ID to get project labels for | | `linear_list_teams` | List teams with optional filtering by name or key | - `limit` (number, optional): Number of teams to return - `after` (string, optional): Cursor for pagination - `before` (string, optional): Cursor for backward pagination - `query` (string, optional): Search teams by name or key | | `linear_get_team` | Get details of a specific team by ID | - `id` (string): Team ID | | `linear_list_users` | List users with optional filtering by name or email | - `limit` (number, optional): Number of users to return - `after` (string, optional): Cursor for pagination - `before` (string, optional): Cursor for backward pagination - `includeDisabled` (boolean, optional): Include disabled users - `query` (string, optional): Search users by name, displayName, or email - `name` (string, optional): Filter users by name - `email` (string, optional): Filter users by email - `active` (boolean, optional): Filter by active status | | `linear_get_user` | Get details of a specific user or current user | - `id` (string, optional): User ID (optional, defaults to current user) | ## Configuration To use these tools, you need to configure a **Linear Personal API Key** ### Creating your Linear Personal API Key: Step 1: Navigate to your profile icon. Step 2: Select 'Settings'. Step 3: Click 'Security & access'. Step 4: Go to the 'Personal API keys'. Step 5: Click on 'New API key'.Step 6: Click the API key field and enter a name for your API.We recommend using "altimate-Altimate MCP" as the name for easier tracking. Only Admins and permitted Members can create personal API keys from Settings > Account > Security & Access. # PostgreSQL Tools Documentation This document lists all available Postgres tools and their usage. ## Tools | Tool Name | Description | Parameters | | -------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `postgresql_execute_database_query` | **Execute** SQL queries against a PostgreSQL database | - `connection_id` (string): The ID of the PostgreSQL connection to use - `sql_query` (string): The SQL query to execute | | `postgresql_list_database_connections` | List all available PostgreSQL connections | None | ## Configuration ### Required Parameters Before connecting to PostgreSQL, you'll need to gather the following information: 1. **PostgreSQL Host** - The server address where your PostgreSQL database is running (e.g., `localhost` or `db.example.com`) 1. **PostgreSQL Port** - The port number PostgreSQL is listening on (default is `5432`) 1. **PostgreSQL Database** - The name of the database you want to connect to 1. **PostgreSQL Username** - Your database user account 1. **PostgreSQL Password** - Your database user password 1. **PostgreSQL Schema** (optional) - The specific schema you want to use (defaults to `public` if not specified) ### Connection String Format The standard PostgreSQL connection string format is: ```postgresql postgresql://:@:/ ``` Example: ```postgresql postgresql://myuser:mypassword@localhost:5432/mydatabase ``` ## Troubleshooting If you encounter connection issues: 1. Check if the PostgreSQL server is running 1. Verify your credentials are correct 1. Ensure the database exists and is accessible 1. Check network connectivity to the host and port 1. Verify your IP is allowed in PostgreSQL's access control lists (pg_hba.conf) For additional help or specific error messages, consult the [PostgreSQL documentation](https://www.postgresql.org/docs/current/index.html). # Snowflake Tools Documentation This document lists all available Snowflake tools and their usage. ## Tools | Tool Name | Description | Parameters | | ------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | | `snowflake_execute_database_query` | Execute SQL queries against a Snowflake database | - `connection_id` (string): The ID of the Snowflake connection to use - `sql_query` (string): The SQL query to execute | | `snowflake_list_database_connections` | List all available Snowflake connections | None | ## Configuration To use these tools, you need to configure one of the following authentication methods: - Username/Password authentication - External Browser authentication - [OAuth authentication](https://docs.snowflake.com/en/user-guide/oauth-ext-overview) - [Key Pair authentication](https://docs.snowflake.com/en/user-guide/key-pair-auth#configuring-key-pair-authentication) For more information on connecting to Snowflake - check out their [docs](https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-connect#connecting-using-the-default-authenticator) Common configuration parameters: - Snowflake Account - Username - Database - Schema - Warehouse - Role # Setting Up Claude Code with Altimate MCP Connect Altimate MCP to Claude Code to use your AI assistant with MCP (Model Context Protocol) server capabilities. ## Configuration Steps Tip You can also install the extension using the Datamates GUI in [VSCode](https://help.altimate.ai/datamates/user-guide/setup/vscode-setup/index.md) or [Cursor](https://help.altimate.ai/datamates/user-guide/setup/cursor-setup/index.md). If you do, skip to [Step 3](#step-3-run-altimate-diagnostics-and-copy-server-url) on this page to continue the Claude Code setup. ### Step 1: Install Extension in IDE 1. Open Extensions in your IDE (`Ctrl+Shift+X` or `Cmd+Shift+X`). 1. Search for "Datamates". 1. Find **Datamates by Altimate AI**. 1. Click **Install**. ### Step 2: Add Instance Name and API Key Configure your Altimate credentials in the Datamates extension: 1. Click **Select datamate** on the bottom of your IDE screen. 1. Click on the vertical ellipse on the top right of the Datamates menu. 1. Select **view credentials**. 1. Select your Datamates' plan: Either **Community, Pro, or Team Plan** or **Enterprise Plan**. 1. Enter your **Altimate Instance Name** (e.g., `mycompany`). 1. Enter your **Altimate API Key**. Note To find your API Key and instance name: 1. Navigate to the Datamates website. 1. On the sidebar, click **settings**. 1. Click **API Key**. ### Step 3: Run Altimate Diagnostics and Copy Server URL 1. Open Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`). 1. Run: `Datamates: Run Altimate Diagnostics`. 1. Wait for diagnostics to complete successfully. 1. Copy the **server URL** from the diagnostics output (it will look like `http://localhost:7700/sse`). Note The port number (7700) may vary depending on your system. Use the exact URL shown in your diagnostics output. ### Step 4: Add MCP Server to Claude Code Add the Datamates MCP server to Claude Code using the command line: ```bash claude mcp add --transport sse datamate http://localhost:7700/sse ``` Important Make sure to replace `http://localhost:7700/sse` with the actual server URL from your diagnostics output if it's different. Command Breakdown - `claude mcp add` - Adds a new MCP server - `--transport sse` - Specifies Server-Sent Events transport type - `datamate` - The name for this MCP server - `http://localhost:7700/sse` - The server URL from your diagnostics You can verify the MCP server was added by running: ```bash claude mcp list ``` ## Interactive Demo ## Configuration Steps ### Step 1: Install Nodejs Install Nodejs if not already installed. You can download it from [here](https://nodejs.org/en/download/). ### Step 2: Install MCP CLI Install the AltimateAI MCP CLI globally using npm: ```bash npm install -g @altimateai/datamate ``` ### Step 3: Setup Configuration Input your API key and instance name into this JSON and save it as a config file. ```json { "connections": [], "settings": { "1": {} }, "datamate_id": "1", "altimateUrl": "https://api.myaltimate.com", "altimateInstanceName": "YOUR_INSTANCE_NAME", "altimateApiKey": "YOUR_API_KEY" } ``` Note To find your API Key and instance name: 1. Navigate to the Datamates website. 1. On the sidebar, click **settings**. 1. Click **API Key**. ### Step 4: Start MCP Server Run the following command in your terminal to start the MCP server: ```bash datamate start --datamate 1 --client claude-code --config-file ``` Command Breakdown Argument --config-file is optional and will be needed only if you are setting this datamate for the first time in your machines ## Verify Connection In your Claude Code session, run the following command to verify the connection and datamate mcp server should be listed with connected status. ```bash /mcp ``` ## Interactive Demo ______________________________________________________________________ **Related:** [Setup Overview](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md) # Setting Up Cline with Altimate MCP Connect Altimate MCP to Cline to use your AI assistant with MCP (Model Context Protocol) server capabilities. ## Configuration Steps ### Step 1: Install Extension in IDE 1. Open Extensions in your IDE (`Ctrl+Shift+X` or `Cmd+Shift+X`). 1. Search for "Datamates". 1. Find **Datamates by Altimate AI**. 1. Click **Install**. ### Step 2: Add Instance Name and API Key Configure your Altimate credentials in the Datamates extension: 1. Click **Select datamate** on the bottom of your IDE screen. 1. Click on the vertical ellipse on the top right of the Datamates menu. 1. Select **view credentials**. 1. Select your Datamates' plan: Either **Community, Pro, or Team Plan** or **Enterprise Plan**. 1. Enter your **Altimate Instance Name** (e.g., `mycompany`). 1. Enter your **Altimate API Key**. Note To find your API Key and instance name: 1. Navigate to the Datamates website. 1. On the sidebar, click **settings**. 1. Click **API Key**. ### Automatic Configuration Once the Datamates extension is installed and your credentials are set, the extension automatically configures Cline's MCP settings. No manual JSON editing is required. The extension writes a `datamate` entry to Cline's `cline_mcp_settings.json` using an environment variable (`${env:DATAMATES_URL}`) that resolves to the correct server URL per VS Code window. This means multi-window setups work automatically without any prompts or manual port management. ## Verify Connection After completing these steps: 1. The Datamates MCP server should appear in Cline's MCP server list. 1. You can verify the connection is working by checking Cline's MCP server status. Note If Cline was already running, you may need to reload the window (`Ctrl+Shift+P` / `Cmd+Shift+P` → "Developer: Reload Window") for the integration to take effect. ## Interactive Demo ______________________________________________________________________ **Related:** [Setup Overview](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md) # Setting Up Cursor with Altimate MCP Connect Altimate MCP to Cursor to use your AI assistant with MCP (Model Context Protocol) server capabilities. Note A Datamate needs to be created in the UI to start the process. ## Configuration Steps 1. Navigate and login to your Altimate AI instance. 1. Navigate to the Datamates menu by clicking **Datamates** on the sidebar. 1. Click **Configure Extension**. 1. Click **Cursor**. ## Verify Installation 1. Navigate to Cursor settings. 1. Click **Tools and MCP**. 1. Verify that you see **datamate** as an installed MCP Server. ## Configure Datamate 1. Click **Needs configuration**. 1. Click **New Connection**. 1. Input your connection information for that tool. 1. Click **Save Connection**. Note If your Altimate MCP uses dbt, you'll be prompted to install the Power User for dbt extension. ## Interactive Demo ______________________________________________________________________ **Related:** [Setup Overview](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md) # Setup Overview Get Altimate MCP running in your IDE. Choose your IDE below to get started! ## Choose Your IDE For Installation of the extension please refer to the following official links - [VSCode - Official Microsoft Marketplace](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) [Cursor or other VSCode Compatible Editors - Open VSX Registry](https://open-vsx.org/extension/altimateai/vscode-altimate-mcp-server) If you've created an Altimate API key from our [Power User for dbt Extension](https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user) you can use those credentials ## Interactive Guide Select your IDE to see setup instructions: - **[Cursor](https://help.altimate.ai/datamates/user-guide/setup/cursor-setup/index.md)** - Set up Altimate MCP in Cursor - **[Claude Code](https://help.altimate.ai/datamates/user-guide/setup/claude-code-setup/index.md)** - Set up Altimate MCP in Claude Code - **[Cline](https://help.altimate.ai/datamates/user-guide/setup/cline-setup/index.md)** - Set up Altimate MCP in Cline - **[VS Code](https://help.altimate.ai/datamates/user-guide/setup/vscode-setup/index.md)** - Set up Altimate MCP in Visual Studio Code Each guide includes all the steps you need to get Altimate MCP up and running in your preferred IDE. ## Install links - [Official VSCode Marketplace Link](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) - [Official VSX Registry](https://open-vsx.org/extension/altimateai/vscode-altimate-mcp-server) # Setting Up Altimate MCP in VS Code Get Altimate MCP running in VS Code with these quick setup steps. Note A Datamate needs to be created in the UI to start the process. ## Configuration Steps 1. Navigate and login to your Altimate AI instance. 1. Navigate to the Datamates menu by clicking **Datamates** on the sidebar. 1. Click **Configure Extension**. 1. Click **VS Code**. ## Configure Datamate 1. Click **Needs configuration**. 1. Click **New Connection**. 1. Input your connection information for that tool. 1. Click **Save Connection**. Note If your Altimate MCP uses dbt, you'll be prompted to install the Power User for dbt extension. ## Verify Installation 1. Look for the Datamates icon in your sidebar. 1. Try opening Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and type "Altimate MCP" - you should see Altimate MCP commands. **Restart VS Code if you don't see these** ## Interactive Demo ______________________________________________________________________ **Related:** [Setup Overview](https://help.altimate.ai/datamates/user-guide/setup/setup/index.md) # Altimate Lite for Snowflake # Altimate Lite for Snowflake Altimate Lite for Snowflake is a Native App running entirely inside your Snowflake account. No outbound calls, ever. Available on Snowflake Marketplace It's a Snowflake Native App you install straight from the Snowflake Marketplace, and it runs entirely inside your account. [View the listing on Snowflake Marketplace →](https://app.snowflake.com/marketplace/listing/GZTYZ1VSPRPWK/altimate-ai-altimate-lite-for-ai-and-warehouse-cost-optimization) ## After install and onboarding: turn on Auto Tune Auto Tune is a good starting point for saving costs and takes effect as soon as it is enabled. To enable it, open the **Warehouses** page and turn on the toggle for each eligible warehouse. Once enabled, Auto Tune continuously adjusts the warehouse to match actual usage: it suspends the warehouse when it goes idle and scales clusters down when demand drops. ## The main sections ### [Warehouses](https://help.altimate.ai/snowflake-native-app/warehouses/index.md) Lists each warehouse with its cost, savings from Auto Tune, and remaining potential savings. Auto Tune is enabled per warehouse from this page. ### [Auto-Tune Cost Savings](https://help.altimate.ai/snowflake-native-app/auto-tune-cost-savings/index.md) See how the cost savings are calculated. ### [AI Services](https://help.altimate.ai/snowflake-native-app/ai-services/index.md) See what you're spending on every Cortex AI feature, broken down by service, user, and model. ### [Data Ingestion](https://help.altimate.ai/snowflake-native-app/ingestion/index.md) Watch the sync that keeps everything current, or trigger a refresh yourself whenever you want the latest numbers. ## You stay in control The app only touches warehouses you explicitly opt in to from the Warehouses page. Auto Tune makes small, reversible adjustments on those warehouses and nothing else. Your data, queries, and roles are never touched. ## At a glance - **Data residency:** Stays inside your Snowflake account, in every region the listing is published in. - **Network egress:** None, zero outbound calls. - **Install time:** Under 5 minutes including the privilege approval. - **First value:** Turn on Auto Tune on an eligible warehouse and savings start accruing the same day, with no configuration and no schedule. - **Reversal:** A single `DROP APPLICATION` removes the app and all its state. Warehouses you opted in to keep whatever idle-timeout Auto Tune last set for them. ## Other Altimate products - [Altimate Code](/code/) — The open-source data engineering harness. - [Power User for dbt](/dbt-power-user/) — Best dbt extension for VS Code / Cursor. - [Altimate MCP](/datamates/) — A local-first MCP server for your data stack. - [Altimate Platform](https://altimate.ai/platform?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) — Enterprise cost optimization for [Snowflake](https://altimate.ai/use-cases/altimate-for-snowflake?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link) and [Databricks](https://altimate.ai/use-cases/altimate-for-databricks?utm_source=help-docs&utm_medium=referral&utm_campaign=docs-inline-link). # AI Services See what every Cortex AI feature is costing you, all in one place. See [The services](#the-services) below for what each one does. ## What you get ### Total AI cost Account-wide spend across every Cortex AI feature for the period you pick, in dollars where we can price it, credits otherwise. ### Token usage Total tokens consumed across token-metered AI functions. Output tokens typically cost several times more than input; the per-service breakdown shows the input/output split where Snowflake reports it. ### Adoption How many of the AI services this app tracks are actually in use in your account (e.g. "3 of 8"). ### Daily cost trend A day-by-day chart of spend, colored by which service it came from (AI SQL Functions, Cortex Analyst, Search, Agents, Intelligence, Code, or Fine-tuning), so you can see when usage spiked and which service drove it. ## The services - **[AI SQL Functions](https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql):** SQL functions that run LLM tasks (summarizing, translating, extracting, classifying) directly on your data. - **[Cortex Analyst](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-analyst):** Lets people ask questions in plain English and get back accurate answers, grounded in a semantic model of your data. - **[Cortex Search](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-overview):** Search over your own documents and unstructured data, built to hand an LLM accurate, up-to-date context. - **[Cortex Agents](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents):** An orchestrated agent that combines Cortex Analyst and Cortex Search to reason across both structured and unstructured data. - **[Snowflake Intelligence](https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-intelligence):** A natural-language interface for exploring your data: ask a question, get an answer or a chart, no dashboard needed. - **[Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code):** An AI coding assistant for writing and explaining SQL and Python inside Snowflake. - **[Fine-tuning](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-finetuning):** Customizes a base LLM on your own data for tasks a general-purpose model doesn't handle well out of the box. ## Three ways to slice it The **Services**, **Users**, and **Models** tabs each give you a ranked table for the selected time window: who or what is driving the spend, with a share-of-total column so you can see concentration at a glance. The **Service**, **User**, and **Model** filters at the top are searchable and combine: narrow to one service, one user, one model, or any mix of the three, and every number (the KPIs, the chart, all three tables) recalculates around that filter. **Export CSV** on any table downloads every matching row for the current filter, not just what's on screen. ## Drilling in Click any Service, User, or Model row and you get its own page: a daily spend chart scoped to exactly that slice, plus the full activity behind it. The Activity table's shape changes depending on what Snowflake actually reports for that service: **AI SQL Functions, Cortex Code, Agents, and Intelligence** show one row per call, with a **Query ID** (AI SQL Functions; click through to see the query text) or a **Request ID** (the rest, since these are AI requests, not Snowflake queries), plus the user, function, model, and tokens. **Cortex Analyst** doesn't expose individual queries: Snowflake only reports hourly request counts per user, so rows are summed to one per user for the selected window, with a **Requests** count instead of tokens. **Cortex Search** has no user or request id at all; rows are grouped by the named search service instead, with a **Tag** showing whether the credits were query-time (`SERVING`) or indexing-time (`EMBED_TEXT_TOKENS`). **Export CSV** on the Activity table (and every table on this page) downloads every matching row, not just what's currently on screen. ## Good to know Most Cortex AI features bill a separate "AI Credit" pool from your regular compute credits; Fine-tuning and Cortex Analyst are the exceptions, billing your regular compute credits instead. Dollar amounts show once a reliable rate is available for the relevant pool; otherwise the page shows credits. Hover the **Total AI Cost** info icon for the exact rate in use. **How the $/credit rate is set:** for the AI Credit pool, it's priced from your account's own invoiced AI spend when that history is available, otherwise Snowflake's published flat rate ($2.00/credit for global routing, $2.20/credit for regional). Regular compute credits (used for Fine-tuning and Cortex Analyst) are priced from your account's actual compute rate. Numbers refresh daily and backfill the last 30 days automatically on install; **Run now** on the Ingest page gets you the latest figures on demand. # Overview Altimate AI's Auto Tune agents automatically optimize your warehouse costs by dynamically adjusting key configurations based on real-time workload demands. Our system intelligently manages: - **Auto-suspend** – Automatically pauses idle warehouses to eliminate unnecessary costs - **Max cluster count** – Scales compute resources up or down to match query demand ## **High-Level Approach to Calculating Savings** ### Core Principles - **Conservative**: Underestimates when uncertain - **Transparent**: Provides min-max ranges reflecting real variability and overall confidence - **Auditable**: Every calculation traces to specific events - **Performance-Aware**: Accounts for potential speed/cost trade-offs Our savings calculation methodology based on whether Auto Tune is enabled: **1. Estimated Savings (Auto Tune Off)** For warehouses without Auto Tune enabled, we replay historical workloads to project potential savings: - Collect warehouse metrics from previous months - **Replay historical workloads** through our optimization model to determine what decisions it would have made - Compare our replayed optimization decisions against Snowflake's actual default behavior during that period - Calculate the estimated savings range based on the difference between optimized and actual events. **2. Realized Savings (Auto Tune On)** For warehouses with Auto Tune actively managing configurations: - Capture real-time metrics reflecting our optimization decisions - Estimate Snowflake's default behavior to establish a baseline - Compare actual optimized costs against the baseline scenario - Calculate the realized savings range achieved through optimization ______________________________________________________________________ # Warehouse Suspension **Purpose**: Reduces idle warehouse costs by intelligently predicting when warehouses can be safely suspended, eliminating wasted runtime between queries without impacting performance. ## Estimated Savings (**Auto Tune -** Off) 1. **Reconstruct warehouse timeline**: Map all query executions during active periods for every warehouse 1. **Determine eligible savings periods**: Replay the model across the timeline to identify when would Altimate would adjust and try to suspend the warehouse due to it being idle 1. **Calculate credits**: Calculate the time difference between where we would suspend to when snowflake suspended and that is the savings we have achieved. That would be converted to credits and cost based on the warehouse size and warehouse type. **Example** - **Warehouse:** Medium (4 credits/hr), 60-second auto-suspend - **Runtime:** Warehouse was on f**or** 6:00 AM – 6:10 AM - **Opportunity:** We detected that the warehouse would be idle at 6:09 AM (1 minute early) and would have suspended then. - **Savings:** 1 min ÷ 60 × 4 credits = **0.067 credits** ## **Realized Savings (Auto Tune - On)** 1. **Capture Auto Tune suspension event**: Record the exact timestamp when Altimate suspends the warehouse based on the model prediction 1. **Establish baseline comparison**: Determine when Snowflake's default auto-suspend would have triggered based on the configured threshold (e.g., 10-minute auto-suspend setting) 1. **Measure actual idle duration**: Track how long the warehouse remained suspended before the next query arrived 1. **Calculate actual savings window**: The savings window is the minimum of - 1. Time between Auto Tune suspension and default auto-suspend threshold, OR 1. Time between Auto Tune suspension and when the next query actually arrived This ensures we only count savings for idle time that was actually eliminated, capped by either the default auto_suspend or when the warehouse was restarted. 1. **Convert to credit savings**: Multiply the saved idle time by the warehouse's credit consumption rate (based on warehouse size and type) **Example 1: Full savings (no query interruption)** - **Warehouse:** Medium (4 credits/hr) with 10-minute default auto-suspend - **Auto Tune suspended at:** 10:00 AM - **Next query arrived at:** 10:15 AM - **Snowflake would have suspended at:** 10:10 AM - **Savings window:** 10 minutes (capped by default threshold) - **Credits saved:** 10 min ÷ 60 × 4 credits/hr = **0.67 credits** **Example 2: Partial savings (query arrives early)** - **Warehouse:** Medium (4 credits/hr) with 10-minute default auto-suspend - **Auto Tune suspended at:** 10:00 AM - **Next query arrived at:** 10:05 AM (warehouse resumes) - **Snowflake would have suspended at:** 10:10 AM (never reached) - **Savings window:** 5 minutes (capped by next query arrival) - **Credits saved:** 5 min ÷ 60 × 4 credits/hr = **0.33 credits** ______________________________________________________________________ # Warehouse Scaling **Purpose**: Optimizes cluster counts in multi-cluster warehouses by scaling down idle clusters more aggressively than Snowflake's native scaling policies, eliminating wasted compute spend during periods of reduced query demand. ## Estimated Savings (**Auto Tune - Off**) 1. **Reconstruct cluster utilization timeline**: Map all query executions and warehouse cluster timelines. 1. **Replay Auto Tune scaling logic**: Simulate when Altimate would have scaled down each cluster based on our optimization model 1. **Calculate savings window**: For each cluster's idle period, determine the actual time saved by comparing: 1. The savings window is the **minimum of these two durations** - we can only save time up until either work resumes - or time till the cluster was suspended by snowflake. 1. **Convert to credit savings range**: Multiply the saved idle time by each cluster's credit consumption rate (based on warehouse size and type), then sum across all clusters. Apply a 10% range to account for variability, providing minimum and maximum savings estimates. ## **Realized Savings (Auto Tune - On)** 1. **Capture Auto Tune scale-down event**: Record when Altimate scales down a cluster, noting the exact timestamp and which cluster was removed 1. **Measure time until next query**: Track the duration from scale-down until the next query arrives on that cluster (indicating capacity was needed again) 1. **Calculate credit savings range**: Both are capped by the time to next query because we can only save time until capacity is needed again. We calculate a savings range as we are unsure when snowflake would turn it off. Based on past documentation and observation - A Multi cluster warehouse would do 2-3 checks on 1 minute interval 1. **Minimum savings**: min(2 minutes, time to next query) 1. **Maximum savings:** min(3 minutes, time to next query) **Example 1: Next query arrives within the maximum threshold** - **Warehouse:** Large (8 credits/hr per cluster) - **Auto Tune scaled down at:** 10:00 AM (removed 1 cluster) - **Next query arrived at:** 10:02:30 AM (2.5 minutes later) - **Calculation:** - Minimum: MIN(2 min, 2.5 min) = 2 min - Maximum: MIN(3 min, 2.5 min) = 2.5 min - **Credits saved:** - Minimum: 2 min ÷ 60 × 8 credits/hr = **0.27 credits** - Maximum: 2.5 min ÷ 60 × 8 credits/hr = **0.33 credits** **Example 2: Next query arrives before minimum threshold** - **Warehouse:** Large (8 credits/hr per cluster) - **Auto Tune scaled down at:** 10:00 AM (removed 1 cluster) - **Next query arrived at:** 10:01:30 AM (1.5 minutes later) - **Calculation:** - Minimum: MIN(2 min, 1.5 min) = 1.5 min (capped by when query arrived) - Maximum: MIN(3 min, 1.5 min) = 1.5 min (also capped by when query arrived) - **Credits saved:** - Minimum: 1.5 min ÷ 60 × 8 credits/hr = **0.20 credits** - Maximum: 1.5 min ÷ 60 × 8 credits/hr = **0.20 credits** **Example 3: Next query arrives beyond maximum threshold** - **Warehouse:** Medium (4 credits/hr per cluster) - **Auto Tune scaled down at:** 2:00 PM (removed 1 cluster) - **Next query arrived at:** 2:05 PM (5 minutes later) - **Calculation:** - Minimum: MIN(2 min, 5 min) = 2 min (full minimum threshold) - Maximum: MIN(3 min, 5 min) = 3 min (full maximum threshold) - **Credits saved:** - Minimum: 2 min ÷ 60 × 4 credits/hr = **0.13 credits** - Maximum: 3 min ÷ 60 × 4 credits/hr = **0.20 credits** ______________________________________________________________________ # Total Annualized Potential Cost Savings We calculate your total potential annual autonomous savings by aggregating all optimization types (suspension and scaling) across your warehouses over a rolling 28-day period. For each warehouse on each day, we use estimated savings if Auto Tune was off (projected savings) or realized savings if Auto Tune was on (actual savings). These daily totals are summed to establish your 28-day baseline, which we then annualize by multiplying by 365 / 28. # FAQ ## Does data leave my Snowflake account? No. The app runs entirely inside your Snowflake account: auto tune, the web UI, every `ACCOUNT_USAGE` query, and every Cortex call. Zero outbound network calls. The one thing that reaches us is a small set of operational signals, shared through Snowflake's own Native App event sharing rather than any network call. Your queries and table contents are never part of it. See [Collected Telemetry](https://help.altimate.ai/snowflake-native-app/telemetry/index.md) for the full list. ## What does the app actually cost to run? Auto-tune and the web UI share one compute pool; the app's own warehouse (`NATIVE_APP_WH`) only spins up when the UI runs an `ACCOUNT_USAGE` query. Net savings comfortably outweigh that runtime cost. The first warehouse auto tune touches usually pays for the app many times over. ## How does auto tune decide which warehouses to touch? Only the ones you opt in to on the Warehouses page. Once opted in, it reacts within about a minute of that warehouse going idle. Flip the toggle off any time, no uninstall needed. ## What Snowflake editions are supported? **Standard** and above. Nothing requires Cortex to be enabled. AI Services simply has nothing to show if you're not using any Cortex AI features yet. ## Can I uninstall and reinstall later? Yes. `DROP APPLICATION` removes the app cleanly. Reinstalling restarts auto tune on whatever warehouses you re-opt in to. # Data Ingestion The Warehouses and AI Services pages are built from a copy of your Snowflake usage data, stored inside your account and refreshed on a schedule. The Data Ingestion page shows the status of those refreshes and lets you run one manually. ## What you get ### Next scheduled run A live countdown to the next automatic refresh, or a one-click way to turn scheduling on if it's off. ### Current status Whether a refresh is running right now, and the error if the last one failed. ### Run now Pull the latest numbers on demand instead of waiting for the next scheduled run. ### Run history The last 30 refreshes: when each one ran, whether it succeeded, how long it took, and the date window it covered. ## How it stays current A refresh runs automatically once a day. The first refresh happens the moment you install the app, pulling 30 days of history so the rest of the app has something to show right away; every refresh after that is incremental, pulling only what's changed since the last run. If scheduling is ever off, a banner at the top offers a one-click **Set up auto-refresh**. ## Running it yourself Click **Run now** any time you want the latest figures without waiting. The **Backfill** dropdown next to it controls how far back that one run reaches: - **Incremental** (default): the fast, normal option. Continues from the last successful run. - **Last 7 / 30 / 90 / 180 days**: forces a full re-pull of that many days, overwriting whatever was there. Use this if you suspect a gap, or want deeper history than the automatic 30-day backfill gave you. Only one refresh runs at a time; **Run now** is disabled while one is already in progress. ## Reading the run history Each row is one refresh: when it started, its status, how long it took, and the date window it covered. **Export CSV** downloads the full history, including what triggered each run (the initial install pull, a scheduled run, or a manual **Run now**) and how many rows it pulled, not just the 30 rows on screen. ## Good to know A failed run doesn't lose data: everything from the last successful run stays exactly as it was until the next refresh succeeds. The current-status banner only appears for states that need your attention (running, or failed with the error message); a normal successful refresh shows nothing there, since the run history and the rest of the app's numbers already speak for themselves. # Install Available on Snowflake Marketplace It's a Snowflake Native App you install straight from the Snowflake Marketplace, and it runs entirely inside your account. [View the listing on Snowflake Marketplace →](https://app.snowflake.com/marketplace/listing/GZTYZ1VSPRPWK/altimate-ai-altimate-lite-for-ai-and-warehouse-cost-optimization) ## Prerequisites - **Snowsight access** with the **ACCOUNTADMIN** role (required so you can grant the account-level privileges in step 2). - A Snowflake **Standard edition or higher** account. - No outbound network policy required: the app does not make external calls. ## 1. Get the app 1. Sign in to Snowsight as **ACCOUNTADMIN**. 1. In the left navigation, go to **Marketplace → Snowflake Marketplace**. 1. Type **Altimate AI** into the search bar and select the listing when it appears. 1. On the listing page, click **Get**. 1. Pick a warehouse to run the install with (any small warehouse works, since the app creates its own dedicated warehouse afterward), then click **Get** again to confirm. ## 2. Approve the requested privileges Snowsight will show you six privileges the app needs: `IMPORTED PRIVILEGES ON SNOWFLAKE DB`, `CREATE COMPUTE POOL`, `BIND SERVICE ENDPOINT`, `CREATE WAREHOUSE`, `MANAGE WAREHOUSES`, and the `SNOWFLAKE.CORTEX_USER` database role. Approve all six to continue. For a Snowflake Native App, approving the install dialog **is** the grant, so you don't need to run `GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER` manually. ## 3. Open the app 1. Go to **Apps → Altimate AI** in the Snowsight left nav. 1. The bundled launcher will appear. Click **Start app**. 1. When the URL appears, click **Open web app**. Snowflake signs you in with your existing Snowsight session, no separate password. ## 4. Onboard The web UI walks you through three short steps: 1. **Connect:** The app probes `ACCOUNT_USAGE` and confirms it can see your historical warehouse activity. 1. **Pick warehouses:** Flip auto tune on for each warehouse you want managed. 1. **Optional, open AI Services:** If you're using any Cortex AI features, see their spend and usage broken down by service, user, and model right away. ## Uninstall `DROP APPLICATION` from a Snowsight worksheet, or **Apps → Altimate AI → Manage → Uninstall** in the UI. Removes: - The application and the services it owns - The dedicated `NATIVE_APP_WH` warehouse - Every row of app state (savings logs, agent recommendations, auto tune events) It does **not** undo the idle-timeout changes Auto Tune made on the warehouses you opted in to. They keep running with whatever Auto Tune last set. # Privileges ## Account-level privileges - **`IMPORTED PRIVILEGES ON SNOWFLAKE DB`:** Read access to `SNOWFLAKE.ACCOUNT_USAGE` for cost analytics, query history, warehouse metering, and Cortex AI usage. - **`CREATE COMPUTE POOL`:** Runs auto tune and the in-app web UI, both in a single compute pool the app provisions itself. - **`BIND SERVICE ENDPOINT`:** Exposes the web UI's HTTPS endpoint so users in your account can reach the app from Apps → Altimate AI. - **`CREATE WAREHOUSE`:** Auto-creates a dedicated `NATIVE_APP_WH`, used exclusively by the web service for its own `ACCOUNT_USAGE` queries. - **`MANAGE WAREHOUSES`:** Reads each warehouse's settings and applies the `AUTO_SUSPEND` adjustment, only on warehouses you opt in to. ## Database role - **`SNOWFLAKE.CORTEX_USER`:** Lets the app call Snowflake Cortex LLM functions for its AI-driven capabilities. All calls stay in-account, billed against your existing Cortex credits. Approving the install dialog **is** the grant. No manual `GRANT DATABASE ROLE` step needed. # Support ## Reach us | Channel | Use for | | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | **info@altimate.ai** | Sales, billing, account & onboarding questions. | | **support@altimate.ai** | Bug reports, install issues, "auto tune isn't working on my warehouse." Include the warehouse name and the time window you're asking about. | | **[Snowflake Marketplace listing](https://app.snowflake.com/marketplace/providers/GZTYZ94Q7QA/Altimate%20AI)** | Marketplace-side issues: listing not visible in a region, trial period questions. | ## Support access Support access lets Altimate support run a diagnostic check inside your app instead of asking you to run commands and paste output. It is **off by default**, and every check is logged in your account. What a check can see Diagnostic statements run with the permissions the app already has and nothing more. That means Snowflake's own metadata views in the `SNOWFLAKE` database, such as `ACCOUNT_USAGE` for warehouse and cost history, plus the app's own objects. Your databases, schemas, and tables are not reachable, and no new access is granted or requested. ### Turn it on Run both steps as `ACCOUNTADMIN`. **Step 1. Find your app's name.** ```sql SHOW APPLICATIONS; ``` Each installed app is one row. Find the Altimate one and copy its `name`. Unless you renamed it at install, that is `ALTIMATE_LITE_FOR_AI_AND_WAREHOUSE_COST_OPTIMIZATION`. The `source` column shows the listing or package it came from, and `version` / `patch` show which build you are on. **Step 2. Grant permission**, using the name from step 1. ```sql ALTER APPLICATION ALTIMATE_LITE_FOR_AI_AND_WAREHOUSE_COST_OPTIMIZATION SET AUTHORIZE_RESTRICTED_PROVIDER_REMOTE_OPERATIONS_UNTIL = 'INDEFINITE'; ``` Let your support contact know once it is done. ### Turn it off ```sql ALTER APPLICATION ALTIMATE_LITE_FOR_AI_AND_WAREHOUSE_COST_OPTIMIZATION SET AUTHORIZE_RESTRICTED_PROVIDER_REMOTE_OPERATIONS_UNTIL = 'NEVER'; ``` New requests are blocked immediately. A request already running may finish. A common pattern is to switch it on when you open a ticket and off once it is closed. Both commands are safe to run as often as you like. ### Snowflake documentation - [Remote app operations](https://docs.snowflake.com/en/LIMITEDACCESS/developer-guide/native-apps/ui-consumer-remote-app-operation) — the consumer guide for the permission you are granting. - [ALTER APPLICATION](https://docs.snowflake.com/en/sql-reference/sql/alter-application) — command reference. - [SHOW APPLICATIONS](https://docs.snowflake.com/en/sql-reference/sql/show-applications) — listing the apps installed in your account. - [ACCOUNT_USAGE views](https://docs.snowflake.com/en/sql-reference/account-usage) — the metadata views a check can read. - [Event tables](https://docs.snowflake.com/en/developer-guide/logging-tracing/event-table-setting-up) — where the record of each check is written. - [About the Snowflake Native App Framework](https://docs.snowflake.com/en/developer-guide/native-apps/native-apps-about) — background on how apps run in your account. Questions? Reach out to us at [support@altimate.ai](mailto:support@altimate.ai) # Collected Telemetry Altimate AI Cost Intelligence runs entirely inside your own Snowflake account. This page covers the small set of operational signals the app shares back to us, the publisher, so we can support it and show you it's working. It also covers everything the app never shares. ## How telemetry leaves your account There is no Altimate AI server for the app to call. It uses Snowflake's own **Native App event sharing**: when you approve telemetry sharing at install, a short list of operational signals is written to an event table that Snowflake makes visible to us. Nothing goes anywhere else. ## What we collect | Signal | What it contains | Why we collect it | | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | | **App health** | An hourly "still running" ping. Status only. | Confirms your instance is alive so we can catch outages before you report them. | | **Auto Tune configuration** | Which warehouses have auto-suspend turned on or off, and when. | Shows feature adoption and lets us support your setup. | | **Auto Tune activity** | Daily counts of suspends and cluster-size reductions, plus estimated and realized credit and dollar savings. Account-wide totals, never per warehouse. | The core "did this save you money" metric. | | **Warehouse inventory** | Size, type, cluster count, and auto-suspend setting for each warehouse you've added to the app. | Helps us understand typical configurations and improve recommendations. | | **Resize recommendations** | When a resize is suggested, and whether it was applied. | Tracks whether the recommendations are actually useful. | | **Errors and failures** | What failed and roughly why, for example a permission gap on a specific Snowflake view. | Lets us fix problems, often before you notice them. | | **Billing events** *(metered listings only)* | The credits and dollars charged for a warehouse on a given day. | Lets us reconcile the charges we emit against Snowflake's own Marketplace billing records. | | **Blocked-account notices** *(Enterprise accounts only)* | A record that your account tried to enable or disable Auto Tune on a plan that doesn't include it. | Confirms the block worked. Fires only on that one action. | | **AI Teammate activity** | Which Teammate ran, whether it succeeded, and how many items it created. No warehouse or query content. | Basic usage and health signal for the AI features. | ## How identifiable any of this is Wherever a warehouse is involved, its name is one-way hashed before it leaves your account. We see that "a warehouse" was suspended, not which one. The single exception is the **blocked-account notice**, which includes your Snowflake account identifier. It fires only when an Enterprise account attempts an Auto Tune change its plan doesn't cover. ## What we never collect - Query text or query results - The contents of any table or database in your account - Raw `ACCOUNT_USAGE` rows. Only aggregate counts and credits derived from them - Per-action detail for individual suspends or cluster resizes. Only daily totals travel, the full history stays local to your account ## Your controls Telemetry sharing is a single consent you grant at install through Snowflake's own install flow. It isn't a separate Altimate AI setting. Uninstalling the app removes its schemas and stops all sharing immediately. Questions about your data Email **[info@altimate.ai](mailto:info@altimate.ai)** and we'll answer. # Warehouses Track every warehouse's cost and savings in one place, then turn on **Auto Tune** per warehouse to cut idle spend automatically. ## What you get ### Total cost Spend across every warehouse for the period you pick. ### Potential savings An annualized estimate of what Auto Tune could save across every warehouse, combining savings already captured with savings still on the table. ### Eligible warehouses How many warehouses could be tuned but aren't yet. ### Enabled warehouses How many warehouses have Auto Tune turned on right now. ## Turning on Auto Tune Every warehouse in the list has an **Auto Tune** toggle. Flip it on and Altimate continuously tunes that warehouse to real usage: it suspends the moment the warehouse goes idle and scales down clusters the instant demand drops, so spend always tracks actual workload instead of a static setting. Nothing else about the warehouse changes. Snowflake-managed warehouses (e.g. Adaptive Compute) aren't eligible. If the app doesn't yet have the grant it needs on a given warehouse, toggling it on shows the exact `GRANT MONITOR, MODIFY ON WAREHOUSE ...` statement to run. Copy it into a worksheet, run it as a role that can grant on that warehouse, then try the toggle again. ## Seeing your savings Each warehouse row shows either **"Saved $X"** (Auto Tune is on, money already captured) or **"Potential $X"** (Auto Tune is off, an estimate of what turning it on would save), each with an annualized figure underneath. **Export CSV** next to the search box downloads the full table. ## Reading the daily chart The Daily Spend & Savings chart (on the overview and again on every warehouse's detail page) stacks three colors per day: - **Yellow, Spend:** What that warehouse actually cost that day. - **Orange, Possible Savings:** Idle spend Auto Tune could still recover, on warehouses where it's off (or hasn't caught everything yet). - **Green, Auto Tune Savings:** Idle spend Auto Tune already recovered that day. A tall yellow bar with a big orange cap means real, uncaptured savings sitting on the table: a good candidate to turn Auto Tune on. A bar that's mostly green means Auto Tune is already doing its job there. ## The warehouse detail page Click any warehouse name for the full picture. - **Key Information:** The warehouse's real Snowflake settings (size, scaling policy, clusters, auto-resume, query acceleration) at a glance. - **Auto Tune:** The same toggle as the list. Once it's on, this warehouse is tuned to real usage continuously: suspended the moment it's idle, scaled down the instant demand drops, and shows **"Saved · last N days"** for the currently selected window. - **Realized Savings** vs. **Projected Savings:** Realized Savings is actual dollars recovered in the window you've selected; Projected Savings is always an annualized estimate, so the two use different time bases on purpose. One tells you what already happened, the other what a full year looks like at the current rate. - **Agent Decisions:** How often the tuning agent has acted on this warehouse over the window; spikes line up with the events below. Hover any point for the exact date and count. - **Auto Tune history:** A timestamped log of every decision: "Warehouse was suspended by Auto Tune" (idle → suspended), "Warehouse was scaled down by Auto Tune" (active cluster count reduced), "Resized from X to Y" (size changed), and "Auto Tune turned on/off" (you flipping the toggle). Filter it to one event type from the dropdown when you're trying to answer "did it ever scale this down?" instead of scrolling everything, and use **Export CSV** to pull the log into a spreadsheet. # Resources Resources # Cross-product references and operational guides. Spans Altimate Code, Power User for dbt, Altimate MCP and the Enterprise Platform. ### [LLM Gateway](/resources/llm-gateway/) Pricing, models and BYOK vs managed routing. ### [Security & Trust](/resources/security-trust/) SOC 2, local-first architecture and per-product security FAQs. ### [Pricing & Billing](/resources/pricing/) Plans, usage credits and gateway tiers. ### [Troubleshooting](/resources/troubleshooting/) Fixes and diagnostics across products. ### [Examples & Recipes](/resources/examples/) End-to-end walkthroughs. ### [Changelogs](/resources/changelog/) Release notes and version history. ### [Glossary](/resources/glossary/) Canonical product and term names. # Changelogs - [Altimate Code — Changelog](https://help.altimate.ai/code/reference/changelog/index.md) Power User for dbt ships through the VS Code Marketplace; Altimate MCP and the Enterprise Platform release notes are published in-product. This page will pull each product's release notes at build time once the changelog feeds are wired up. # Examples & Recipes End-to-end walkthroughs across the products. **Altimate MCP** (six full walkthroughs): - [Build, test, and document a dbt model from a Jira ticket](https://help.altimate.ai/datamates/examples/build-test-document-dbt-model/index.md) - [Find broken views in Snowflake](https://help.altimate.ai/datamates/examples/find-broken-views-snowflake/index.md) - [Optimize cost and performance](https://help.altimate.ai/datamates/examples/optimize-costs-and-performance/index.md) - [Migrate a PySpark project to dbt](https://help.altimate.ai/datamates/examples/migrate-pyspark-dbt/index.md) - [Debug an Airflow DAG](https://help.altimate.ai/datamates/examples/debug-airflow-dag/index.md) - [Write Snowflake UDFs](https://help.altimate.ai/datamates/examples/write-snowflake-udfs/index.md) **Altimate Code:** - [Showcase](https://help.altimate.ai/code/examples/index.md) # Glossary Canonical names for Altimate products and terms. Use these spellings everywhere. | Canonical name | What it is | Also seen as (avoid) | | ----------------------- | --------------------------------------------- | -------------------------------------------------------------------------- | | **Altimate Code** | Open-source data engineering harness / CLI | `altimate-code`, `altimate` (CLI), "the harness" | | **Power User for dbt** | VS Code / Cursor extension | "dbt Power User" (old name), DataPilot | | **Altimate MCP** | Local-first MCP server for IDEs | "Datamates" (old name), "Altimate Code Chat" (that is a feature inside it) | | **Enterprise Platform** | Snowflake / Databricks cost + governance SaaS | "Altimate Platform", "the platform", DataPilot (legacy) | | **LLM Gateway** | Managed multi-model routing | "Altimate LLM Gateway", "the gateway" | | **Studio** | Natural-language agent inside the Platform | "DataPilot Assist" (legacy) | **Terms** - **ADE-Bench** — agentic data engineering benchmark; Altimate Code ranks #1 (74.4%). - **BYOK** — bring your own key; use your own LLM provider credentials, free. - **Agent modes** — Builder (read/write), Analyst (read-only), Plan (minimal). - **Knowledge Hub / Memory Hub** — Altimate MCP components for context and recall. - **Data Contracts** — the Platform's CUE-based data quality and performance guardrails. # Altimate LLM Gateway Managed multi-model access at a flat rate. Skip managing API keys; the gateway routes each task to the best model and bills at 60-80% less than direct provider tokens. Bring-your-own-key (BYOK) stays free and unlimited. | Tier | Price | Tokens | Effective | | --------- | ------ | -------------- | ---------------------- | | Community | Free | 10M (one-time) | — | | Pro 1 | $29/mo | 20M | $1.45/M ($5/M overage) | | Pro 2 | $89/mo | 70M | $1.27/M ($3/M overage) | Example savings on 20M tokens: Opus-class direct ~$140 vs $29 (~79%); Sonnet-class ~$84 vs $29 (~65%). Prompts and responses are not retained. The gateway is used across the products: - In [Altimate Code](https://help.altimate.ai/code/configure/providers/index.md), as one of 35+ providers. - In [Power User for dbt](https://help.altimate.ai/dbt-power-user/arch/llm-gateway/index.md), with full pricing, models, and BYOK comparison. - In [Altimate MCP](https://help.altimate.ai/datamates/user-guide/components/llm-gateway/index.md), for IDE chat. > This page is the canonical summary. Product-specific setup lives in each product's docs above. Marketplace # Install our extensions Get Altimate extensions for VS Code, Cursor, and other compatible editors. Pick the registry your editor uses. **VS Code Marketplace** Visual Studio Code · Cursor · Windsurf [Power User for dbt Build, test, document and optimize dbt models 3x faster with AI teammates. Install](https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user) [Altimate MCP Server Local-first MCP server bringing your data stack into any AI-powered editor. Install](https://marketplace.visualstudio.com/items?itemName=altimateai.vscode-altimate-mcp-server) **Open VSX Registry** VSCodium · Gitpod · Theia · Eclipse Che [Power User for dbt The same extension on the open, vendor-neutral registry for Codium, Theia and more. Install](https://open-vsx.org/extension/innoverio/vscode-dbt-power-user) [Altimate MCP Server Local-first MCP server on the Open VSX registry for Codium, Theia and more. Install](https://open-vsx.org/extension/altimateai/vscode-altimate-mcp-server) **Snowflake Marketplace** Snowflake Native App · runs inside your account [Altimate Lite for Snowflake Cut Snowflake warehouse and AI costs with a Native App that installs in minutes and runs entirely inside your account. No data ever leaves. Get it on Snowflake](https://app.snowflake.com/marketplace/listing/GZTYZ1VSPRPWK/altimate-ai-altimate-lite-for-ai-and-warehouse-cost-optimization) # Pricing & Billing - [LLM Gateway tiers and savings](https://help.altimate.ai/resources/llm-gateway/index.md): flat-rate managed routing, 60-80% cheaper than direct provider tokens. BYOK is free and unlimited. - [Power User for dbt — Pricing FAQ](https://help.altimate.ai/dbt-power-user/arch/pricingfaq/index.md): credit costs per feature. - [Altimate MCP — Pricing FAQ](https://help.altimate.ai/datamates/faq/pricing-faqs/index.md): usage-based credits; integrations are free. The Enterprise Platform (Snowflake / Databricks cost intelligence) is priced per account with no per-seat fee; contact the team for an enterprise quote. # Security & Trust Altimate is SOC 2 Type II, uses a metadata-only / local-first architecture, and never trains models on customer data. Each product documents its own security model: - [Altimate Code — Security FAQ](https://help.altimate.ai/code/reference/security-faq/index.md): sandboxing, sensitive-write protection, telemetry, MCP hardening. - [Power User for dbt — Security FAQ](https://help.altimate.ai/dbt-power-user/arch/faq/index.md): local mode, what metadata is sent, SOC 2, retention. - [Altimate MCP — Security FAQ](https://help.altimate.ai/datamates/faq/security/index.md): local-first MCP, credential storage, PII guardrails. - [Enterprise Platform — Security FAQ](https://help.altimate.ai/platform/faq/security-faq/): data privacy, encryption, access control. Shared guarantees: TLS 1.3, AWS private VPC, IAM RBAC, MFA enforced, and a 30-day feedback retention window. # Troubleshooting - [Altimate Code — Troubleshooting](https://help.altimate.ai/code/reference/troubleshooting/index.md) - [Power User for dbt — Troubleshooting](https://help.altimate.ai/dbt-power-user/troubleshooting/index.md) - [Altimate MCP — Troubleshooting](https://help.altimate.ai/datamates/faq/troubleshooting/index.md) For Platform (Snowflake / Databricks) onboarding issues, see [Setup & Settings](https://help.altimate.ai/platform/setup/snowflake/) or contact support.